]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20111007 snapshot
authorChet Ramey <chet.ramey@case.edu>
Mon, 9 Jan 2012 13:29:54 +0000 (08:29 -0500)
committerChet Ramey <chet.ramey@case.edu>
Mon, 9 Jan 2012 13:29:54 +0000 (08:29 -0500)
36 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
MANIFEST
Makefile.in
Makefile.in~ [new file with mode: 0644]
assoc.c
assoc.h
builtins/common.c~ [new file with mode: 0644]
builtins/set.def~ [new file with mode: 0644]
doc/bash.1
doc/bash.1~
doc/bashref.texi
doc/bashref.texi~
doc/version.texi
doc/version.texi~
error.c~ [new file with mode: 0644]
flags.c
jobs.c
jobs.c~ [new file with mode: 0644]
lib/sh/Makefile.in
lib/sh/Makefile.in~ [new file with mode: 0644]
pathexp.c
pcomplete.c
pcomplete.c~
po/LINGUAS
po/LINGUAS~ [new file with mode: 0644]
po/it.po [new file with mode: 0644]
po/nl.po
print_cmd.c
tests/array.right
tests/array2.sub
tests/redir.right
tests/redir.tests
tests/redir10.sub [new file with mode: 0644]
variables.c
variables.c~ [new file with mode: 0644]

index 8a25a5116b0e64f66c7dec3a4aed1ab5e309dc43..c00ea942891caa256b567e4b494eaaacf950e415 100644 (file)
@@ -9148,7 +9148,7 @@ parse.y
                                   ----
 variables.c
        - fix bind_variable_internal to call a variable's dynamic 'set function'
-         with the right arguments depending on whether its an associative
+         with the right arguments depending on whether it's an associative
          array, an indexed array, or a scalar.  Fixes Ubuntu bug #471504
          https://bugs.launchpad.net/ubuntu/+source/bash/+bug/471504 reported
          by AJ Slater <aj.slater@gmail.com>
@@ -10383,7 +10383,7 @@ support/signames.c
 
 shell.c
        - instead of closing all fds 3-20 at shell startup, just set them to
-         be close-on-exec.  Report from Rainer Müller<raimue@macports.org>
+         be close-on-exec.  Report from Rainer Mülle <raimue@macports.org>
 
 lib/readline/isearch.c
        - in _rl_isearch_dispatch, if the current character maps to ISKMAP,
@@ -12287,3 +12287,58 @@ pcomplete.c
          Having it on causes readline to quote the matches as if they
          were filenames.  Adds functionality requested by many,
          including Clark Wang <dearvoid@gmail.com>
+
+assoc.[ch]
+       - assoc_replace: new function, takes the same arguments as
+         assoc_insert, but returns the old data instead of freeing it
+       - assoc_insert: if the object returned by hash_insert doesn't have
+         the same value for its key as the key passed as an argument, we
+         are overwriting an existing value.  In this case, we can free the
+         key.  Fixes bug reported by David Parks <davidparks21@yahoo.com>
+
+                                  10/5
+                                  ----
+print_cmd.c
+       - indirection_level_string: small change to only re-enable `x'
+         option after calling decode_prompt_string if it was on before.  In
+         normal mode, it will be, but John Reiser <jreiser@bitwagon.com>
+         has a novel use for that code in conjunction with a pre-loaded
+         shared library that traces system call usage in shell scripts
+
+                                  10/10
+                                  -----
+Makefile.in
+       - Fix from Mike Frysinger <vapier@gentoo.org> to avoid trying to
+         build y.tab.c and y.tab.h with two separate runs of yacc if
+         parse.y changes.  Problem with parallel makes
+       - Fix from Mike Frysinger <vapier@gentoo.org> to avoid subdirectory
+         builds each trying to make version.h (and all its dependencies)
+
+lib/sh/Makefile.in
+       - remove some dependencies on version.h where it doesn't make sense
+
+variables.c
+       - initialize_shell_variables: while reading the environment, a shell
+         running in posix mode now checks for SHELLOPTS being readonly (it
+         gets set early on in main()) before trying to assign to it.  It
+         saves an error message and the variable gets parsed as it should.
+         Fixes bug reported by Len Giambrone <Len.Giambrone@intersystems.com>
+
+                                  10/14
+                                  -----
+doc/{bash.1,bashref.texi}
+       - add to the "duplicating file descriptors" description that >&word
+         doesn't redirect stdout and stderr if word expands to `-'
+       - add to the "appending standard output and standard error"
+         description a note that >&word, where word is a number or `-',
+         causes other redirection operators to apply for sh and Posix
+         compatibility reasons.  Suggested by Greg Wooledge
+         <wooledg@eeg.ccf.org>
+
+                                  10/15
+                                  -----
+pcomplete.c
+       - change pcomp_filename_completion_function to only run the filename
+         dequoting function in the cases (as best as it can figure) where
+         readline won't do it via rl_filename_completion_function.  Based
+         on reports from <lolilolicon@gmail.com>
index 340794454428875c313ea08c8233b11e7c5523f7..3cd9be24ee8679b5841fa872f61906dfc7d948cd 100644 (file)
@@ -9148,7 +9148,7 @@ parse.y
                                   ----
 variables.c
        - fix bind_variable_internal to call a variable's dynamic 'set function'
-         with the right arguments depending on whether its an associative
+         with the right arguments depending on whether it's an associative
          array, an indexed array, or a scalar.  Fixes Ubuntu bug #471504
          https://bugs.launchpad.net/ubuntu/+source/bash/+bug/471504 reported
          by AJ Slater <aj.slater@gmail.com>
@@ -10383,7 +10383,7 @@ support/signames.c
 
 shell.c
        - instead of closing all fds 3-20 at shell startup, just set them to
-         be close-on-exec.  Report from Rainer Müller<raimue@macports.org>
+         be close-on-exec.  Report from Rainer Mülle <raimue@macports.org>
 
 lib/readline/isearch.c
        - in _rl_isearch_dispatch, if the current character maps to ISKMAP,
@@ -12285,4 +12285,52 @@ pcomplete.c
          rl_filename_completion_desired if it was off before we called
          rl_filename_completion_function and we didn't get any matches.
          Having it on causes readline to quote the matches as if they
-         were filenames.
+         were filenames.  Adds functionality requested by many,
+         including Clark Wang <dearvoid@gmail.com>
+
+assoc.[ch]
+       - assoc_replace: new function, takes the same arguments as
+         assoc_insert, but returns the old data instead of freeing it
+       - assoc_insert: if the object returned by hash_insert doesn't have
+         the same value for its key as the key passed as an argument, we
+         are overwriting an existing value.  In this case, we can free the
+         key.  Fixes bug reported by David Parks <davidparks21@yahoo.com>
+
+                                  10/5
+                                  ----
+print_cmd.c
+       - indirection_level_string: small change to only re-enable `x'
+         option after calling decode_prompt_string if it was on before.  In
+         normal mode, it will be, but John Reiser <jreiser@bitwagon.com>
+         has a novel use for that code in conjunction with a pre-loaded
+         shared library that traces system call usage in shell scripts
+
+                                  10/10
+                                  -----
+Makefile.in
+       - Fix from Mike Frysinger <vapier@gentoo.org> to avoid trying to
+         build y.tab.c and y.tab.h with two separate runs of yacc if
+         parse.y changes.  Problem with parallel makes
+       - Fix from Mike Frysinger <vapier@gentoo.org> to avoid subdirectory
+         builds each trying to make version.h (and all its dependencies)
+
+lib/sh/Makefile.in
+       - remove some dependencies on version.h where it doesn't make sense
+
+variables.c
+       - initialize_shell_variables: while reading the environment, a shell
+         running in posix mode now checks for SHELLOPTS being readonly (it
+         gets set early on in main()) before trying to assign to it.  It
+         saves an error message and the variable gets parsed as it should.
+         Fixes bug reported by Len Giambrone <Len.Giambrone@intersystems.com>
+
+                                  10/14
+                                  -----
+doc/{bash.1,bashref.texi}
+       - add to the "duplicating file descriptors" description that >&word
+         doesn't redirect stdout and stderr if word expands to `-'
+       - add to the "appending standard output and standard error"
+         description a note that >&word, where word is a number or `-',
+         causes other redirection operators to apply for sh and Posix
+         compatibility reasons.  Suggested by Greg Wooledge
+         <wooledg@eeg.ccf.org>
index 878b76263a0f35a9e8bc74a811fcf22101bf2e99..2e2163b9b3100dec2be7d34a4c2d78e64f5508a2 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1005,6 +1005,7 @@ tests/redir6.sub  f
 tests/redir7.sub       f
 tests/redir8.sub       f
 tests/redir9.sub       f
+tests/redir10.sub      f
 tests/rhs-exp.tests    f
 tests/rhs-exp.right    f
 tests/rhs-exp1.sub     f
index ad57b27a99d8eb9a92db151954ed9b343a263aa4..b5a2193c293eb4280a37fa69a55baac2f92597cd 100644 (file)
@@ -1,6 +1,6 @@
-# Makefile for bash-4.2, version 4.5
+# Makefile for bash-4.2, version 4.6
 #
-# Copyright (C) 1996-2010 Free Software Foundation, Inc.
+# Copyright (C) 1996-2011 Free Software Foundation, Inc.
 
 #   This program is free software: you can redistribute it and/or modify
 #   it under the terms of the GNU General Public License as published by
@@ -579,23 +579,27 @@ buildversion.o: version.h conftypes.h patchlevel.h $(srcdir)/version.c
 
 # old rules
 GRAM_H = parser-built
-y.tab.o: y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h
+y.tab.o: y.tab.h y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h
 ${GRAM_H}:     y.tab.h
        @-if test -f y.tab.h ; then \
                cmp -s $@ y.tab.h 2>/dev/null || cp -p y.tab.h $@; \
        fi
-y.tab.c y.tab.h: parse.y
+
+y.tab.c: parse.y
 #      -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
        $(YACC) -d $(srcdir)/parse.y
        touch parser-built
 #      -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; else cp -p y.tab.h ${GRAM_H}; fi
 
-# experimental new rules - work with GNU make but not BSD (or OSF) make
-#y.tab.o: y.tab.c y.tab.h
-#y.tab.c y.tab.h: parse.y command.h ${BASHINCDIR}/stdc.h input.h
-#      -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
-#      $(YACC) -d $(srcdir)/parse.y
-#      -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; fi
+y.tab.h: y.tab.c
+       @true
+
+# Subdirs will often times want version.h, so they'll change back up to
+# the top level and try to create it.  This causes parallel build issues
+# so just force top level sanity before we descend.
+$(LIBDEP): .build
+#$(LIBDEP): version.h
 
 $(READLINE_LIBRARY): config.h $(READLINE_SOURCE)
        @echo making $@ in ${RL_LIBDIR}
diff --git a/Makefile.in~ b/Makefile.in~
new file mode 100644 (file)
index 0000000..20c2d19
--- /dev/null
@@ -0,0 +1,1534 @@
+# Makefile for bash-4.2, version 4.6
+#
+# Copyright (C) 1996-2011 Free Software Foundation, Inc.
+
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Make sure the first target in the makefile is the right one
+all: .made
+
+PACKAGE = @PACKAGE_NAME@
+VERSION = @PACKAGE_VERSION@
+
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+# Include some boilerplate Gnu makefile definitions.
+prefix = @prefix@
+
+exec_prefix = @exec_prefix@
+
+datarootdir = @datarootdir@
+
+bindir = @bindir@
+libdir = @libdir@
+infodir = @infodir@
+includedir = @includedir@
+datadir = @datadir@
+localedir = @localedir@
+
+mandir = @mandir@
+manpfx = man
+
+man1ext = .1
+man1dir = $(mandir)/$(manpfx)1
+man3ext = .3
+man3dir = $(mandir)/$(manpfx)3
+
+htmldir = @htmldir@
+
+# Support an alternate destination root directory for package building
+DESTDIR =
+
+topdir = @top_srcdir@
+BUILD_DIR = @BUILD_DIR@
+top_builddir = @BUILD_DIR@
+srcdir = @srcdir@
+VPATH = .:@srcdir@
+
+@SET_MAKE@
+CC = @CC@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+YACC = @YACC@
+SHELL = @MAKE_SHELL@
+CP = cp
+RM = rm -f
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RANLIB = @RANLIB@
+SIZE = @SIZE@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALLMODE= -m 0755
+INSTALLMODE2 = -m 0555
+
+TESTSCRIPT = @TESTSCRIPT@
+
+DEBUGGER_START_FILE = @DEBUGGER_START_FILE@
+
+#If you have purify, and want to use it, uncomment this definition or
+# run the make as `make PURIFY=purify'
+# or run configure with the --with-purify argument.
+PURIFY = @PURIFY@
+
+# Here is a rule for making .o files from .c files that does not
+# force the type of the machine (like -M_MACHINE) into the flags.
+.c.o:
+       $(RM) $@
+       $(CC) $(CCFLAGS) -c $<
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+
+# The name of this program and some version information.
+VERSPROG = bashversion$(EXEEXT)
+VERSOBJ = bashversion.$(OBJEXT)
+
+Program = bash$(EXEEXT)
+Version = @BASHVERS@
+PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
+RELSTATUS = @RELSTATUS@
+
+Machine = @host_cpu@
+OS = @host_os@
+VENDOR = @host_vendor@
+MACHTYPE = @host@
+
+# comment out for release
+DEBUG = @DEBUG@
+MALLOC_DEBUG = @MALLOC_DEBUG@
+
+THIS_SH = $(BUILD_DIR)/$(Program)
+
+# PROFILE_FLAGS is either -pg, to generate profiling info for use
+# with gprof, or nothing (the default).
+PROFILE_FLAGS= @PROFILE_FLAGS@
+
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @CROSS_COMPILE@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG} ${MALLOC_DEBUG}
+DEFS = @DEFS@
+LOCAL_DEFS = @LOCAL_DEFS@
+
+LOCALE_DEFS = -DLOCALEDIR='"$(localedir)"' -DPACKAGE='"$(PACKAGE)"'
+
+LOCAL_LIBS = @LOCAL_LIBS@
+LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@
+LIBS_FOR_BUILD = 
+
+STATIC_LD = @STATIC_LD@
+LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
+
+SYSTEM_FLAGS = -DPROGRAM='"$(Program)"' -DCONF_HOSTTYPE='"$(Machine)"' -DCONF_OSTYPE='"$(OS)"' -DCONF_MACHTYPE='"$(MACHTYPE)"' -DCONF_VENDOR='"$(VENDOR)"' $(LOCALE_DEFS)
+
+BASE_CCFLAGS = $(PROFILE_FLAGS) $(SYSTEM_FLAGS) $(LOCAL_DEFS) \
+         $(DEFS) $(LOCAL_CFLAGS) $(INCLUDES)
+
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
+
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
+
+LDFLAGS = @LDFLAGS@ $(STATIC_LD) $(LOCAL_LDFLAGS) $(PROFILE_FLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ $(LOCAL_LDFLAGS) $(CFLAGS_FOR_BUILD)
+
+INCLUDES = -I. @RL_INCLUDE@ -I$(srcdir) -I$(BASHINCDIR) -I$(LIBSRC) $(INTL_INC)
+
+# Maybe add: -Wextra
+GCC_LINT_FLAGS = -O -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wno-parentheses \
+                -Wcast-align -Wstrict-prototypes -Wconversion -Wformat \
+                -Wformat-nonliteral -Wmissing-braces -Wuninitialized \
+                -Wmissing-declarations  -Winline \
+                -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
+
+GCC_LINT_CFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(GCC_LINT_FLAGS)
+
+#
+# Support libraries
+# 
+
+dot = .
+
+LIBSUBDIR = lib
+LIBSRC = $(srcdir)/$(LIBSUBDIR)
+
+LIBBUILD = ${BUILD_DIR}/${LIBSUBDIR}
+
+SUBDIR_INCLUDES = -I. @RL_INCLUDE@ -I$(topdir) -I$(topdir)/$(LIBSUBDIR)
+
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+
+# the bash library
+# the library is a mix of functions that the C library does not provide on
+# some platforms and general shell utility functions
+SH_LIBSRC = $(LIBSRC)/sh
+SH_LIBDIR = $(dot)/${LIBSUBDIR}/sh
+SH_ABSSRC = ${topdir}/${SH_LIBSRC}
+
+SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
+               ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \
+               ${SH_LIBSRC}/setlinebuf.c ${SH_LIBSRC}/strchrnul.c \
+               ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strerror.c \
+               ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \
+               ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \
+               ${SH_LIBSRC}/itos.c ${SH_LIBSRC}/rename.c \
+               ${SH_LIBSRC}/zread.c ${SH_LIBSRC}/zwrite.c \
+               ${SH_LIBSRC}/shtty.c ${SH_LIBSRC}/inet_aton.c \
+               ${SH_LIBSRC}/netopen.c ${SH_LIBSRC}/strpbrk.c \
+               ${SH_LIBSRC}/timeval.c ${SH_LIBSRC}/clock.c \
+               ${SH_LIBSRC}/makepath.c ${SH_LIBSRC}/pathcanon.c \
+               ${SH_LIBSRC}/pathphys.c ${SH_LIBSRC}/stringlist.c \
+               ${SH_LIBSRC}/stringvec.c ${SH_LIBSRC}/tmpfile.c \
+               ${SH_LIBSRC}/spell.c ${SH_LIBSRC}/strtrans.c \
+               ${SH_LIBSRC}/strcasestr.c ${SH_LIBSRC}/shquote.c \
+               ${SH_LIBSRC}/snprintf.c ${SH_LIBSRC}/mailstat.c \
+               ${SH_LIBSRC}/fmtulong.c ${SH_LIBSRC}/fmtullong.c \
+               ${SH_LIBSRC}/strtoll.c ${SH_LIBSRC}/strtoull.c \
+               ${SH_LIBSRC}/strtoimax.c ${SH_LIBSRC}/strtoumax.c \
+               ${SH_LIBSRC}/fmtumax.c ${SH_LIBSRC}/netconn.c \
+               ${SH_LIBSRC}/mktime.c ${SH_LIBSRC}/strftime.c \
+               ${SH_LIBSRC}/memset.c ${SH_LIBSRC}/mbschr.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}/zmapfd.c ${SH_LIBSRC}/fpurge.c \
+               ${SH_LIBSRC}/zgetline.c ${SH_LIBSRC}/mbscmp.c \
+               ${SH_LIBSRC}/casemod.c ${SH_LIBSRC}/uconvert.c \
+               ${SH_LIBSRC}/ufuncs.c ${SH_LIBSRC}/dprintf.c \
+               ${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \
+               ${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \
+               ${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/shmbchar.c
+
+SHLIB_LIB = -lsh
+SHLIB_LIBNAME = libsh.a
+SHLIB_LIBRARY = ${SH_LIBDIR}/${SHLIB_LIBNAME}
+SHLIB_LDFLAGS = -L${SH_LIBDIR}
+SHLIB_DEP = ${SHLIB_LIBRARY}
+
+# we assume for now that readline source is being shipped with bash
+RL_LIBSRC = $(LIBSRC)/readline
+RL_LIBDOC = $(RL_LIBSRC)/doc
+RL_LIBDIR = @RL_LIBDIR@
+RL_ABSSRC = ${topdir}/$(RL_LIBDIR)
+
+RL_INCLUDEDIR = @RL_INCLUDEDIR@
+
+READLINE_LIB = @READLINE_LIB@
+READLINE_LIBRARY = $(RL_LIBDIR)/libreadline.a
+READLINE_LDFLAGS = -L${RL_LIBDIR}
+READLINE_DEP = @READLINE_DEP@
+
+# The source, object and documentation of the GNU Readline library.
+READLINE_SOURCE        = $(RL_LIBSRC)/rldefs.h $(RL_LIBSRC)/rlconf.h \
+                 $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/tcap.h \
+                 $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/keymaps.h \
+                 $(RL_LIBSRC)/history.h $(RL_LIBSRC)/histlib.h \
+                 $(RL_LIBSRC)/posixstat.h $(RL_LIBSRC)/tilde.h \
+                 $(RL_LIBSRC)/rlstdc.h ${RL_LIBSRC}/xmalloc.h \
+                 $(RL_LIBSRC)/rlshell.h ${RL_LIBSRC}/rlprivate.h \
+                 $(RL_LIBSRC)/funmap.c $(RL_LIBSRC)/emacs_keymap.c \
+                 $(RL_LIBSRC)/search.c $(RL_LIBSRC)/vi_keymap.c \
+                 $(RL_LIBSRC)/keymaps.c $(RL_LIBSRC)/parens.c \
+                 $(RL_LIBSRC)/vi_mode.c $(RL_LIBSRC)/callback.c \
+                 $(RL_LIBSRC)/readline.c $(RL_LIBSRC)/tilde.c \
+                 $(RL_LIBSRC)/rltty.c $(RL_LIBSRC)/complete.c \
+                 $(RL_LIBSRC)/bind.c $(RL_LIBSRC)/isearch.c \
+                 $(RL_LIBSRC)/display.c $(RL_LIBSRC)/signals.c \
+                 $(RL_LIBSRC)/util.c $(RL_LIBSRC)/kill.c $(RL_LIBSRC)/text.c \
+                 $(RL_LIBSRC)/undo.c $(RL_LIBSRC)/macro.c \
+                 $(RL_LIBSRC)/terminal.c $(RL_LIBSRC)/nls.c \
+                 $(RL_LIBSRC)/input.c $(RL_LIBSRC)/xmalloc.c \
+                 $(RL_LIBSRC)/shell.c $(RL_LIBSRC)/savestring.c \
+                 $(RL_LIBSRC)/misc.c $(RL_LIBSRC)/mbutil.c $(RL_LIBSRC)/compat.c \
+                 $(RL_LIBSRC)/histexpand.c $(RL_LIBSRC)/history.c \
+                 $(RL_LIBSRC)/histsearch.c $(RL_LIBSRC)/histfile.c
+
+READLINE_OBJ   = $(RL_LIBDIR)/readline.o $(RL_LIBDIR)/funmap.o \
+                 $(RL_LIBDIR)/parens.o $(RL_LIBDIR)/search.o \
+                 $(RL_LIBDIR)/keymaps.o $(RL_LIBDIR)/xmalloc.o \
+                 $(RL_LIBDIR)/rltty.o $(RL_LIBDIR)/complete.o \
+                 $(RL_LIBDIR)/bind.o $(RL_LIBDIR)/isearch.o \
+                 $(RL_LIBDIR)/display.o $(RL_LIBDIR)/signals.o \
+                 $(RL_LIBDIR)/tilde.o $(RL_LIBDIR)/util.o \
+                 $(RL_LIBDIR)/kill.o $(RL_LIBDIR)/undo.o $(RL_LIBDIR)/nls.o \
+                 $(RL_LIBDIR)/macro.o $(RL_LIBDIR)/input.o \
+                 $(RL_LIBDIR)/terminal.o $(RL_LIBDIR)/callback.o \
+                 $(RL_LIBDIR)/shell.o $(RL_LIBDIR)/savestring.o \
+                 $(RL_LIBDIR)/mbutil.o $(RL_LIBDIR)/compat.o \
+                 $(RL_LIBDIR)/history.o $(RL_LIBDIR)/histexpand.o \
+                 $(RL_LIBDIR)/histsearch.o $(RL_LIBDIR)/histfile.o
+
+HIST_LIBSRC = $(LIBSRC)/readline
+HIST_LIBDIR = @HIST_LIBDIR@
+HIST_ABSSRC = ${topdir}/$(HIST_LIBDIR)
+
+HISTORY_LIB = @HISTORY_LIB@
+HISTORY_LIBRARY = $(HIST_LIBDIR)/libhistory.a
+HISTORY_LDFLAGS = -L$(HIST_LIBDIR)
+HISTORY_DEP = @HISTORY_DEP@
+
+# The source, object and documentation of the history library.
+HISTORY_SOURCE = $(HIST_LIBSRC)/history.c $(HIST_LIBSRC)/histexpand.c \
+                 $(HIST_LIBSRC)/histsearch.c $(HIST_LIBSRC)/histfile.c \
+                 $(HIST_LIBSRC)/shell.c \
+                 $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/histlib.h
+HISTORY_OBJ    = $(HIST_LIBDIR)/history.o $(HIST_LIBDIR)/histexpand.o \
+                 $(HIST_LIBDIR)/histsearch.o $(HIST_LIBDIR)/histfile.o \
+                 $(HIST_LIBDIR)/shell.o
+
+# You only need termcap (or curses) if you are linking with GNU Readline.
+TERM_LIBSRC = $(LIBSRC)/termcap
+TERM_LIBDIR = $(dot)/$(LIBSUBDIR)/termcap
+TERM_ABSSRC = ${topdir}/$(TERM_LIBDIR)
+
+TERMCAP_LIB = @TERMCAP_LIB@
+TERMCAP_LIBRARY = $(TERM_LIBDIR)/libtermcap.a
+TERMCAP_LDFLAGS = -L$(TERM_LIBDIR)
+TERMCAP_DEP = @TERMCAP_DEP@
+
+TERMCAP_SOURCE = $(TERM_LIBSRC)/termcap.c $(TERM_LIBSRC)/tparam.c
+TERMCAP_OBJ    = $(TERM_LIBDIR)/termcap.o $(TERM_LIBDIR)/tparam.o
+
+GLOB_LIBSRC = $(LIBSRC)/glob
+GLOB_LIBDIR = $(dot)/$(LIBSUBDIR)/glob
+GLOB_ABSSRC = ${topdir}/$(GLOB_LIBDIR)
+
+GLOB_LIB     = -lglob
+GLOB_LIBRARY = $(GLOB_LIBDIR)/libglob.a
+GLOB_LDFLAGS = -L$(GLOB_LIBDIR)
+GLOB_DEP = $(GLOB_LIBRARY)
+
+GLOB_SOURCE = $(GLOB_LIBSRC)/glob.c $(GLOB_LIBSRC)/strmatch.c \
+             $(GLOB_LIBSRC)/smatch.c $(GLOB_LIBSRC)/xmbsrtowcs.c \
+             $(GLOB_LIBSRC)/glob_loop.c $(GLOB_LIBSRC)/sm_loop.c \
+             $(GLOB_LIBSRC)/gmisc.c \
+             $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+GLOB_OBJ    = $(GLOB_LIBDIR)/glob.o $(GLOB_LIBDIR)/strmatch.o \
+             $(GLOB_LIBDIR)/smatch.o $(GLOB_LIBDIR)/xmbsrtowcs.o \
+             $(GLOB_LIBDIR)/gmisc.o
+
+# The source, object and documentation for the GNU Tilde library.
+TILDE_LIBSRC = $(LIBSRC)/tilde
+TILDE_LIBDIR = $(dot)/$(LIBSUBDIR)/tilde
+TILDE_ABSSRC = ${topdir}/$(TILDE_LIBDIR)
+
+TILDE_LIB = @TILDE_LIB@
+TILDE_LIBRARY = $(TILDE_LIBDIR)/libtilde.a
+TILDE_LDFLAGS = -L$(TILDE_LIBDIR)
+TILDE_DEP = $(TILDE_LIBRARY)
+
+TILDE_SOURCE   = $(TILDE_LIBSRC)/tilde.c $(TILDE_LIBSRC)/tilde.h
+TILDE_OBJ      = $(TILDE_LIBDIR)/tilde.o
+
+# libintl
+INTL_LIBSRC = $(LIBSRC)/intl
+INTL_LIBDIR = $(dot)/$(LIBSUBDIR)/intl
+INTL_ABSSRC = ${topdir}/$(INTL_LIB)
+INTL_BUILDDIR = ${LIBBUILD}/intl
+
+INTL_LIB     = @LIBINTL@
+INTL_LIBRARY = $(INTL_LIBDIR)/libintl.a
+INTL_DEP = @INTL_DEP@
+INTL_INC = @INTL_INC@
+
+LIBINTL_H = @LIBINTL_H@
+
+# libiconv
+LIBICONV = @LIBICONV@
+
+# tests
+LIBINTL = @LIBINTL@
+LTLIBINTL = @LTLIBINTL@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+
+# Our malloc.
+MALLOC_TARGET = @MALLOC_TARGET@
+
+# set to alloca.o if we are using the C alloca in lib/malloc
+ALLOCA = @ALLOCA@
+
+ALLOC_LIBSRC = $(LIBSRC)/malloc
+ALLOC_LIBDIR = $(dot)/$(LIBSUBDIR)/malloc
+ALLOC_ABSSRC = ${topdir}/$(ALLOC_LIBDIR)
+
+MALLOC_SRC = @MALLOC_SRC@
+MALLOC_OTHERSRC = ${ALLOC_LIBSRC}/trace.c ${ALLOC_LIBSRC}/stats.c \
+                 ${ALLOC_LIBSRC}/table.c ${ALLOC_LIBSRC}/watch.c
+MALLOC_SOURCE = ${ALLOC_LIBSRC}/${MALLOC_SRC} ${MALLOC_OTHERSRC}
+MALLOC_CFLAGS = -DRCHECK -Dbotch=programming_error ${MALLOC_DEBUG}
+
+MALLOC_LIB     = @MALLOC_LIB@
+MALLOC_LIBRARY = @MALLOC_LIBRARY@
+MALLOC_LDFLAGS = @MALLOC_LDFLAGS@
+MALLOC_DEP = @MALLOC_DEP@
+
+ALLOC_HEADERS = $(ALLOC_LIBSRC)/getpagesize.h $(ALLOC_LIBSRC)/shmalloc.h \
+               $(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h \
+               $(ALLOC_LIBSRC)/table.h $(ALLOC_LIBSRC)/watch.h
+
+$(MALLOC_LIBRARY):     ${MALLOC_SOURCE} ${ALLOC_HEADERS} config.h
+               @(cd $(ALLOC_LIBDIR) && \
+                $(MAKE) $(MFLAGS) \
+                MALLOC_CFLAGS="$(MALLOC_CFLAGS)" ${MALLOC_TARGET} ) || exit 1
+
+BASHINCDIR = ${srcdir}/include
+BASHINCFILES =  $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \
+                $(BASHINCDIR)/filecntl.h $(BASHINCDIR)/posixdir.h \
+                $(BASHINCDIR)/memalloc.h $(BASHINCDIR)/stdc.h \
+                $(BASHINCDIR)/posixjmp.h $(BASHINCDIR)/posixwait.h \
+                $(BASHINCDIR)/posixtime.h $(BASHINCDIR)/systimes.h \
+                $(BASHINCDIR)/unionwait.h $(BASHINCDIR)/maxpath.h \
+                $(BASHINCDIR)/shtty.h $(BASHINCDIR)/typemax.h \
+                $(BASHINCDIR)/ocache.h
+
+LIBRARIES = $(GLOB_LIB) $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) \
+           $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LIBICONV) $(LOCAL_LIBS)
+
+LIBDEP = $(GLOB_DEP) $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) \
+        $(TILDE_DEP) $(MALLOC_DEP)
+
+LIBRARY_LDFLAGS = $(READLINE_LDFLAGS) $(HISTORY_LDFLAGS) $(GLOB_LDFLAGS) \
+                 $(TILDE_LDFLAGS) $(MALLOC_LDFLAGS) $(SHLIB_LDFLAGS)
+
+#
+# The shell itself
+#
+
+# The main source code for the Bourne Again SHell.
+CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \
+          dispose_cmd.c execute_cmd.c variables.c $(GLOBC) version.c \
+          expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \
+          test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \
+          input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \
+          unwind_prot.c siglist.c bashline.c bracecomp.c error.c \
+          list.c stringlib.c locale.c findcmd.c redir.c \
+          pcomplete.c pcomplib.c syntax.c xmalloc.c
+
+HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \
+          general.h variables.h config.h $(ALLOC_HEADERS) alias.h \
+          quit.h unwind_prot.h syntax.h ${GRAM_H} \
+          command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \
+          subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \
+          array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \
+          execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h \
+          $(BASHINCFILES)
+
+SOURCES         = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS)
+
+# header files chosen based on running of configure
+SIGNAMES_H = @SIGNAMES_H@
+
+# object files chosen based on running of configure
+JOBS_O = @JOBS_O@
+SIGLIST_O = @SIGLIST_O@
+SIGNAMES_O = @SIGNAMES_O@
+
+# Matching object files.
+OBJECTS         = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
+          dispose_cmd.o execute_cmd.o variables.o copy_cmd.o error.o \
+          expr.o flags.o $(JOBS_O) subst.o hashcmd.o hashlib.o mailcheck.o \
+          trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \
+          alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \
+          bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \
+          pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O)
+
+# Where the source code of the shell builtins resides.
+BUILTIN_SRCDIR=$(srcdir)/builtins
+DEFSRC=$(BUILTIN_SRCDIR)
+BUILTIN_ABSSRC=${topdir}/builtins
+DEFDIR = $(dot)/builtins
+DEBUGGER_DIR = $(dot)/debugger
+
+BUILTIN_DEFS = $(DEFSRC)/alias.def $(DEFSRC)/bind.def $(DEFSRC)/break.def \
+              $(DEFSRC)/builtin.def $(DEFSRC)/cd.def $(DEFSRC)/colon.def \
+              $(DEFSRC)/command.def ${DEFSRC}/complete.def \
+              $(DEFSRC)/caller.def $(DEFSRC)/declare.def \
+              $(DEFSRC)/echo.def $(DEFSRC)/enable.def $(DEFSRC)/eval.def \
+              $(DEFSRC)/exec.def $(DEFSRC)/exit.def $(DEFSRC)/fc.def \
+              $(DEFSRC)/fg_bg.def $(DEFSRC)/hash.def $(DEFSRC)/help.def \
+              $(DEFSRC)/history.def $(DEFSRC)/jobs.def $(DEFSRC)/kill.def \
+              $(DEFSRC)/let.def $(DEFSRC)/read.def $(DEFSRC)/return.def \
+              $(DEFSRC)/set.def $(DEFSRC)/setattr.def $(DEFSRC)/shift.def \
+              $(DEFSRC)/source.def $(DEFSRC)/suspend.def $(DEFSRC)/test.def \
+              $(DEFSRC)/times.def $(DEFSRC)/trap.def $(DEFSRC)/type.def \
+              $(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \
+              $(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \
+              $(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def \
+              $(DEFSRC)/mapfile.def
+BUILTIN_C_SRC  = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \
+                $(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \
+                $(DEFSRC)/bashgetopt.c $(GETOPT_SOURCE)
+BUILTIN_C_OBJ  = $(DEFDIR)/common.o $(DEFDIR)/evalstring.o \
+                $(DEFDIR)/evalfile.o $(DEFDIR)/bashgetopt.o
+BUILTIN_OBJS = $(DEFDIR)/alias.o $(DEFDIR)/bind.o $(DEFDIR)/break.o \
+              $(DEFDIR)/builtin.o $(DEFDIR)/cd.o $(DEFDIR)/colon.o \
+              $(DEFDIR)/command.o $(DEFDIR)/caller.o $(DEFDIR)/declare.o \
+              $(DEFDIR)/echo.o $(DEFDIR)/enable.o $(DEFDIR)/eval.o \
+              $(DEFDIR)/exec.o $(DEFDIR)/exit.o $(DEFDIR)/fc.o \
+              $(DEFDIR)/fg_bg.o $(DEFDIR)/hash.o $(DEFDIR)/help.o \
+              $(DEFDIR)/history.o $(DEFDIR)/jobs.o $(DEFDIR)/kill.o \
+              $(DEFDIR)/let.o $(DEFDIR)/pushd.o $(DEFDIR)/read.o \
+              $(DEFDIR)/return.o $(DEFDIR)/shopt.o $(DEFDIR)/printf.o \
+              $(DEFDIR)/set.o $(DEFDIR)/setattr.o $(DEFDIR)/shift.o \
+              $(DEFDIR)/source.o $(DEFDIR)/suspend.o $(DEFDIR)/test.o \
+              $(DEFDIR)/times.o $(DEFDIR)/trap.o $(DEFDIR)/type.o \
+              $(DEFDIR)/ulimit.o $(DEFDIR)/umask.o $(DEFDIR)/wait.o \
+              $(DEFDIR)/getopts.o $(DEFDIR)/mapfile.o $(BUILTIN_C_OBJ)
+GETOPT_SOURCE   = $(DEFSRC)/getopt.c $(DEFSRC)/getopt.h
+PSIZE_SOURCE   = $(DEFSRC)/psize.sh $(DEFSRC)/psize.c
+
+BUILTINS_LIBRARY = $(DEFDIR)/libbuiltins.a
+BUILTINS_LIB = -lbuiltins
+BUILTINS_LDFLAGS = -L$(DEFDIR)
+BUILTINS_DEP = $(BUILTINS_LIBRARY)
+
+# Documentation for the shell.
+DOCSRC = $(srcdir)/doc
+DOCDIR = $(dot)/doc
+
+# Translations and other i18n support files
+PO_SRC = $(srcdir)/po/
+PO_DIR = $(dot)/po/
+
+SIGNAMES_SUPPORT = $(SUPPORT_SRC)mksignames.c
+
+SUPPORT_SRC = $(srcdir)/support/
+SDIR = $(dot)/support/
+
+TESTS_SUPPORT = recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) xcase$(EXEEXT)
+CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \
+                 tests/recho$(EXEEXT) tests/zecho$(EXEEXT) \
+                 tests/printenv$(EXEEXT) xcase$(EXEEXT) tests/xcase$(EXEEXT) \
+                 mksignames$(EXEEXT) lsignames.h \
+                 mksyntax${EXEEXT} syntax.c $(VERSPROG) $(VERSOBJ) \
+                 buildversion.o mksignames.o signames.o buildsignames.o
+CREATED_CONFIGURE = config.h config.cache config.status config.log \
+                   stamp-h po/POTFILES config.status.lineno
+CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
+                   lib/readline/Makefile lib/glob/Makefile \
+                   lib/sh/Makefile lib/tilde/Makefile lib/malloc/Makefile \
+                   lib/termcap/Makefile examples/loadables/Makefile \
+                   examples/loadables/perl/Makefile support/Makefile \
+                   lib/intl/Makefile po/Makefile po/Makefile.in
+
+# Keep GNU Make from exporting the entire environment for small machines.
+.NOEXPORT:
+
+.made: $(Program) bashbug
+       @echo "$(Program) last made for a $(Machine) running $(OS)" >.made
+
+$(Program):  .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP)
+       $(RM) $@
+       $(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS)
+       ls -l $(Program)
+       -$(SIZE) $(Program)
+
+.build:        $(SOURCES) config.h Makefile version.h $(VERSPROG)
+       @echo
+       @echo "   ***********************************************************"
+       @echo "   *                                                         *"
+       @echo "   * `$(BUILD_DIR)/$(VERSPROG) -l`"
+       @echo "   *                                                         *"
+       @echo "   ***********************************************************"
+       @echo
+
+bashbug: $(SUPPORT_SRC)bashbug.sh config.h Makefile $(VERSPROG)
+       @sed -e "s%!MACHINE!%$(Machine)%" -e "s%!OS!%$(OS)%" \
+            -e "s%!CFLAGS!%$(CCFLAGS)%" -e "s%!CC!%$(CC)%" \
+            -e "s%!RELEASE!%$(Version)%" -e "s%!PATCHLEVEL!%$(PatchLevel)%" \
+            -e "s%!MACHTYPE!%$(MACHTYPE)%" -e "s%!RELSTATUS!%$(RELSTATUS)%" \
+            $(SUPPORT_SRC)bashbug.sh > $@
+       @chmod a+rx bashbug
+
+strip: $(Program) .made
+       strip $(Program)
+       ls -l $(Program)
+       -$(SIZE) $(Program)
+
+lint:
+       ${MAKE} ${MFLAGS} CFLAGS='${GCC_LINT_FLAGS}' .made
+
+version.h:  $(SOURCES) config.h Makefile patchlevel.h
+       $(SHELL) $(SUPPORT_SRC)mkversion.sh -b -S ${topdir} -s $(RELSTATUS) -d $(Version) -o newversion.h \
+               && mv newversion.h version.h
+
+bashversion$(EXEEXT):  patchlevel.h conftypes.h version.h buildversion.o $(SUPPORT_SRC)bashversion.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)bashversion.c buildversion.o ${LIBS_FOR_BUILD}
+
+buildversion.o: version.h conftypes.h patchlevel.h $(srcdir)/version.c
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -c -o $@ $(srcdir)/version.c
+
+# old rules
+GRAM_H = parser-built
+y.tab.o: y.tab.h y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h
+${GRAM_H}:     y.tab.h
+       @-if test -f y.tab.h ; then \
+               cmp -s $@ y.tab.h 2>/dev/null || cp -p y.tab.h $@; \
+       fi
+
+y.tab.c: parse.y
+#      -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
+       $(YACC) -d $(srcdir)/parse.y
+       touch parser-built
+#      -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; else cp -p y.tab.h ${GRAM_H}; fi
+
+y.tab.h: y.tab.c
+       @true
+
+# Subdirs will often times want version.h, so they'll change back up to
+# the top level and try to create it.  This causes parallel build issues
+# so just force top level sanity before we descend.
+#$(LIBDEP): .build
+$(LIBDEP): version.h
+
+$(READLINE_LIBRARY): config.h $(READLINE_SOURCE)
+       @echo making $@ in ${RL_LIBDIR}
+       @( { test "${RL_LIBDIR}" = "${libdir}" && exit 0; } || \
+               cd ${RL_LIBDIR} && $(MAKE) $(MFLAGS) libreadline.a) || exit 1
+
+$(HISTORY_LIBRARY): config.h $(HISTORY_SOURCE) $(READLINE_DEP)
+       @echo making $@ in ${HIST_LIBDIR}
+       @( { test "${HIST_LIBDIR}" = "${libdir}" && exit 0; } || \
+               cd ${HIST_LIBDIR} && $(MAKE) $(MFLAGS) libhistory.a) || exit 1
+
+$(GLOB_LIBRARY): config.h $(GLOB_SOURCE)
+       @echo making $@ in ${GLOB_LIBDIR}
+       @(cd ${GLOB_LIBDIR} && \
+               $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libglob.a) || exit 1
+
+$(TILDE_LIBRARY): config.h $(TILDE_SOURCE)
+       @echo making $@ in ${TILDE_LIBDIR}
+       @(cd ${TILDE_LIBDIR} && \
+               $(MAKE) $(MFLAGS) libtilde.a) || exit 1
+
+$(TERMCAP_LIBRARY): config.h ${TERMCAP_SOURCE}
+       @echo making $@ in ${TERM_LIBDIR}       
+       @(cd ${TERM_LIBDIR} && \
+               $(MAKE) $(MFLAGS) libtermcap.a) || exit 1
+
+$(SHLIB_LIBRARY): config.h ${SHLIB_SOURCE}
+       @echo making $@ in ${SH_LIBDIR}
+       @(cd ${SH_LIBDIR} && \
+               $(MAKE) $(MFLAGS) DEBUG=${DEBUG} ${SHLIB_LIBNAME}) || exit 1
+
+${INTL_LIBRARY}: config.h ${INTL_LIBDIR}/Makefile
+       @echo making $@ in ${INTL_LIBDIR}
+       @(cd ${INTL_LIBDIR} && \
+               $(MAKE) $(MFLAGS) all) || exit 1
+
+${LIBINTL_H}:  ${INTL_DEP}
+
+signames.o: $(SUPPORT_SRC)signames.c
+       $(RM) $@
+       $(CC) $(CCFLAGS) -c $(SUPPORT_SRC)signames.c
+
+buildsignames.o:       $(SUPPORT_SRC)signames.c
+       $(RM) $@
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -o $@ -c $(SUPPORT_SRC)signames.c
+
+mksignames.o:  $(SUPPORT_SRC)mksignames.c
+       $(RM) $@
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -c $(SUPPORT_SRC)mksignames.c
+
+mksignames$(EXEEXT):   mksignames.o buildsignames.o
+       $(RM) $@
+       $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ mksignames.o buildsignames.o ${LIBS_FOR_BUILD}
+
+mksyntax$(EXEEXT):     ${srcdir}/mksyntax.c config.h syntax.h ${BASHINCDIR}/chartypes.h
+       $(RM) $@
+       ${CC_FOR_BUILD} ${CCFLAGS_FOR_BUILD} -o $@ ${srcdir}/mksyntax.c ${LIBS_FOR_BUILD}
+
+# make a list of signals for the local system -- this is done when we're
+# *not* cross-compiling
+lsignames.h:   mksignames$(EXEEXT)
+       $(RM) $@
+       ./mksignames$(EXEEXT) $@
+
+# copy the correct signames header file to signames.h
+signames.h: $(SIGNAMES_H)
+       -if cmp -s $(SIGNAMES_H) $@ ; then :; else $(RM) $@ ; $(CP) $(SIGNAMES_H) $@ ; fi
+
+syntax.c:      mksyntax${EXEEXT} $(srcdir)/syntax.h 
+       $(RM) $@
+       ./mksyntax$(EXEEXT) -o $@
+
+$(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h ${BASHINCDIR}/memalloc.h version.h
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libbuiltins.a ) || exit 1
+
+# these require special rules to circumvent make builtin rules
+${DEFDIR}/common.o:    $(BUILTIN_SRCDIR)/common.c
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} common.o) || exit 1
+
+${DEFDIR}/bashgetopt.o:        $(BUILTIN_SRCDIR)/bashgetopt.c
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} bashgetopt.o) || exit 1
+
+${DEFDIR}/builtext.h: $(BUILTIN_DEFS)
+       @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) builtext.h ) || exit 1
+
+# For the justification of the following Makefile rules, see node
+# `Automatic Remaking' in GNU Autoconf documentation.
+
+Makefile makefile:     config.status $(srcdir)/Makefile.in
+       CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+Makefiles makefiles:   config.status $(srcdir)/Makefile.in
+       @for mf in $(CREATED_MAKEFILES); do \
+               CONFIG_FILES=$$mf CONFIG_HEADERS= $(SHELL) ./config.status ; \
+       done
+
+config.h:      stamp-h 
+
+stamp-h:       config.status $(srcdir)/config.h.in $(srcdir)/config-top.h $(srcdir)/config-bot.h
+       CONFIG_FILES= CONFIG_HEADERS=config.h $(SHELL) ./config.status
+
+config.status: $(srcdir)/configure
+       $(SHELL) ./config.status --recheck
+
+pathnames.h:           Makefile $(srcdir)/pathnames.h.in
+       @sed -e 's|@DEBUGGER_START_FILE\@|${DEBUGGER_START_FILE}|g' $(srcdir)/pathnames.h.in > pathnames.tmp
+       @if test -f $@; then \
+               cmp -s pathnames.tmp $@ || mv pathnames.tmp $@; \
+       else \
+               mv pathnames.tmp $@; \
+       fi
+       @${RM} pathnames.tmp
+
+# comment out for distribution
+$(srcdir)/configure:   $(srcdir)/configure.in $(srcdir)/aclocal.m4 $(srcdir)/config.h.in
+       cd $(srcdir) && autoconf
+
+# for chet
+reconfig: force
+       sh $(srcdir)/configure -C
+
+#newversion:   mkversion
+#      $(RM) .build
+#      ./mkversion -dir $(srcdir) -dist
+#      mv -f newversion.h version.h
+#      $(MAKE) -f $(srcdir)/Makefile $(MFLAGS) srcdir=$(srcdir)
+
+doc documentation:  force
+       @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) )
+
+info dvi ps: force
+       @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) CFLAGS='$(CCFLAGS)' $@ )
+
+force:
+
+TAGS:  $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+       etags $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+
+tags:  $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+       ctags -x $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE) > $@
+
+# Targets that actually do things not part of the build
+
+installdirs:
+       @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(bindir)
+       @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(man1dir)
+       @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(infodir)
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install:       .made installdirs
+       $(INSTALL_PROGRAM) $(INSTALLMODE) $(Program) $(DESTDIR)$(bindir)/$(Program)
+       $(INSTALL_SCRIPT) $(INSTALLMODE2) bashbug $(DESTDIR)$(bindir)/bashbug
+       -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+               man1dir=$(man1dir) man1ext=$(man1ext) \
+               man3dir=$(man3dir) man3ext=$(man3ext) \
+               infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+       -( cd $(DEFDIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install-strip:
+       $(MAKE) $(MFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
+               prefix=${prefix} exec_prefix=${exec_prefix} \
+               DESTDIR=$(DESTDIR) install
+
+uninstall:     .made
+       $(RM) $(DESTDIR)$(bindir)/$(Program) $(DESTDIR)$(bindir)/bashbug
+       -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+               man1dir=$(man1dir) man1ext=$(man1ext) \
+               man3dir=$(man3dir) man3ext=$(man3ext) \
+               infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+.PHONY: basic-clean clean realclean maintainer-clean distclean mostlyclean maybe-clean
+
+LIB_SUBDIRS = ${RL_LIBDIR}  ${HIST_LIBDIR} ${TERM_LIBDIR} ${GLOB_LIBDIR} \
+               ${INTL_LIBDIR} ${TILDE_LIBDIR} ${ALLOC_LIBDIR} ${SH_LIBDIR}
+
+basic-clean:
+       $(RM) $(OBJECTS) $(Program) bashbug
+       $(RM) .build .made version.h 
+
+clean: basic-clean
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       $(RM) $(CREATED_SUPPORT)
+
+mostlyclean: basic-clean
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+distclean:     basic-clean maybe-clean
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       $(RM) $(CREATED_CONFIGURE) tags TAGS 
+       $(RM) $(CREATED_SUPPORT) Makefile $(CREATED_MAKEFILES) pathnames.h
+
+maintainer-clean:      basic-clean
+       @echo This command is intended for maintainers to use.
+       @echo It deletes files that may require special tools to rebuild.
+       $(RM) y.tab.c y.tab.h parser-built tags TAGS
+       ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+       ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+       ( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+       -for libdir in ${LIB_SUBDIRS}; do \
+               (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+       done
+       -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+       $(RM) $(CREATED_CONFIGURE) $(CREATED_MAKEFILES)
+       $(RM) $(CREATED_SUPPORT) Makefile pathnames.h
+
+maybe-clean:
+       -if test "X$(topdir)" != "X$(BUILD_DIR)" ; then \
+               $(RM) parser-built y.tab.c y.tab.h ; \
+       fi
+
+recho$(EXEEXT):                $(SUPPORT_SRC)recho.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)recho.c ${LIBS_FOR_BUILD}
+
+zecho$(EXEEXT):                $(SUPPORT_SRC)zecho.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)zecho.c ${LIBS_FOR_BUILD}
+
+printenv$(EXEEXT):     $(SUPPORT_SRC)printenv.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)printenv.c ${LIBS_FOR_BUILD}
+
+xcase$(EXEEXT):        $(SUPPORT_SRC)xcase.c
+       @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)xcase.c ${LIBS_FOR_BUILD}
+
+test tests check:      force $(Program) $(TESTS_SUPPORT)
+       @-test -d tests || mkdir tests
+       @cp $(TESTS_SUPPORT) tests
+       @( cd $(srcdir)/tests && \
+               PATH=$(BUILD_DIR)/tests:$$PATH THIS_SH=$(THIS_SH) $(SHELL) ${TESTSCRIPT} )
+
+symlinks:
+       $(SHELL) $(SUPPORT_SRC)fixlinks -s $(srcdir)
+
+dist:  force
+       @echo Bash distributions are created using $(srcdir)/support/mkdist.
+       @echo Here is a sample of the necessary commands:
+       @echo $(Program) $(srcdir)/support/mkdist -m $(srcdir)/MANIFEST -s $(srcdir) -r ${PACKAGE} $(PACKAGE_VERSION)
+       @echo tar cf $(PACKAGE)-${PACKAGE_VERSION}.tar ${PACKAGE}-$(PACKAGE_VERSION)
+       @echo gzip $(PACKAGE)-$(PACKAGE_VERSION).tar
+
+depend:        depends
+
+depends: force
+       $(Program) $(SUPPORT_SRC)mkdep -c ${CC} -- ${CCFLAGS} ${CSOURCES}
+
+#### PRIVATE TARGETS ####
+hashtest:      hashlib.c
+       $(CC) -DTEST_HASHING $(CCFLAGS) -o $@ $(srcdir)/hashlib.c
+
+############################ DEPENDENCIES ###############################
+
+# Files that depend on the definitions in config-top.h, which are not meant
+# to be changed
+bashhist.o: config-top.h
+shell.o: config-top.h
+input.o: config-top.h
+y.tab.o: config-top.h
+jobs.o: config-top.h
+nojobs.o: config-top.h
+execute_cmd.o: config-top.h
+variables.o: config-top.h
+builtins/command.o: config-top.h
+builtins/common.o: config-top.h
+builtins/break.o: config-top.h
+builtins/echo.o: config-top.h
+builtins/evalstring.o: config-top.h
+builtins/exit.o: config-top.h
+builtins/kill.o: config-top.h
+
+# shell basics
+copy_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+copy_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+copy_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+copy_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+dispose_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h
+dispose_cmd.o: error.h general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+dispose_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+dispose_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: ${BASHINCDIR}/ocache.h
+error.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h flags.h ${BASHINCDIR}/stdc.h error.h
+error.o: command.h general.h xmalloc.h externs.h input.h bashhist.h
+error.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+error.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+error.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+error.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+error.o: input.h execute_cmd.h 
+eval.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h trap.h flags.h ${DEFSRC}/common.h
+eval.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+eval.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+eval.o: input.h execute_cmd.h 
+execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+execute_cmd.o: ${BASHINCDIR}/memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit.h siglist.h
+execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h
+execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h
+execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h
+expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h 
+expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+expr.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+expr.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+expr.o: ${BASHINCDIR}/chartypes.h
+findcmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h
+findcmd.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h
+findcmd.o: ${BASHINCDIR}/stdc.h error.h general.h xmalloc.h variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+findcmd.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
+findcmd.o: flags.h hashlib.h pathexp.h hashcmd.h 
+findcmd.o: ${BASHINCDIR}/chartypes.h
+flags.o: config.h flags.h 
+flags.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+flags.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+flags.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+flags.o: make_cmd.h subst.h sig.h pathnames.h externs.h bashhist.h
+general.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+general.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+general.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+general.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+general.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+general.o: ${BASHINCDIR}/maxpath.h ${BASHINCDIR}/posixtime.h
+general.o: ${BASHINCDIR}/chartypes.h
+hashcmd.o: config.h ${BASHINCDIR}/posixstat.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashcmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashcmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashcmd.h
+hashcmd.o: execute_cmd.h findcmd.h ${BASHINCDIR}/stdc.h pathnames.h hashlib.h
+hashlib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+hashlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+hashlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+input.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+input.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h input.h error.h externs.h
+input.o: quit.h
+list.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+list.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+list.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+list.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+locale.o: config.h bashtypes.h bashintl.h ${LIBINTL_H} bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+locale.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+locale.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+locale.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+locale.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+locale.o: ${BASHINCDIR}/chartypes.h
+mailcheck.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+mailcheck.o: ${BASHINCDIR}/posixtime.h
+mailcheck.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+mailcheck.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+mailcheck.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+mailcheck.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+mailcheck.o: execute_cmd.h mailcheck.h 
+make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
+make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
+make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
+make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h parser.h
+make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h ${BASHINCDIR}/ocache.h
+y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
+y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+y.tab.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+y.tab.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+y.tab.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+y.tab.o: trap.h flags.h parser.h input.h mailcheck.h $(DEFSRC)/common.h
+y.tab.o: $(DEFDIR)/builtext.h bashline.h bashhist.h jobs.h siglist.h alias.h
+pathexp.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+pathexp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+pathexp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+pathexp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+pathexp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+pathexp.o: pathexp.h flags.h 
+pathexp.o: $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+pathexp.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+print_cmd.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+print_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+print_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+print_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+print_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+print_cmd.o: ${GRAM_H} $(DEFSRC)/common.h
+redir.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+redir.o: ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+redir.o: general.h xmalloc.h variables.h arrayfunc.h conftypes.h array.h hashlib.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h 
+redir.o: flags.h execute_cmd.h redir.h input.h
+shell.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+shell.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+shell.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+shell.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+shell.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+shell.o: flags.h trap.h mailcheck.h builtins.h $(DEFSRC)/common.h
+shell.o: jobs.h siglist.h input.h execute_cmd.h findcmd.h bashhist.h bashline.h
+shell.o: ${GLOB_LIBSRC}/strmatch.h ${BASHINCDIR}/posixtime.h
+sig.o: config.h bashtypes.h
+sig.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+sig.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+sig.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+sig.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+sig.o: jobs.h siglist.h trap.h $(DEFSRC)/common.h bashline.h bashhist.h
+siglist.o: config.h bashtypes.h siglist.h trap.h 
+stringlib.o: bashtypes.h ${BASHINCDIR}/chartypes.h
+stringlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+stringlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+stringlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+stringlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+stringlib.o: ${GLOB_LIBSRC}/glob.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+subst.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+subst.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+subst.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+subst.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h
+subst.o: flags.h jobs.h siglist.h execute_cmd.h ${BASHINCDIR}/filecntl.h trap.h pathexp.h
+subst.o: mailcheck.h input.h $(DEFSRC)/getopt.h $(DEFSRC)/common.h
+subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: ${BASHINCDIR}/chartypes.h
+subst.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+subst.o: ${DEFDIR}/builtext.h
+test.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+test.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+test.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+test.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+test.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+test.o: ${DEFSRC}/common.h 
+trap.o: config.h bashtypes.h trap.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+trap.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+trap.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+trap.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+trap.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+trap.o: signames.h $(DEFSRC)/common.h
+trap.o: ${DEFDIR}/builtext.h jobs.h
+unwind_prot.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+unwind_prot.o: general.h xmalloc.h unwind_prot.h quit.h sig.h
+variables.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+variables.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+variables.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+variables.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+variables.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+variables.o: flags.h execute_cmd.h mailcheck.h input.h $(DEFSRC)/common.h
+variables.o: findcmd.h bashhist.h hashcmd.h pathexp.h
+variables.o: pcomplete.h  ${BASHINCDIR}/chartypes.h
+variables.o: ${BASHINCDIR}/posixtime.h assoc.h
+version.o:  conftypes.h patchlevel.h version.h
+xmalloc.o: config.h bashtypes.h ${BASHINCDIR}/ansi_stdlib.h error.h
+
+# job control
+
+jobs.o: config.h bashtypes.h trap.h ${BASHINCDIR}/filecntl.h input.h ${BASHINCDIR}/shtty.h
+jobs.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+jobs.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+jobs.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+jobs.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+jobs.o: execute_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h 
+jobs.o: jobs.h flags.h $(DEFSRC)/common.h $(DEFDIR)/builtext.h
+jobs.o: ${BASHINCDIR}/posixwait.h ${BASHINCDIR}/unionwait.h
+jobs.o: ${BASHINCDIR}/posixtime.h
+nojobs.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+nojobs.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h jobs.h quit.h siglist.h externs.h
+nojobs.o: sig.h error.h ${BASHINCDIR}/shtty.h input.h
+nojobs.o: $(DEFDIR)/builtext.h
+
+# shell features that may be compiled in
+
+array.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+array.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+array.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+array.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+array.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+array.o: $(DEFSRC)/common.h
+arrayfunc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+arrayfunc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+arrayfunc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+arrayfunc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+arrayfunc.o: make_cmd.h subst.h sig.h pathnames.h externs.h pathexp.h
+arrayfunc.o: $(DEFSRC)/common.h
+arrayfunc.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+assoc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+assoc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+assoc.o: command.h ${BASHINCDIR}/stdc.h error.h
+assoc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
+assoc.o: assoc.h hashlib.h
+assoc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+assoc.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+assoc.o: $(DEFSRC)/common.h
+braces.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+braces.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+braces.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+braces.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+braces.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+braces.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+alias.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+alias.o: general.h xmalloc.h bashtypes.h externs.h alias.h
+alias.o: pcomplete.h 
+alias.o: ${BASHINCDIR}/chartypes.h
+
+pcomplib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplib.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplib.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplib.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplib.o: externs.h ${BASHINCDIR}/maxpath.h
+
+pcomplete.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplete.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplete.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplete.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplete.o: externs.h ${BASHINCDIR}/maxpath.h execute_cmd.h 
+
+# library support files
+
+bashhist.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+bashhist.o: ${BASHINCDIR}/filecntl.h
+bashhist.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashhist.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashhist.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashhist.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+bashhist.o: flags.h input.h parser.h pathexp.h $(DEFSRC)/common.h bashline.h
+bashhist.o: $(GLOB_LIBSRC)/strmatch.h
+bashline.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bashline.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashline.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashline.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashline.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+bashline.o: builtins.h bashhist.h bashline.h execute_cmd.h findcmd.h pathexp.h
+bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h
+bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h input.h
+bashline.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+bracecomp.o: command.h ${BASHINCDIR}/stdc.h error.h
+bracecomp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
+bracecomp.o: array.h hashlib.h alias.h builtins.h 
+bracecomp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bracecomp.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+
+# library dependencies
+
+bashline.o: $(RL_LIBSRC)/rlconf.h
+bashline.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+bashline.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+bracecomp.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+bracecomp.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+y.tab.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+y.tab.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+subst.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+subst.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+
+shell.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+subst.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashline.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashhist.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+y.tab.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+
+execute_cmd.o: $(TILDE_LIBSRC)/tilde.h
+general.o: $(TILDE_LIBSRC)/tilde.h
+mailcheck.o: $(TILDE_LIBSRC)/tilde.h
+shell.o: $(TILDE_LIBSRC)/tilde.h
+subst.o: $(TILDE_LIBSRC)/tilde.h
+variables.o: $(TILDE_LIBSRC)/tilde.h
+
+# libintl dependencies
+arrayfunc.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashhist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashline.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+braces.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+error.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+eval.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+execute_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+expr.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+general.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+input.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+jobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+mailcheck.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+make_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+nojobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+y.tab.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplete.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplib.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+print_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+redir.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+shell.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+sig.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+siglist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+subst.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+test.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+trap.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+variables.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+version.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+xmalloc.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+
+signames.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+
+# XXX - dependencies checked through here
+
+# builtin c sources
+builtins/bashgetopt.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/bashgetopt.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/bashgetopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/bashgetopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+builtins/bashgetopt.o: $(DEFSRC)/common.h
+builtins/bashgetopt.o: ${BASHINCDIR}/chartypes.h
+builtins/common.o: bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/common.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h
+builtins/common.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h siglist.h
+builtins/common.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/common.o: dispose_cmd.h make_cmd.h subst.h externs.h bashhist.h 
+builtins/common.o: execute_cmd.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h pathnames.h
+builtins/common.o: ${DEFDIR}/builtext.h
+builtins/common.o: ${BASHINCDIR}/chartypes.h
+builtins/evalfile.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalfile.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/evalfile.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/evalfile.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+builtins/evalfile.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalfile.o: bashhist.h $(DEFSRC)/common.h
+builtins/evalstring.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalstring.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h siglist.h
+builtins/evalstring.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h
+builtins/evalstring.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/evalstring.o: dispose_cmd.h make_cmd.h subst.h externs.h 
+builtins/evalstring.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalstring.o: bashhist.h $(DEFSRC)/common.h pathnames.h
+builtins/getopt.o: config.h ${BASHINCDIR}/memalloc.h
+builtins/getopt.o: shell.h syntax.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/getopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/getopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h 
+builtins/getopt.o: $(DEFSRC)/getopt.h
+builtins/mkbuiltins.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+builtins/mkbuiltins.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+
+# builtin def files
+builtins/alias.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/alias.o: quit.h $(DEFSRC)/common.h pathnames.h
+builtins/alias.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h ${BASHINCDIR}/stdc.h unwind_prot.h
+builtins/alias.o: dispose_cmd.h make_cmd.h subst.h externs.h variables.h arrayfunc.h conftypes.h 
+builtins/bind.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/bind.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/bind.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/bind.o: $(DEFSRC)/bashgetopt.h pathnames.h
+builtins/break.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/break.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/break.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/break.o: pathnames.h
+builtins/builtin.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/builtin.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/builtin.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/builtin.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/builtin.o: pathnames.h
+builtins/caller.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/caller.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/caller.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/caller.o: $(DEFSRC)/common.h quit.h 
+builtins/caller.o: ${BASHINCDIR}/chartypes.h bashtypes.h
+builtins/caller.o: ${DEFDIR}/builtext.h pathnames.h
+builtins/cd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/cd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/cd.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/cd.o: $(DEFSRC)/common.h quit.h pathnames.h
+builtins/command.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/command.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/command.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/command.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h pathnames.h
+builtins/declare.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/declare.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/declare.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/declare.o: $(DEFSRC)/bashgetopt.h pathnames.h
+builtins/echo.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/echo.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/echo.o: pathnames.h
+builtins/enable.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/enable.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/enable.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/enable.o: pcomplete.h pathnames.h
+builtins/eval.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/eval.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/eval.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/eval.o: pathnames.h
+builtins/exec.o: bashtypes.h pathnames.h
+builtins/exec.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exec.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/exec.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h 
+builtins/exec.o: findcmd.h flags.h quit.h $(DEFSRC)/common.h ${BASHINCDIR}/stdc.h
+builtins/exec.o: pathnames.h
+builtins/exit.o: bashtypes.h 
+builtins/exit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/exit.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/exit.o: pathnames.h
+builtins/fc.o: bashtypes.h ${BASHINCDIR}/posixstat.h
+builtins/fc.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h builtins.h command.h ${BASHINCDIR}/stdc.h 
+builtins/fc.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fc.o: flags.h unwind_prot.h variables.h arrayfunc.h conftypes.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h 
+builtins/fc.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h quit.h 
+builtins/fc.o: $(DEFSRC)/bashgetopt.h bashhist.h pathnames.h
+builtins/fc.o: ${BASHINCDIR}/chartypes.h
+builtins/fg_bg.o: bashtypes.h $(DEFSRC)/bashgetopt.h 
+builtins/fg_bg.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fg_bg.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/fg_bg.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/fg_bg.o: pathnames.h
+builtins/getopts.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/getopts.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/getopts.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/getopts.o: pathnames.h
+builtins/hash.o: bashtypes.h 
+builtins/hash.o: builtins.h command.h findcmd.h ${BASHINCDIR}/stdc.h $(DEFSRC)/common.h
+builtins/hash.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/hash.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/hash.o: pathnames.h
+builtins/help.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/help.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/help.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/help.o: $(GLOB_LIBSRC)/glob.h pathnames.h
+builtins/history.o: bashtypes.h pathnames.h
+builtins/history.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/history.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/history.o: ${BASHINCDIR}/filecntl.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h
+builtins/history.o: bashhist.h variables.h arrayfunc.h conftypes.h 
+builtins/inlib.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/inlib.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h 
+builtins/inlib.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/inlib.o: pathnames.h
+builtins/jobs.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/jobs.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/jobs.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/jobs.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/jobs.o: pathnames.h
+builtins/kill.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/kill.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/kill.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h trap.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/kill.o: pathnames.h
+builtins/let.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/let.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/let.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/let.o: pathnames.h
+builtins/printf.o: config.h ${BASHINCDIR}/memalloc.h bashjmp.h command.h error.h
+builtins/printf.o: general.h xmalloc.h quit.h dispose_cmd.h make_cmd.h subst.h
+builtins/printf.o: externs.h sig.h pathnames.h shell.h syntax.h unwind_prot.h
+builtins/printf.o: variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/stdc.h $(DEFSRC)/bashgetopt.h
+builtins/printf.o: ${BASHINCDIR}/chartypes.h 
+builtins/pushd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/pushd.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/pushd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/pushd.o: $(DEFSRC)/common.h pathnames.h
+builtins/read.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/read.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/read.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/read.o: pathnames.h
+builtins/return.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/return.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/return.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/return.o: pathnames.h
+builtins/set.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/set.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/set.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h flags.h
+builtins/set.o: pathnames.h
+builtins/setattr.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/setattr.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/setattr.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/setattr.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/setattr.o: pathnames.h
+builtins/shift.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/shift.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/shift.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: pathnames.h
+builtins/shopt.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h
+builtins/shopt.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/shopt.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h unwind_prot.h variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/maxpath.h
+builtins/shopt.o: $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h pathnames.h
+builtins/shopt.o: bashhist.h bashline.h
+builtins/source.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/source.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/source.o: findcmd.h $(DEFSRC)/bashgetopt.h flags.h trap.h
+builtins/source.o: pathnames.h
+builtins/suspend.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/suspend.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/suspend.o: pathnames.h
+builtins/test.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/test.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/test.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/test.o: test.h pathnames.h
+builtins/times.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/times.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/times.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/times.o: pathnames.h
+builtins/trap.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/trap.o: quit.h $(DEFSRC)/common.h
+builtins/trap.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/trap.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/trap.o: pathnames.h
+builtins/type.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/type.o: quit.h $(DEFSRC)/common.h findcmd.h
+builtins/type.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/type.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/type.o: pathnames.h
+builtins/ulimit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/ulimit.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/ulimit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/ulimit.o: pathnames.h
+builtins/umask.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/umask.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/umask.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/umask.o: ${BASHINCDIR}/chartypes.h pathnames.h
+builtins/wait.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/wait.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/wait.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/wait.o: ${BASHINCDIR}/chartypes.h pathnames.h
+
+builtins/complete.o: config.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h
+builtins/complete.o: unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/complete.o: bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/complete.o: builtins.h pathnames.h
+builtins/complete.o: pcomplete.h
+builtins/complete.o: ${DEFSRC}/common.h ${DEFSRC}/bashgetopt.h
+builtins/mapfile.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/mapfile.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/mapfile.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h 
+builtins/mapfile.o: pathnames.h
+
+# libintl dependencies
+builtins/bind.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/break.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/caller.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/cd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/common.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/complete.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/declare.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/enable.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/evalfile.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exec.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fc.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fg_bg.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/getopt.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/hash.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/help.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/history.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/inlib.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/jobs.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/kill.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/let.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/mapfile.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/mkbuiltins.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/printf.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/pushd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/read.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/return.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/set.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/setattr.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shift.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shopt.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/source.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/suspend.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/type.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/ulimit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/umask.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+
+# builtin library dependencies
+builtins/bind.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+builtins/bind.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/bind.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/fc.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/history.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/common.o: $(TILDE_LIBSRC)/tilde.h
+builtins/cd.o: $(TILDE_LIBSRC)/tilde.h 
+
+builtins/alias.o: $(DEFSRC)/alias.def
+builtins/bind.o: $(DEFSRC)/bind.def
+builtins/break.o: $(DEFSRC)/break.def
+builtins/builtin.o: $(DEFSRC)/builtin.def
+builtins/caller.o: $(DEFSRC)/caller.def
+builtins/cd.o: $(DEFSRC)/cd.def
+builtins/colon.o: $(DEFSRC)/colon.def
+builtins/command.o: $(DEFSRC)/command.def
+builtins/complete.o: $(DEFSRC)/complete.def
+builtins/declare.o: $(DEFSRC)/declare.def
+builtins/echo.o: $(DEFSRC)/echo.def
+builtins/enable.o: $(DEFSRC)/enable.def
+builtins/eval.o: $(DEFSRC)/eval.def
+builtins/exec.o: $(DEFSRC)/exec.def
+builtins/exit.o: $(DEFSRC)/exit.def
+builtins/fc.o: $(DEFSRC)/fc.def
+builtins/fg_bg.o: $(DEFSRC)/fg_bg.def
+builtins/getopts.o: $(DEFSRC)/getopts.def
+builtins/hash.o: $(DEFSRC)/hash.def
+builtins/help.o: $(DEFSRC)/help.def
+builtins/history.o: $(DEFSRC)/history.def
+builtins/inlib.o: $(DEFSRC)/inlib.def
+builtins/jobs.o: $(DEFSRC)/jobs.def
+builtins/kill.o: $(DEFSRC)/kill.def
+builtins/let.o: $(DEFSRC)/let.def
+builtins/mapfile.o: $(DEFSRC)/mapfile.def
+builtins/pushd.o: $(DEFSRC)/pushd.def
+builtins/read.o: $(DEFSRC)/read.def
+builtins/reserved.o: $(DEFSRC)/reserved.def
+builtins/return.o: $(DEFSRC)/return.def
+builtins/set.o: $(DEFSRC)/set.def
+builtins/setattr.o: $(DEFSRC)/setattr.def
+builtins/shift.o: $(DEFSRC)/shift.def
+builtins/shopt.o: $(DEFSRC)/shopt.def
+builtins/source.o: $(DEFSRC)/source.def
+builtins/suspend.o: $(DEFSRC)/suspend.def
+builtins/test.o: $(DEFSRC)/test.def
+builtins/times.o: $(DEFSRC)/times.def
+builtins/trap.o: $(DEFSRC)/trap.def
+builtins/type.o: $(DEFSRC)/type.def
+builtins/ulimit.o: $(DEFSRC)/ulimit.def
+builtins/umask.o: $(DEFSRC)/umask.def
+builtins/wait.o: $(DEFSRC)/wait.def
diff --git a/assoc.c b/assoc.c
index bbc7b177720245f0a9255bfa3007e46875064c59..5d3cd11bc3997cdc3d936859e5334d0fc6164e5a 100644 (file)
--- a/assoc.c
+++ b/assoc.c
@@ -7,7 +7,7 @@
  * chet@ins.cwru.edu
  */
 
-/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008,2009,2011 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -65,7 +65,7 @@ assoc_flush (hash)
 {
   hash_flush (hash, 0);
 }
-     
+
 int
 assoc_insert (hash, key, value)
      HASH_TABLE *hash;
@@ -77,11 +77,39 @@ assoc_insert (hash, key, value)
   b = hash_search (key, hash, HASH_CREATE);
   if (b == 0)
     return -1;
+  /* If we are overwriting an existing element's value, we're not going to
+     use the key.  Nothing in the array assignment code path frees the key
+     string, so we can free it here to avoid a memory leak. */
+  if (b->key != key)
+    free (key);
   FREE (b->data);
   b->data = value ? savestring (value) : (char *)0;
   return (0);
 }
 
+/* Like assoc_insert, but returns b->data instead of freeing it */
+PTR_T
+assoc_replace (hash, key, value)
+     HASH_TABLE *hash;
+     char *key;
+     char *value;
+{
+  BUCKET_CONTENTS *b;
+  PTR_T t;
+
+  b = hash_search (key, hash, HASH_CREATE);
+  if (b == 0)
+    return (PTR_T)0;
+  /* If we are overwriting an existing element's value, we're not going to
+     use the key.  Nothing in the array assignment code path frees the key
+     string, so we can free it here to avoid a memory leak. */
+  if (b->key != key)
+    free (key);
+  t = b->data;
+  b->data = value ? savestring (value) : (char *)0;
+  return t;
+}
+
 void
 assoc_remove (hash, string)
      HASH_TABLE *hash;
diff --git a/assoc.h b/assoc.h
index 1ec1f6b23b1693c0074d54d651c4ab9ff86eb7af..db8383b2c9bc63f04b5e0c262ca640c6357d016a 100644 (file)
--- a/assoc.h
+++ b/assoc.h
@@ -38,6 +38,7 @@ extern void assoc_dispose __P((HASH_TABLE *));
 extern void assoc_flush __P((HASH_TABLE *));
 
 extern int assoc_insert __P((HASH_TABLE *, char *, char *));
+extern PTR_T assoc_replace __P((HASH_TABLE *, char *, char *));
 extern void assoc_remove __P((HASH_TABLE *, char *));
 
 extern char *assoc_reference __P((HASH_TABLE *, char *));
diff --git a/builtins/common.c~ b/builtins/common.c~
new file mode 100644 (file)
index 0000000..8332831
--- /dev/null
@@ -0,0 +1,892 @@
+/* common.c - utility functions for all builtins */
+
+/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <chartypes.h>
+#include "../bashtypes.h"
+#include "posixstat.h"
+#include <signal.h>
+
+#include <errno.h>
+
+#if defined (PREFER_STDARG)
+#  include <stdarg.h>
+#else
+#  include <varargs.h>
+#endif
+
+#include "../bashansi.h"
+#include "../bashintl.h"
+
+#define NEED_FPURGE_DECL
+
+#include "../shell.h"
+#include "maxpath.h"
+#include "../flags.h"
+#include "../jobs.h"
+#include "../builtins.h"
+#include "../input.h"
+#include "../execute_cmd.h"
+#include "../trap.h"
+#include "bashgetopt.h"
+#include "common.h"
+#include "builtext.h"
+#include <tilde/tilde.h>
+
+#if defined (HISTORY)
+#  include "../bashhist.h"
+#endif
+
+#if !defined (errno)
+extern int errno;   
+#endif /* !errno */
+
+extern int indirection_level, subshell_environment;
+extern int line_number;
+extern int last_command_exit_value;
+extern int running_trap;
+extern int posixly_correct;
+extern char *this_command_name, *shell_name;
+extern const char * const bash_getcwd_errstr;
+
+/* Used by some builtins and the mainline code. */
+sh_builtin_func_t *last_shell_builtin = (sh_builtin_func_t *)NULL;
+sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL;
+
+/* **************************************************************** */
+/*                                                                 */
+/*          Error reporting, usage, and option processing          */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is a lot like report_error (), but it is for shell builtins
+   instead of shell control structures, and it won't ever exit the
+   shell. */
+
+static void
+builtin_error_prolog ()
+{
+  char *name;
+
+  name = get_name_for_error ();
+  fprintf (stderr, "%s: ", name);
+
+  if (interactive_shell == 0)
+    fprintf (stderr, _("line %d: "), executing_line_number ());
+
+  if (this_command_name && *this_command_name)
+    fprintf (stderr, "%s: ", this_command_name);
+}
+
+void
+#if defined (PREFER_STDARG)
+builtin_error (const char *format, ...)
+#else
+builtin_error (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  builtin_error_prolog ();
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+}
+
+void
+#if defined (PREFER_STDARG)
+builtin_warning (const char *format, ...)
+#else
+builtin_warning (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  builtin_error_prolog ();
+  fprintf (stderr, _("warning: "));
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+}
+
+/* Print a usage summary for the currently-executing builtin command. */
+void
+builtin_usage ()
+{
+  if (this_command_name && *this_command_name)
+    fprintf (stderr, _("%s: usage: "), this_command_name);
+  fprintf (stderr, "%s\n", _(current_builtin->short_doc));
+  fflush (stderr);
+}
+
+/* Return if LIST is NULL else barf and jump to top_level.  Used by some
+   builtins that do not accept arguments. */
+void
+no_args (list)
+     WORD_LIST *list;
+{
+  if (list)
+    {
+      builtin_error (_("too many arguments"));
+      top_level_cleanup ();
+      jump_to_top_level (DISCARD);
+    }
+}
+
+/* Check that no options were given to the currently-executing builtin,
+   and return 0 if there were options. */
+int
+no_options (list)
+     WORD_LIST *list;
+{
+  reset_internal_getopt ();
+  if (internal_getopt (list, "") != -1)
+    {
+      builtin_usage ();
+      return (1);
+    }
+  return (0);
+}
+
+void
+sh_needarg (s)
+     char *s;
+{
+  builtin_error (_("%s: option requires an argument"), s);
+}
+
+void
+sh_neednumarg (s)
+     char *s;
+{
+  builtin_error (_("%s: numeric argument required"), s);
+}
+
+void
+sh_notfound (s)
+     char *s;
+{
+  builtin_error (_("%s: not found"), s);
+}
+
+/* Function called when one of the builtin commands detects an invalid
+   option. */
+void
+sh_invalidopt (s)
+     char *s;
+{
+  builtin_error (_("%s: invalid option"), s);
+}
+
+void
+sh_invalidoptname (s)
+     char *s;
+{
+  builtin_error (_("%s: invalid option name"), s);
+}
+
+void
+sh_invalidid (s)
+     char *s;
+{
+  builtin_error (_("`%s': not a valid identifier"), s);
+}
+
+void
+sh_invalidnum (s)
+     char *s;
+{
+  char *msg;
+
+  if (*s == '0' && isdigit (s[1]))
+    msg = _("invalid octal number");
+  else if (*s == '0' && s[1] == 'x')
+    msg = _("invalid hex number");
+  else
+    msg = _("invalid number");
+  builtin_error ("%s: %s", s, msg);
+}
+
+void
+sh_invalidsig (s)
+     char *s;
+{
+  builtin_error (_("%s: invalid signal specification"), s);
+}
+
+void
+sh_badpid (s)
+     char *s;
+{
+  builtin_error (_("`%s': not a pid or valid job spec"), s);
+}
+
+void
+sh_readonly (s)
+     const char *s;
+{
+  builtin_error (_("%s: readonly variable"), s);
+itrace("sh_readonly: %d", getpid());
+  sleep (200);
+}
+
+void
+sh_erange (s, desc)
+     char *s, *desc;
+{
+  if (s)
+    builtin_error (_("%s: %s out of range"), s, desc ? desc : _("argument"));
+  else
+    builtin_error (_("%s out of range"), desc ? desc : _("argument"));
+}
+
+#if defined (JOB_CONTROL)
+void
+sh_badjob (s)
+     char *s;
+{
+  builtin_error (_("%s: no such job"), s);
+}
+
+void
+sh_nojobs (s)
+     char *s;
+{
+  if (s)
+    builtin_error (_("%s: no job control"), s);
+  else
+    builtin_error (_("no job control"));
+}
+#endif
+
+#if defined (RESTRICTED_SHELL)
+void
+sh_restricted (s)
+     char *s;
+{
+  if (s)
+    builtin_error (_("%s: restricted"), s);
+  else
+    builtin_error (_("restricted"));
+}
+#endif
+
+void
+sh_notbuiltin (s)
+     char *s;
+{
+  builtin_error (_("%s: not a shell builtin"), s);
+}
+
+void
+sh_wrerror ()
+{
+#if defined (DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS) && defined (EPIPE)
+  if (errno != EPIPE)
+#endif /* DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS && EPIPE */
+  builtin_error (_("write error: %s"), strerror (errno));
+}
+
+void
+sh_ttyerror (set)
+     int set;
+{
+  if (set)
+    builtin_error (_("error setting terminal attributes: %s"), strerror (errno));
+  else
+    builtin_error (_("error getting terminal attributes: %s"), strerror (errno));
+}
+
+int
+sh_chkwrite (s)
+     int s;
+{
+  fflush (stdout);
+  if (ferror (stdout))
+    {
+      sh_wrerror ();
+      fpurge (stdout);
+      clearerr (stdout);
+      return (EXECUTION_FAILURE);
+    }
+  return (s);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*          Shell positional parameter manipulation                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Convert a WORD_LIST into a C-style argv.  Return the number of elements
+   in the list in *IP, if IP is non-null.  A convenience function for
+   loadable builtins; also used by `test'. */
+char **
+make_builtin_argv (list, ip)
+     WORD_LIST *list;
+     int *ip;
+{
+  char **argv;
+
+  argv = strvec_from_word_list (list, 0, 1, ip);
+  argv[0] = this_command_name;
+  return argv;
+}
+
+/* Remember LIST in $1 ... $9, and REST_OF_ARGS.  If DESTRUCTIVE is
+   non-zero, then discard whatever the existing arguments are, else
+   only discard the ones that are to be replaced. */
+void
+remember_args (list, destructive)
+     WORD_LIST *list;
+     int destructive;
+{
+  register int i;
+
+  for (i = 1; i < 10; i++)
+    {
+      if ((destructive || list) && dollar_vars[i])
+       {
+         free (dollar_vars[i]);
+         dollar_vars[i] = (char *)NULL;
+       }
+
+      if (list)
+       {
+         dollar_vars[i] = savestring (list->word->word);
+         list = list->next;
+       }
+    }
+
+  /* If arguments remain, assign them to REST_OF_ARGS.
+     Note that copy_word_list (NULL) returns NULL, and
+     that dispose_words (NULL) does nothing. */
+  if (destructive || list)
+    {
+      dispose_words (rest_of_args);
+      rest_of_args = copy_word_list (list);
+    }
+
+  if (destructive)
+    set_dollar_vars_changed ();
+}
+
+static int changed_dollar_vars;
+
+/* Have the dollar variables been reset to new values since we last
+   checked? */
+int
+dollar_vars_changed ()
+{
+  return (changed_dollar_vars);
+}
+
+void
+set_dollar_vars_unchanged ()
+{
+  changed_dollar_vars = 0;
+}
+
+void
+set_dollar_vars_changed ()
+{
+  if (variable_context)
+    changed_dollar_vars |= ARGS_FUNC;
+  else if (this_shell_builtin == set_builtin)
+    changed_dollar_vars |= ARGS_SETBLTIN;
+  else
+    changed_dollar_vars |= ARGS_INVOC;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Validating numeric input and arguments              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Read a numeric arg for this_command_name, the name of the shell builtin
+   that wants it.  LIST is the word list that the arg is to come from.
+   Accept only the numeric argument; report an error if other arguments
+   follow.  If FATAL is 1, call throw_to_top_level, which exits the
+   shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the
+   current command; if FATAL is 0, return an indication of an invalid
+   number by setting *NUMOK == 0 and return -1. */
+int
+get_numeric_arg (list, fatal, count)
+     WORD_LIST *list;
+     int fatal;
+     intmax_t *count;
+{
+  char *arg;
+
+  if (count)
+    *count = 1;
+
+  if (list && list->word && ISOPTION (list->word->word, '-'))
+    list = list->next;
+
+  if (list)
+    {
+      arg = list->word->word;
+      if (arg == 0 || (legal_number (arg, count) == 0))
+       {
+         sh_neednumarg (list->word->word ? list->word->word : "`'");
+         if (fatal == 0)
+           return 0;
+         else if (fatal == 1)          /* fatal == 1; abort */
+           throw_to_top_level ();
+         else                          /* fatal == 2; discard current command */
+           {
+             top_level_cleanup ();
+             jump_to_top_level (DISCARD);
+           }
+       }
+      no_args (list->next);
+    }
+
+  return (1);
+}
+
+/* Get an eight-bit status value from LIST */
+int
+get_exitstat (list)
+     WORD_LIST *list;
+{
+  int status;
+  intmax_t sval;
+  char *arg;
+
+  if (list && list->word && ISOPTION (list->word->word, '-'))
+    list = list->next;
+
+  if (list == 0)
+    return (last_command_exit_value);      
+
+  arg = list->word->word;
+  if (arg == 0 || legal_number (arg, &sval) == 0)
+    {
+      sh_neednumarg (list->word->word ? list->word->word : "`'");
+      return EX_BADUSAGE;
+    }
+  no_args (list->next);
+
+  status = sval & 255;
+  return status;
+}
+
+/* Return the octal number parsed from STRING, or -1 to indicate
+   that the string contained a bad number. */
+int
+read_octal (string)
+     char *string;
+{
+  int result, digits;
+
+  result = digits = 0;
+  while (*string && ISOCTAL (*string))
+    {
+      digits++;
+      result = (result * 8) + (*string++ - '0');
+      if (result > 0777)
+       return -1;
+    }
+
+  if (digits == 0 || *string)
+    result = -1;
+
+  return (result);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*          Manipulating the current working directory             */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Return a consed string which is the current working directory.
+   FOR_WHOM is the name of the caller for error printing.  */
+char *the_current_working_directory = (char *)NULL;
+
+char *
+get_working_directory (for_whom)
+     char *for_whom;
+{
+  if (no_symbolic_links)
+    {
+      FREE (the_current_working_directory);
+      the_current_working_directory = (char *)NULL;
+    }
+
+  if (the_current_working_directory == 0)
+    {
+#if defined (GETCWD_BROKEN)
+      the_current_working_directory = getcwd (0, PATH_MAX);
+#else
+      the_current_working_directory = getcwd (0, 0);
+#endif
+      if (the_current_working_directory == 0)
+       {
+         fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"),
+                  (for_whom && *for_whom) ? for_whom : get_name_for_error (),
+                  _(bash_getcwd_errstr), strerror (errno));
+         return (char *)NULL;
+       }
+    }
+
+  return (savestring (the_current_working_directory));
+}
+
+/* Make NAME our internal idea of the current working directory. */
+void
+set_working_directory (name)
+     char *name;
+{
+  FREE (the_current_working_directory);
+  the_current_working_directory = savestring (name);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Job control support functions                       */
+/*                                                                 */
+/* **************************************************************** */
+
+#if defined (JOB_CONTROL)
+int
+get_job_by_name (name, flags)
+     const char *name;
+     int flags;
+{
+  register int i, wl, cl, match, job;
+  register PROCESS *p;
+  register JOB *j;
+
+  job = NO_JOB;
+  wl = strlen (name);
+  for (i = js.j_jobslots - 1; i >= 0; i--)
+    {
+      j = get_job_by_jid (i);
+      if (j == 0 || ((flags & JM_STOPPED) && J_JOBSTATE(j) != JSTOPPED))
+        continue;
+
+      p = j->pipe;
+      do
+        {
+         if (flags & JM_EXACT)
+           {
+             cl = strlen (p->command);
+             match = STREQN (p->command, name, cl);
+           }
+         else if (flags & JM_SUBSTRING)
+           match = strcasestr (p->command, name) != (char *)0;
+         else
+           match = STREQN (p->command, name, wl);
+
+         if (match == 0)
+           {
+             p = p->next;
+             continue;
+           }
+         else if (flags & JM_FIRSTMATCH)
+           return i;           /* return first match */
+         else if (job != NO_JOB)
+           {
+             if (this_shell_builtin)
+               builtin_error (_("%s: ambiguous job spec"), name);
+             else
+               report_error (_("%s: ambiguous job spec"), name);
+             return (DUP_JOB);
+           }
+         else
+           job = i;
+        }
+      while (p != j->pipe);
+    }
+
+  return (job);
+}
+
+/* Return the job spec found in LIST. */
+int
+get_job_spec (list)
+     WORD_LIST *list;
+{
+  register char *word;
+  int job, jflags;
+
+  if (list == 0)
+    return (js.j_current);
+
+  word = list->word->word;
+
+  if (*word == '\0')
+    return (NO_JOB);
+
+  if (*word == '%')
+    word++;
+
+  if (DIGIT (*word) && all_digits (word))
+    {
+      job = atoi (word);
+      return (job > js.j_jobslots ? NO_JOB : job - 1);
+    }
+
+  jflags = 0;
+  switch (*word)
+    {
+    case 0:
+    case '%':
+    case '+':
+      return (js.j_current);
+
+    case '-':
+      return (js.j_previous);
+
+    case '?':                  /* Substring search requested. */
+      jflags |= JM_SUBSTRING;
+      word++;
+      /* FALLTHROUGH */
+
+    default:
+      return get_job_by_name (word, jflags);
+    }
+}
+#endif /* JOB_CONTROL */
+
+/*
+ * NOTE:  `kill' calls this function with forcecols == 0
+ */
+int
+display_signal_list (list, forcecols)
+     WORD_LIST *list;
+     int forcecols;
+{
+  register int i, column;
+  char *name;
+  int result, signum, dflags;
+  intmax_t lsignum;
+
+  result = EXECUTION_SUCCESS;
+  if (!list)
+    {
+      for (i = 1, column = 0; i < NSIG; i++)
+       {
+         name = signal_name (i);
+         if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
+           continue;
+
+         if (posixly_correct && !forcecols)
+           {
+             /* This is for the kill builtin.  POSIX.2 says the signal names
+                are displayed without the `SIG' prefix. */
+             if (STREQN (name, "SIG", 3))
+               name += 3;
+             printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
+           }
+         else
+           {
+             printf ("%2d) %s", i, name);
+
+             if (++column < 5)
+               printf ("\t");
+             else
+               {
+                 printf ("\n");
+                 column = 0;
+               }
+           }
+       }
+
+      if ((posixly_correct && !forcecols) || column != 0)
+       printf ("\n");
+      return result;
+    }
+
+  /* List individual signal names or numbers. */
+  while (list)
+    {
+      if (legal_number (list->word->word, &lsignum))
+       {
+         /* This is specified by Posix.2 so that exit statuses can be
+            mapped into signal numbers. */
+         if (lsignum > 128)
+           lsignum -= 128;
+         if (lsignum < 0 || lsignum >= NSIG)
+           {
+             sh_invalidsig (list->word->word);
+             result = EXECUTION_FAILURE;
+             list = list->next;
+             continue;
+           }
+
+         signum = lsignum;
+         name = signal_name (signum);
+         if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
+           {
+             list = list->next;
+             continue;
+           }
+#if defined (JOB_CONTROL)
+         /* POSIX.2 says that `kill -l signum' prints the signal name without
+            the `SIG' prefix. */
+         printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
+#else
+         printf ("%s\n", name);
+#endif
+       }
+      else
+       {
+         dflags = DSIG_NOCASE;
+         if (posixly_correct == 0 || this_shell_builtin != kill_builtin)
+           dflags |= DSIG_SIGPREFIX;
+         signum = decode_signal (list->word->word, dflags);
+         if (signum == NO_SIG)
+           {
+             sh_invalidsig (list->word->word);
+             result = EXECUTION_FAILURE;
+             list = list->next;
+             continue;
+           }
+         printf ("%d\n", signum);
+       }
+      list = list->next;
+    }
+  return (result);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*         Finding builtin commands and their functions            */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Perform a binary search and return the address of the builtin function
+   whose name is NAME.  If the function couldn't be found, or the builtin
+   is disabled or has no function associated with it, return NULL.
+   Return the address of the builtin.
+   DISABLED_OKAY means find it even if the builtin is disabled. */
+struct builtin *
+builtin_address_internal (name, disabled_okay)
+     char *name;
+     int disabled_okay;
+{
+  int hi, lo, mid, j;
+
+  hi = num_shell_builtins - 1;
+  lo = 0;
+
+  while (lo <= hi)
+    {
+      mid = (lo + hi) / 2;
+
+      j = shell_builtins[mid].name[0] - name[0];
+
+      if (j == 0)
+       j = strcmp (shell_builtins[mid].name, name);
+
+      if (j == 0)
+       {
+         /* It must have a function pointer.  It must be enabled, or we
+            must have explicitly allowed disabled functions to be found,
+            and it must not have been deleted. */
+         if (shell_builtins[mid].function &&
+             ((shell_builtins[mid].flags & BUILTIN_DELETED) == 0) &&
+             ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
+           return (&shell_builtins[mid]);
+         else
+           return ((struct builtin *)NULL);
+       }
+      if (j > 0)
+       hi = mid - 1;
+      else
+       lo = mid + 1;
+    }
+  return ((struct builtin *)NULL);
+}
+
+/* Return the pointer to the function implementing builtin command NAME. */
+sh_builtin_func_t *
+find_shell_builtin (name)
+     char *name;
+{
+  current_builtin = builtin_address_internal (name, 0);
+  return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
+}
+
+/* Return the address of builtin with NAME, whether it is enabled or not. */
+sh_builtin_func_t *
+builtin_address (name)
+     char *name;
+{
+  current_builtin = builtin_address_internal (name, 1);
+  return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
+}
+
+/* Return the function implementing the builtin NAME, but only if it is a
+   POSIX.2 special builtin. */
+sh_builtin_func_t *
+find_special_builtin (name)
+     char *name;
+{
+  current_builtin = builtin_address_internal (name, 0);
+  return ((current_builtin && (current_builtin->flags & SPECIAL_BUILTIN)) ?
+                       current_builtin->function :
+                       (sh_builtin_func_t *)NULL);
+}
+  
+static int
+shell_builtin_compare (sbp1, sbp2)
+     struct builtin *sbp1, *sbp2;
+{
+  int result;
+
+  if ((result = sbp1->name[0] - sbp2->name[0]) == 0)
+    result = strcmp (sbp1->name, sbp2->name);
+
+  return (result);
+}
+
+/* Sort the table of shell builtins so that the binary search will work
+   in find_shell_builtin. */
+void
+initialize_shell_builtins ()
+{
+  qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
+    (QSFUNC *)shell_builtin_compare);
+}
diff --git a/builtins/set.def~ b/builtins/set.def~
new file mode 100644 (file)
index 0000000..b0939bf
--- /dev/null
@@ -0,0 +1,859 @@
+This file is set.def, from which is created set.c.
+It implements the "set" and "unset" builtins in Bash.
+
+Copyright (C) 1987-2009 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+
+$PRODUCES set.c
+
+#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 "../flags.h"
+#include "common.h"
+#include "bashgetopt.h"
+
+#if defined (READLINE)
+#  include "../input.h"
+#  include "../bashline.h"
+#  include <readline/readline.h>
+#endif
+
+#if defined (HISTORY)
+#  include "../bashhist.h"
+#endif
+
+extern int posixly_correct, ignoreeof, eof_encountered_limit;
+#if defined (HISTORY)
+extern int dont_save_function_defs;
+#endif
+#if defined (READLINE)
+extern int no_line_editing;
+#endif /* READLINE */
+
+$BUILTIN set
+$FUNCTION set_builtin
+$SHORT_DOC set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
+Set or unset values of shell options and positional parameters.
+
+Change the value of shell attributes and positional parameters, or
+display the names and values of shell variables.
+
+Options:
+  -a  Mark variables which are modified or created for export.
+  -b  Notify of job termination immediately.
+  -e  Exit immediately if a command exits with a non-zero status.
+  -f  Disable file name generation (globbing).
+  -h  Remember the location of commands as they are looked up.
+  -k  All assignment arguments are placed in the environment for a
+      command, not just those that precede the command name.
+  -m  Job control is enabled.
+  -n  Read commands but do not execute them.
+  -o option-name
+      Set the variable corresponding to option-name:
+          allexport    same as -a
+          braceexpand  same as -B
+#if defined (READLINE)
+          emacs        use an emacs-style line editing interface
+#endif /* READLINE */
+          errexit      same as -e
+          errtrace     same as -E
+          functrace    same as -T
+          hashall      same as -h
+#if defined (BANG_HISTORY)
+          histexpand   same as -H
+#endif /* BANG_HISTORY */
+#if defined (HISTORY)
+          history      enable command history
+#endif
+          ignoreeof    the shell will not exit upon reading EOF
+          interactive-comments
+                       allow comments to appear in interactive commands
+          keyword      same as -k
+          monitor      same as -m
+          noclobber    same as -C
+          noexec       same as -n
+          noglob       same as -f
+          nolog        currently accepted but ignored
+          notify       same as -b
+          nounset      same as -u
+          onecmd       same as -t
+          physical     same as -P
+          pipefail     the return value of a pipeline is the status of
+                       the last command to exit with a non-zero status,
+                       or zero if no command exited with a non-zero status
+          posix        change the behavior of bash where the default
+                       operation differs from the Posix standard to
+                       match the standard
+          privileged   same as -p
+          verbose      same as -v
+#if defined (READLINE)
+          vi           use a vi-style line editing interface
+#endif /* READLINE */
+          xtrace       same as -x
+  -p  Turned on whenever the real and effective user ids do not match.
+      Disables processing of the $ENV file and importing of shell
+      functions.  Turning this option off causes the effective uid and
+      gid to be set to the real uid and gid.
+  -t  Exit after reading and executing one command.
+  -u  Treat unset variables as an error when substituting.
+  -v  Print shell input lines as they are read.
+  -x  Print commands and their arguments as they are executed.
+#if defined (BRACE_EXPANSION)
+  -B  the shell will perform brace expansion
+#endif /* BRACE_EXPANSION */
+  -C  If set, disallow existing regular files to be overwritten
+      by redirection of output.
+  -E  If set, the ERR trap is inherited by shell functions.
+#if defined (BANG_HISTORY)
+  -H  Enable ! style history substitution.  This flag is on
+      by default when the shell is interactive.
+#endif /* BANG_HISTORY */
+  -P  If set, do not follow symbolic links when executing commands
+      such as cd which change the current directory.
+  -T  If set, the DEBUG trap is inherited by shell functions.
+  --  Assign any remaining arguments to the positional parameters.
+      If there are no remaining arguments, the positional parameters
+      are unset.
+  -   Assign any remaining arguments to the positional parameters.
+      The -x and -v options are turned off.
+
+Using + rather than - causes these flags to be turned off.  The
+flags can also be used upon invocation of the shell.  The current
+set of flags may be found in $-.  The remaining n ARGs are positional
+parameters and are assigned, in order, to $1, $2, .. $n.  If no
+ARGs are given, all shell variables are printed.
+
+Exit Status:
+Returns success unless an invalid option is given.
+$END
+
+typedef int setopt_set_func_t __P((int, char *));
+typedef int setopt_get_func_t __P((char *));
+
+static void print_minus_o_option __P((char *, int, int));
+static void print_all_shell_variables __P((void));
+
+static int set_ignoreeof __P((int, char *));
+static int set_posix_mode __P((int, char *));
+
+#if defined (READLINE)
+static int set_edit_mode __P((int, char *));
+static int get_edit_mode __P((char *));
+#endif
+
+#if defined (HISTORY)
+static int bash_set_history __P((int, char *));
+#endif
+
+static const char * const on = "on";
+static const char * const off = "off";
+
+/* A struct used to match long options for set -o to the corresponding
+   option letter or internal variable.  The functions can be called to
+   dynamically generate values. */
+const struct {
+  char *name;
+  int letter;
+  int *variable;
+  setopt_set_func_t *set_func;
+  setopt_get_func_t *get_func;
+} o_options[] = {
+  { "allexport",  'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+#if defined (BRACE_EXPANSION)
+  { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#endif
+#if defined (READLINE)
+  { "emacs",     '\0', (int *)NULL, set_edit_mode, get_edit_mode },
+#endif
+  { "errexit",   'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "errtrace",          'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "functrace",  'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "hashall",    'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#if defined (BANG_HISTORY)
+  { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#endif /* BANG_HISTORY */
+#if defined (HISTORY)
+  { "history",   '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
+#endif
+  { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
+  { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "keyword",    'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "monitor",   'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noclobber",  'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noexec",    'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "noglob",    'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#if defined (HISTORY)
+  { "nolog",     '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+#endif
+#if defined (JOB_CONTROL)
+  { "notify",    'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#endif /* JOB_CONTROL */
+  { "nounset",   'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "onecmd",    't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+  { "physical",   'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "pipefail",  '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "posix",     '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
+  { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  { "verbose",   'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+#if defined (READLINE)
+  { "vi",        '\0', (int *)NULL, set_edit_mode, get_edit_mode },
+#endif
+  { "xtrace",    'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL  },
+  {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+};
+
+#define N_O_OPTIONS    (sizeof (o_options) / sizeof (o_options[0]))
+
+#define GET_BINARY_O_OPTION_VALUE(i, name) \
+  ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
+                          : (*o_options[i].variable))
+
+#define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
+  ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
+                          : (*o_options[i].variable = (onoff == FLAG_ON)))
+
+int
+minus_o_option_value (name)
+     char *name;
+{
+  register int i;
+  int *on_or_off;
+
+  for (i = 0; o_options[i].name; i++)
+    {
+      if (STREQ (name, o_options[i].name))
+       {
+         if (o_options[i].letter)
+           {
+             on_or_off = find_flag (o_options[i].letter);
+             return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
+           }
+         else
+           return (GET_BINARY_O_OPTION_VALUE (i, name));
+       }
+    }
+
+  return (-1);
+}
+
+#define MINUS_O_FORMAT "%-15s\t%s\n"
+
+static void
+print_minus_o_option (name, value, pflag)
+     char *name;
+     int value, pflag;
+{
+  if (pflag == 0)
+    printf (MINUS_O_FORMAT, name, value ? on : off);
+  else
+    printf ("set %co %s\n", value ? '-' : '+', name);
+}
+
+void
+list_minus_o_opts (mode, reusable)
+     int mode, reusable;
+{
+  register int i;
+  int *on_or_off, value;
+
+  for (i = 0; o_options[i].name; i++)
+    {
+      if (o_options[i].letter)
+       {
+         value = 0;
+         on_or_off = find_flag (o_options[i].letter);
+         if (on_or_off == FLAG_UNKNOWN)
+           on_or_off = &value;
+         if (mode == -1 || mode == *on_or_off)
+           print_minus_o_option (o_options[i].name, *on_or_off, reusable);
+       }
+      else
+       {
+         value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
+         if (mode == -1 || mode == value)
+           print_minus_o_option (o_options[i].name, value, reusable);
+       }
+    }
+}
+
+char **
+get_minus_o_opts ()
+{
+  char **ret;
+  int i;
+
+  ret = strvec_create (N_O_OPTIONS + 1);
+  for (i = 0; o_options[i].name; i++)
+    ret[i] = o_options[i].name;
+  ret[i] = (char *)NULL;
+  return ret;
+}
+
+static int
+set_ignoreeof (on_or_off, option_name)
+     int on_or_off;
+     char *option_name;
+{
+  ignoreeof = on_or_off == FLAG_ON;
+  unbind_variable ("ignoreeof");
+  if (ignoreeof)
+    bind_variable ("IGNOREEOF", "10", 0); 
+  else
+    unbind_variable ("IGNOREEOF");
+  sv_ignoreeof ("IGNOREEOF");
+  return 0;
+}
+
+static int
+set_posix_mode (on_or_off, option_name)
+     int on_or_off;
+     char *option_name;
+{
+  posixly_correct = on_or_off == FLAG_ON;
+  if (posixly_correct == 0)
+    unbind_variable ("POSIXLY_CORRECT");
+  else
+    bind_variable ("POSIXLY_CORRECT", "y", 0);
+  sv_strict_posix ("POSIXLY_CORRECT");
+  return (0);
+}
+
+#if defined (READLINE)
+/* Magic.  This code `knows' how readline handles rl_editing_mode. */
+static int
+set_edit_mode (on_or_off, option_name)
+     int on_or_off;
+     char *option_name;
+{
+  int isemacs;
+
+  if (on_or_off == FLAG_ON)
+    {
+      rl_variable_bind ("editing-mode", option_name);
+
+      if (interactive)
+       with_input_from_stdin ();
+      no_line_editing = 0;
+    }
+  else
+    {
+      isemacs = rl_editing_mode == 1;
+      if ((isemacs && *option_name == 'e') || (!isemacs && *option_name == 'v'))
+       {
+         if (interactive)
+           with_input_from_stream (stdin, "stdin");
+         no_line_editing = 1;
+       }
+    }
+  return 1-no_line_editing;
+}
+
+static int
+get_edit_mode (name)
+     char *name;
+{
+  return (*name == 'e' ? no_line_editing == 0 && rl_editing_mode == 1
+                      : no_line_editing == 0 && rl_editing_mode == 0);
+}
+#endif /* READLINE */
+
+#if defined (HISTORY)
+static int
+bash_set_history (on_or_off, option_name)
+     int on_or_off;
+     char *option_name;
+{
+  if (on_or_off == FLAG_ON)
+    {
+      enable_history_list = 1;
+      bash_history_enable ();
+      if (history_lines_this_session == 0)
+       load_history ();
+    }
+  else
+    {
+      enable_history_list = 0;
+      bash_history_disable ();
+    }
+  return (1 - enable_history_list);
+}
+#endif
+
+int
+set_minus_o_option (on_or_off, option_name)
+     int on_or_off;
+     char *option_name;
+{
+  register int i;
+
+  for (i = 0; o_options[i].name; i++)
+    {
+      if (STREQ (option_name, o_options[i].name))
+       {
+         if (o_options[i].letter == 0)
+           {
+             SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
+             return (EXECUTION_SUCCESS);
+           }
+         else
+           {
+             if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
+               {
+                 sh_invalidoptname (option_name);
+                 return (EXECUTION_FAILURE);
+               }
+             else
+               return (EXECUTION_SUCCESS);
+           }
+
+       }
+    }
+
+  sh_invalidoptname (option_name);
+  return (EX_USAGE);
+}
+
+static void
+print_all_shell_variables ()
+{
+  SHELL_VAR **vars;
+
+  vars = all_shell_variables ();
+  if (vars)
+    {
+      print_var_list (vars);
+      free (vars);
+    }
+
+  /* POSIX.2 does not allow function names and definitions to be output when
+     `set' is invoked without options (PASC Interp #202). */
+  if (posixly_correct == 0)
+    {
+      vars = all_shell_functions ();
+      if (vars)
+       {
+         print_func_list (vars);
+         free (vars);
+       }
+    }
+}
+
+void
+set_shellopts ()
+{
+  char *value;
+  char tflag[N_O_OPTIONS];
+  int vsize, i, vptr, *ip, exported;
+  SHELL_VAR *v;
+
+itrace("set_shellopts: entry");
+  for (vsize = i = 0; o_options[i].name; i++)
+    {
+      tflag[i] = 0;
+      if (o_options[i].letter)
+       {
+         ip = find_flag (o_options[i].letter);
+         if (ip && *ip)
+           {
+             vsize += strlen (o_options[i].name) + 1;
+             tflag[i] = 1;
+           }
+       }
+      else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
+       {
+         vsize += strlen (o_options[i].name) + 1;
+         tflag[i] = 1;
+       }
+    }
+
+  value = (char *)xmalloc (vsize + 1);
+
+  for (i = vptr = 0; o_options[i].name; i++)
+    {
+      if (tflag[i])
+       {
+         strcpy (value + vptr, o_options[i].name);
+         vptr += strlen (o_options[i].name);
+         value[vptr++] = ':';
+       }
+    }
+
+  if (vptr)
+    vptr--;                    /* cut off trailing colon */
+  value[vptr] = '\0';
+
+  v = find_variable ("SHELLOPTS");
+itrace("set_shellopts: v = %p", v);
+  /* Turn off the read-only attribute so we can bind the new value, and
+     note whether or not the variable was exported. */
+  if (v)
+    {
+      VUNSETATTR (v, att_readonly);
+      exported = exported_p (v);
+    }
+  else
+    exported = 0;
+
+  v = bind_variable ("SHELLOPTS", value, 0);
+
+  /* Turn the read-only attribute back on, and turn off the export attribute
+     if it was set implicitly by mark_modified_vars and SHELLOPTS was not
+     exported before we bound the new value. */
+  VSETATTR (v, att_readonly);
+  if (mark_modified_vars && exported == 0 && exported_p (v))
+    VUNSETATTR (v, att_exported);
+
+  free (value);
+itrace("set_shellopts: return");
+}
+
+void
+parse_shellopts (value)
+     char *value;
+{
+  char *vname;
+  int vptr;
+
+  vptr = 0;
+  while (vname = extract_colon_unit (value, &vptr))
+    {
+      set_minus_o_option (FLAG_ON, vname);
+      free (vname);
+    }
+}
+
+void
+initialize_shell_options (no_shellopts)
+     int no_shellopts;
+{
+  char *temp;
+  SHELL_VAR *var;
+
+  if (no_shellopts == 0)
+    {
+      var = find_variable ("SHELLOPTS");
+      /* set up any shell options we may have inherited. */
+      if (var && imported_p (var))
+       {
+         temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
+         if (temp)
+           {
+             parse_shellopts (temp);
+             free (temp);
+           }
+       }
+    }
+
+  /* Set up the $SHELLOPTS variable. */
+  set_shellopts ();
+}
+
+/* Reset the values of the -o options that are not also shell flags.  This is
+   called from execute_cmd.c:initialize_subshell() when setting up a subshell
+   to run an executable shell script without a leading `#!'. */
+void
+reset_shell_options ()
+{
+#if defined (HISTORY)
+  remember_on_history = enable_history_list = 1;
+#endif
+  ignoreeof = 0;
+}
+
+/* Set some flags from the word values in the input list.  If LIST is empty,
+   then print out the values of the variables instead.  If LIST contains
+   non-flags, then set $1 - $9 to the successive words of LIST. */
+int
+set_builtin (list)
+     WORD_LIST *list;
+{
+  int on_or_off, flag_name, force_assignment, opts_changed, rv, r;
+  register char *arg;
+  char s[3];
+
+  if (list == 0)
+    {
+      print_all_shell_variables ();
+      return (sh_chkwrite (EXECUTION_SUCCESS));
+    }
+
+  /* Check validity of flag arguments. */
+  rv = EXECUTION_SUCCESS;
+  reset_internal_getopt ();
+  while ((flag_name = internal_getopt (list, optflags)) != -1)
+    {
+      switch (flag_name)
+       {
+         case '?':
+           builtin_usage ();
+           return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
+         default:
+           break;
+       }
+    }
+    
+  /* Do the set command.  While the list consists of words starting with
+     '-' or '+' treat them as flags, otherwise, start assigning them to
+     $1 ... $n. */
+  for (force_assignment = opts_changed = 0; list; )
+    {
+      arg = list->word->word;
+
+      /* If the argument is `--' or `-' then signal the end of the list
+        and remember the remaining arguments. */
+      if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
+       {
+         list = list->next;
+
+         /* `set --' unsets the positional parameters. */
+         if (arg[1] == '-')
+           force_assignment = 1;
+
+         /* Until told differently, the old shell behaviour of
+            `set - [arg ...]' being equivalent to `set +xv [arg ...]'
+            stands.  Posix.2 says the behaviour is marked as obsolescent. */
+         else
+           {
+             change_flag ('x', '+');
+             change_flag ('v', '+');
+             opts_changed = 1;
+           }
+
+         break;
+       }
+
+      if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
+       {
+         while (flag_name = *++arg)
+           {
+             if (flag_name == '?')
+               {
+                 builtin_usage ();
+                 return (EXECUTION_SUCCESS);
+               }
+             else if (flag_name == 'o') /* -+o option-name */
+               {
+                 char *option_name;
+                 WORD_LIST *opt;
+
+                 opt = list->next;
+
+                 if (opt == 0)
+                   {
+                     list_minus_o_opts (-1, (on_or_off == '+'));
+                     rv = sh_chkwrite (rv);
+                     continue;
+                   }
+
+                 option_name = opt->word->word;
+
+                 if (option_name == 0 || *option_name == '\0' ||
+                     *option_name == '-' || *option_name == '+')
+                   {
+                     list_minus_o_opts (-1, (on_or_off == '+'));
+                     continue;
+                   }
+                 list = list->next; /* Skip over option name. */
+
+                 opts_changed = 1;
+                 if ((r = set_minus_o_option (on_or_off, option_name)) != EXECUTION_SUCCESS)
+                   {
+                     set_shellopts ();
+                     return (r);
+                   }
+               }
+             else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
+               {
+                 s[0] = on_or_off;
+                 s[1] = flag_name;
+                 s[2] = '\0';
+                 sh_invalidopt (s);
+                 builtin_usage ();
+                 set_shellopts ();
+                 return (EXECUTION_FAILURE);
+               }
+             opts_changed = 1;
+           }
+       }
+      else
+       {
+         break;
+       }
+      list = list->next;
+    }
+
+  /* Assigning $1 ... $n */
+  if (list || force_assignment)
+    remember_args (list, 1);
+  /* Set up new value of $SHELLOPTS */
+  if (opts_changed)
+    set_shellopts ();
+  return (rv);
+}
+
+$BUILTIN unset
+$FUNCTION unset_builtin
+$SHORT_DOC unset [-f] [-v] [name ...]
+Unset values and attributes of shell variables and functions.
+
+For each NAME, remove the corresponding variable or function.
+
+Options:
+  -f   treat each NAME as a shell function
+  -v   treat each NAME as a shell variable
+
+Without options, unset first tries to unset a variable, and if that fails,
+tries to unset a function.
+
+Some variables cannot be unset; also see `readonly'.
+
+Exit Status:
+Returns success unless an invalid option is given or a NAME is read-only.
+$END
+
+#define NEXT_VARIABLE()        any_failed++; list = list->next; continue;
+
+int
+unset_builtin (list)
+  WORD_LIST *list;
+{
+  int unset_function, unset_variable, unset_array, opt, any_failed;
+  char *name;
+
+  unset_function = unset_variable = unset_array = any_failed = 0;
+
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "fv")) != -1)
+    {
+      switch (opt)
+       {
+       case 'f':
+         unset_function = 1;
+         break;
+       case 'v':
+         unset_variable = 1;
+         break;
+       default:
+         builtin_usage ();
+         return (EX_USAGE);
+       }
+    }
+
+  list = loptend;
+
+  if (unset_function && unset_variable)
+    {
+      builtin_error (_("cannot simultaneously unset a function and a variable"));
+      return (EXECUTION_FAILURE);
+    }
+
+  while (list)
+    {
+      SHELL_VAR *var;
+      int tem;
+#if defined (ARRAY_VARS)
+      char *t;
+#endif
+
+      name = list->word->word;
+
+#if defined (ARRAY_VARS)
+      unset_array = 0;
+      if (!unset_function && valid_array_reference (name))
+       {
+         t = strchr (name, '[');
+         *t++ = '\0';
+         unset_array++;
+       }
+#endif
+
+      /* Bash allows functions with names which are not valid identifiers
+        to be created when not in posix mode, so check only when in posix
+        mode when unsetting a function. */
+      if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
+       {
+         sh_invalidid (name);
+         NEXT_VARIABLE ();
+       }
+
+      var = unset_function ? find_function (name) : find_variable (name);
+
+      if (var && !unset_function && non_unsettable_p (var))
+       {
+         builtin_error (_("%s: cannot unset"), name);
+         NEXT_VARIABLE ();
+       }
+
+      /* Posix.2 says that unsetting readonly variables is an error. */
+      if (var && readonly_p (var))
+       {
+         builtin_error (_("%s: cannot unset: readonly %s"),
+                        name, unset_function ? "function" : "variable");
+         NEXT_VARIABLE ();
+       }
+
+      /* Unless the -f option is supplied, the name refers to a variable. */
+#if defined (ARRAY_VARS)
+      if (var && unset_array)
+       {
+         if (array_p (var) == 0 && assoc_p (var) == 0)
+           {
+             builtin_error (_("%s: not an array variable"), name);
+             NEXT_VARIABLE ();
+           }
+         else
+           {
+             tem = unbind_array_element (var, t);
+             if (tem == -1)
+               any_failed++;
+           }
+       }
+      else
+#endif /* ARRAY_VARS */
+      tem = unset_function ? unbind_func (name) : unbind_variable (name);
+
+      /* This is what Posix.2 draft 11+ says.  ``If neither -f nor -v
+        is specified, the name refers to a variable; if a variable by
+        that name does not exist, a function by that name, if any,
+        shall be unset.'' */
+      if (tem == -1 && !unset_function && !unset_variable)
+       tem = unbind_func (name);
+
+      /* SUSv3, POSIX.1-2001 say:  ``Unsetting a variable or function that
+        was not previously set shall not be considered an error.'' */
+
+      if (unset_function == 0)
+       stupidly_hack_special_variables (name);
+
+      list = list->next;
+    }
+
+  return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+}
index bfe60293d4284d21ec86648b84d5f834c790c4aa..27e26ac05f555c8f854c6dda6cb0e7b057c4fa1e 100644 (file)
@@ -3560,7 +3560,10 @@ This is semantically equivalent to
 \fB>\fP\fIword\fP 2\fB>&\fP1
 .RE
 .PP
-(see \fBDuplicating File Descriptors\fP below).
+When using the second form, \fIword\fP may not expand to a number or
+\fB\-\fP.  If it does, other redirection operators apply
+(see \fBDuplicating File Descriptors\fP below) for compatibility
+reasons.
 .SS Appending Standard Output and Standard Error
 .PP
 This construct allows both the
@@ -3688,8 +3691,15 @@ is not specified, the standard output (file descriptor 1) is used.
 If the digits in
 .I word
 do not specify a file descriptor open for output, a redirection error occurs.
+If
+.I word
+evaluates to
+.BR \- ,
+file descriptor
+.I n
+is closed.
 As a special case, if \fIn\fP is omitted, and \fIword\fP does not
-expand to one or more digits, the standard output and standard
+expand to one or more digits or \fB\-\fP, the standard output and standard
 error are redirected as described previously.
 .SS "Moving File Descriptors"
 .PP
index 3a61ea4853626b0f386a12b7d70464ce0a95c11f..0a39cd34491de19a3ce18dd4047b0c0cc568642f 100644 (file)
@@ -965,6 +965,8 @@ That command is usually a \fIlist\fP of commands between { and }, but
 may be any command listed under \fBCompound Commands\fP above.
 \fIcompound\-command\fP is executed whenever \fIname\fP is specified as the
 name of a simple command.
+When in \fIposix mode\fP, \fIname\fP may not be the name of one of the
+POSIX \fIspecial builtins\fP.
 Any redirections (see
 .SM
 .B REDIRECTION
@@ -3686,8 +3688,15 @@ is not specified, the standard output (file descriptor 1) is used.
 If the digits in
 .I word
 do not specify a file descriptor open for output, a redirection error occurs.
+If
+.I word
+evaluates to
+.BR \- ,
+file descriptor
+.I n
+is closed.
 As a special case, if \fIn\fP is omitted, and \fIword\fP does not
-expand to one or more digits, the standard output and standard
+expand to one or more digits or \fB\-\fP, the standard output and standard
 error are redirected as described previously.
 .SS "Moving File Descriptors"
 .PP
index ec4cc91c58a68b502505cdcd14c590aaf76a6085..29a042163f454ac46804824237c9940144d15fc3 100644 (file)
@@ -2358,7 +2358,9 @@ This is semantically equivalent to
 @example
 >@var{word} 2>&1
 @end example
-(see Duplicating File Descriptors below).
+When using the second form, @var{word} may not expand to a number or
+@samp{-}.  If it does, other redirection operators apply
+(see Duplicating File Descriptors below) for compatibility reasons.
 
 @subsection Appending Standard Output and Standard Error
 This construct allows both the
@@ -2436,8 +2438,8 @@ is made to be a copy of that file descriptor.
 If the digits in @var{word} do not specify a file descriptor open for
 input, a redirection error occurs.
 If @var{word}
-evaluates to @samp{-}, file descriptor @var{n} is closed.  If
-@var{n} is not specified, the standard input (file descriptor 0) is used.
+evaluates to @samp{-}, file descriptor @var{n} is closed.
+If @var{n} is not specified, the standard input (file descriptor 0) is used.
 
 The operator
 @example
@@ -2448,8 +2450,10 @@ is used similarly to duplicate output file descriptors.  If
 @var{n} is not specified, the standard output (file descriptor 1) is used.
 If the digits in @var{word} do not specify a file descriptor open for
 output, a redirection error occurs.
+If @var{word}
+evaluates to @samp{-}, file descriptor @var{n} is closed.
 As a special case, if @var{n} is omitted, and @var{word} does not
-expand to one or more digits, the standard output and standard
+expand to one or more digits or @samp{-}, the standard output and standard
 error are redirected as described previously.
 
 @subsection Moving File Descriptors
index f5c83d5d4c1c19709d94d2196d8fc1206ec6cb5e..aeac19454e255f174f8c4dad16d01e4c55fb0dfb 100644 (file)
@@ -1262,6 +1262,9 @@ That command is usually a @var{list} enclosed between @{ and @}, but
 may be any compound command listed above.
 @var{compound-command} is executed whenever @var{name} is specified as the
 name of a command.
+When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}),
+@var{name} may not be the same as one of the special builtins
+(@pxref{Special Builtins}).
 Any redirections (@pxref{Redirections}) associated with the shell function
 are performed when the function is executed.
 
@@ -2433,8 +2436,8 @@ is made to be a copy of that file descriptor.
 If the digits in @var{word} do not specify a file descriptor open for
 input, a redirection error occurs.
 If @var{word}
-evaluates to @samp{-}, file descriptor @var{n} is closed.  If
-@var{n} is not specified, the standard input (file descriptor 0) is used.
+evaluates to @samp{-}, file descriptor @var{n} is closed.
+If @var{n} is not specified, the standard input (file descriptor 0) is used.
 
 The operator
 @example
@@ -2445,8 +2448,10 @@ is used similarly to duplicate output file descriptors.  If
 @var{n} is not specified, the standard output (file descriptor 1) is used.
 If the digits in @var{word} do not specify a file descriptor open for
 output, a redirection error occurs.
+If @var{word}
+evaluates to @samp{-}, file descriptor @var{n} is closed.
 As a special case, if @var{n} is omitted, and @var{word} does not
-expand to one or more digits, the standard output and standard
+expand to one or more digits or @samp{-}, the standard output and standard
 error are redirected as described previously.
 
 @subsection Moving File Descriptors
index 40b6027a7da1874f766a5939306ed5cd88a5dc4d..9af3395930df7ddf33b096af586de9b761fdc80b 100644 (file)
@@ -2,9 +2,9 @@
 Copyright (C) 1988-2011 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Sun Sep 25 22:01:31 EDT 2011
+@set LASTCHANGE Fri Oct 14 13:18:35 EDT 2011
 
 @set EDITION 4.2
 @set VERSION 4.2
-@set UPDATED 25 September 2011
-@set UPDATED-MONTH September 2011
+@set UPDATED 14 October 2011
+@set UPDATED-MONTH October 2011
index 872254658d87f1f1e0ec29267d41346a7ac3aefa..40b6027a7da1874f766a5939306ed5cd88a5dc4d 100644 (file)
@@ -2,9 +2,9 @@
 Copyright (C) 1988-2011 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Mon Sep 19 21:46:24 EDT 2011
+@set LASTCHANGE Sun Sep 25 22:01:31 EDT 2011
 
 @set EDITION 4.2
 @set VERSION 4.2
-@set UPDATED 19 September 2011
+@set UPDATED 25 September 2011
 @set UPDATED-MONTH September 2011
diff --git a/error.c~ b/error.c~
new file mode 100644 (file)
index 0000000..bcee176
--- /dev/null
+++ b/error.c~
@@ -0,0 +1,457 @@
+/* error.c -- Functions for handling errors. */
+
+/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "bashtypes.h"
+#include <fcntl.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#if defined (PREFER_STDARG)
+#  include <stdarg.h>
+#else
+#  include <varargs.h>
+#endif
+
+#include <stdio.h>
+
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "flags.h"
+#include "input.h"
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#endif
+
+extern int executing_line_number __P((void));
+
+extern int last_command_exit_value;
+extern char *shell_name;
+#if defined (JOB_CONTROL)
+extern pid_t shell_pgrp;
+extern int give_terminal_to __P((pid_t, int));
+#endif /* JOB_CONTROL */
+
+#if defined (ARRAY_VARS)
+extern const char * const bash_badsub_errmsg;
+#endif
+
+static void error_prolog __P((int));
+
+/* The current maintainer of the shell.  You change this in the
+   Makefile. */
+#if !defined (MAINTAINER)
+#define MAINTAINER "bash-maintainers@gnu.org"
+#endif
+
+const char * const the_current_maintainer = MAINTAINER;
+
+int gnu_error_format = 0;
+
+static void
+error_prolog (print_lineno)
+     int print_lineno;
+{
+  char *ename;
+  int line;
+
+  ename = get_name_for_error ();
+  line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1;
+
+  if (line > 0)
+    fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), line);
+  else
+    fprintf (stderr, "%s: ", ename);
+}
+
+/* Return the name of the shell or the shell script for error reporting. */
+char *
+get_name_for_error ()
+{
+  char *name;
+#if defined (ARRAY_VARS)
+  SHELL_VAR *bash_source_v;
+  ARRAY *bash_source_a;
+#endif
+
+  name = (char *)NULL;
+  if (interactive_shell == 0)
+    {
+#if defined (ARRAY_VARS)
+      bash_source_v = find_variable ("BASH_SOURCE");
+      if (bash_source_v && array_p (bash_source_v) &&
+         (bash_source_a = array_cell (bash_source_v)))
+       name = array_reference (bash_source_a, 0);
+      if (name == 0 || *name == '\0')  /* XXX - was just name == 0 */
+#endif
+       name = dollar_vars[0];
+    }
+  if (name == 0 && shell_name && *shell_name)
+    name = base_pathname (shell_name);
+  if (name == 0)
+#if defined (PROGRAM)
+    name = PROGRAM;
+#else
+    name = "bash";
+#endif
+
+  return (name);
+}
+
+/* Report an error having to do with FILENAME.  This does not use
+   sys_error so the filename is not interpreted as a printf-style
+   format string. */
+void
+file_error (filename)
+     const char *filename;
+{
+  report_error ("%s: %s", filename, strerror (errno));
+}
+
+void
+#if defined (PREFER_STDARG)
+programming_error (const char *format, ...)
+#else
+programming_error (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+  char *h;
+
+#if defined (JOB_CONTROL)
+  give_terminal_to (shell_pgrp, 0);
+#endif /* JOB_CONTROL */
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+  va_end (args);
+
+#if defined (HISTORY)
+  if (remember_on_history)
+    {
+      h = last_history_line ();
+      fprintf (stderr, _("last command: %s\n"), h ? h : "(null)");
+    }
+#endif
+
+#if 0
+  fprintf (stderr, "Report this to %s\n", the_current_maintainer);
+#endif
+
+  fprintf (stderr, _("Aborting..."));
+  fflush (stderr);
+
+  abort ();
+}
+
+/* Print an error message and, if `set -e' has been executed, exit the
+   shell.  Used in this file by file_error and programming_error.  Used
+   outside this file mostly to report substitution and expansion errors,
+   and for bad invocation options. */
+void
+#if defined (PREFER_STDARG)
+report_error (const char *format, ...)
+#else
+report_error (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  error_prolog (1);
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+  if (exit_immediately_on_error)
+    exit_shell (1);
+}
+
+void
+#if defined (PREFER_STDARG)
+fatal_error (const char *format, ...)
+#else
+fatal_error (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  error_prolog (0);
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+  sh_exit (2);
+}
+
+void
+#if defined (PREFER_STDARG)
+internal_error (const char *format, ...)
+#else
+internal_error (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  error_prolog (1);
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+}
+
+void
+#if defined (PREFER_STDARG)
+internal_warning (const char *format, ...)
+#else
+internal_warning (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  error_prolog (1);
+  fprintf (stderr, _("warning: "));
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+}
+
+void
+#if defined (PREFER_STDARG)
+sys_error (const char *format, ...)
+#else
+sys_error (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  int e;
+  va_list args;
+
+  e = errno;
+  error_prolog (0);
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, ": %s\n", strerror (e));
+
+  va_end (args);
+}
+
+/* An error from the parser takes the general form
+
+       shell_name: input file name: line number: message
+
+   The input file name and line number are omitted if the shell is
+   currently interactive.  If the shell is not currently interactive,
+   the input file name is inserted only if it is different from the
+   shell name. */
+void
+#if defined (PREFER_STDARG)
+parser_error (int lineno, const char *format, ...)
+#else
+parser_error (lineno, format, va_alist)
+     int lineno;
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+  char *ename, *iname;
+
+  ename = get_name_for_error ();
+  iname = yy_input_name ();
+
+  if (interactive)
+    fprintf (stderr, "%s: ", ename);
+  else if (interactive_shell)
+    fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
+  else if (STREQ (ename, iname))
+    fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), lineno);
+  else
+    fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+
+  if (exit_immediately_on_error)
+    exit_shell (last_command_exit_value = 2);
+}
+
+#ifdef DEBUG
+void
+#if defined (PREFER_STDARG)
+itrace (const char *format, ...)
+#else
+itrace (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+
+  fprintf(stderr, "TRACE: pid %ld: ", (long)getpid());
+
+  SH_VA_START (args, format);
+
+  vfprintf (stderr, format, args);
+  fprintf (stderr, "\n");
+
+  va_end (args);
+
+  fflush(stderr);
+}
+
+/* A trace function for silent debugging -- doesn't require a control
+   terminal. */
+void
+#if defined (PREFER_STDARG)
+trace (const char *format, ...)
+#else
+trace (format, va_alist)
+     const char *format;
+     va_dcl
+#endif
+{
+  va_list args;
+  static FILE *tracefp = (FILE *)NULL;
+
+  if (tracefp == NULL)
+    tracefp = fopen("/tmp/bash-trace.log", "a+");
+
+  if (tracefp == NULL)
+    tracefp = stderr;
+  else
+    fcntl (fileno (tracefp), F_SETFD, 1);     /* close-on-exec */
+
+  fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid());
+
+  SH_VA_START (args, format);
+
+  vfprintf (tracefp, format, args);
+  fprintf (tracefp, "\n");
+
+  va_end (args);
+
+  fflush(tracefp);
+}
+
+#endif /* DEBUG */
+
+/* **************************************************************** */
+/*                                                                 */
+/*                 Common error reporting                          */
+/*                                                                 */
+/* **************************************************************** */
+
+
+static const char * const cmd_error_table[] = {
+       N_("unknown command error"),    /* CMDERR_DEFAULT */
+       N_("bad command type"),         /* CMDERR_BADTYPE */
+       N_("bad connector"),            /* CMDERR_BADCONN */
+       N_("bad jump"),                 /* CMDERR_BADJUMP */
+       0
+};
+
+void
+command_error (func, code, e, flags)
+     const char *func;
+     int code, e, flags;       /* flags currently unused */
+{
+  if (code > CMDERR_LAST)
+    code = CMDERR_DEFAULT;
+
+  programming_error ("%s: %s: %d", func, _(cmd_error_table[code]), e);
+}
+
+char *
+command_errstr (code)
+     int code;
+{
+  if (code > CMDERR_LAST)
+    code = CMDERR_DEFAULT;
+
+  return (_(cmd_error_table[code]));
+}
+
+#ifdef ARRAY_VARS
+void
+err_badarraysub (s)
+     const char *s;
+{
+  report_error ("%s: %s", s, _(bash_badsub_errmsg));
+}
+#endif
+
+void
+err_unboundvar (s)
+     const char *s;
+{
+  report_error (_("%s: unbound variable"), s);
+}
+
+void
+err_readonly (s)
+     const char *s;
+{
+  report_error (_("%s: readonly variable"), s);
+itrace("err_readonly: %d", getpid());
+  sleep (60);
+}
diff --git a/flags.c b/flags.c
index d3b38ad37b24d95cdfd5a4a0eb4e0413807d1c49..0ccdb0bbcbd16f5695965c8928afb9194074d14a 100644 (file)
--- a/flags.c
+++ b/flags.c
@@ -250,7 +250,6 @@ change_flag (flag, on_or_off)
     return (FLAG_ERROR);
 
   old_value = *value;
-
   *value = (on_or_off == FLAG_ON) ? 1 : 0;
 
   /* Special cases for a few flags. */
diff --git a/jobs.c b/jobs.c
index 17615c712de9645f91f83084891aa9efe107c3e2..2f21b17152c44291bbce480b2b4d37bc6521fb22 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -45,7 +45,9 @@
 
 #include "filecntl.h"
 #include <sys/ioctl.h>
+#ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
+#endif
 
 #if defined (BUFFERED_INPUT)
 #  include "input.h"
diff --git a/jobs.c~ b/jobs.c~
new file mode 100644 (file)
index 0000000..17615c7
--- /dev/null
+++ b/jobs.c~
@@ -0,0 +1,4308 @@
+/* jobs.c - functions that make children, remember them, and handle their termination. */
+
+/* This file works with both POSIX and BSD systems.  It implements job
+   control. */
+
+/* Copyright (C) 1989-2011 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "bashtypes.h"
+#include "trap.h"
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "posixtime.h"
+
+#if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_WAIT3) && !defined (_POSIX_VERSION) && !defined (RLIMTYPE)
+#  include <sys/resource.h>
+#endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 && !RLIMTYPE */
+
+#if defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif
+
+#include "filecntl.h"
+#include <sys/ioctl.h>
+#include <sys/param.h>
+
+#if defined (BUFFERED_INPUT)
+#  include "input.h"
+#endif
+
+/* Need to include this up here for *_TTY_DRIVER definitions. */
+#include "shtty.h"
+
+/* Define this if your output is getting swallowed.  It's a no-op on
+   machines with the termio or termios tty drivers. */
+/* #define DRAIN_OUTPUT */
+
+/* For the TIOCGPGRP and TIOCSPGRP ioctl parameters on HP-UX */
+#if defined (hpux) && !defined (TERMIOS_TTY_DRIVER)
+#  include <bsdtty.h>
+#endif /* hpux && !TERMIOS_TTY_DRIVER */
+
+#include "bashansi.h"
+#include "bashintl.h"
+#include "shell.h"
+#include "jobs.h"
+#include "execute_cmd.h"
+#include "flags.h"
+
+#include "builtins/builtext.h"
+#include "builtins/common.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#if !defined (HAVE_KILLPG)
+extern int killpg __P((pid_t, int));
+#endif
+
+#define DEFAULT_CHILD_MAX 32
+#if !defined (DEBUG)
+#define MAX_JOBS_IN_ARRAY 4096         /* production */
+#else
+#define MAX_JOBS_IN_ARRAY 128          /* testing */
+#endif
+
+/* Flag values for second argument to delete_job */
+#define DEL_WARNSTOPPED                1       /* warn about deleting stopped jobs */
+#define DEL_NOBGPID            2       /* don't add pgrp leader to bgpids */
+
+/* Take care of system dependencies that must be handled when waiting for
+   children.  The arguments to the WAITPID macro match those to the Posix.1
+   waitpid() function. */
+
+#if defined (ultrix) && defined (mips) && defined (_POSIX_VERSION)
+#  define WAITPID(pid, statusp, options) \
+       wait3 ((union wait *)statusp, options, (struct rusage *)0)
+#else
+#  if defined (_POSIX_VERSION) || defined (HAVE_WAITPID)
+#    define WAITPID(pid, statusp, options) \
+       waitpid ((pid_t)pid, statusp, options)
+#  else
+#    if defined (HAVE_WAIT3)
+#      define WAITPID(pid, statusp, options) \
+       wait3 (statusp, options, (struct rusage *)0)
+#    else
+#      define WAITPID(pid, statusp, options) \
+       wait3 (statusp, options, (int *)0)
+#    endif /* HAVE_WAIT3 */
+#  endif /* !_POSIX_VERSION && !HAVE_WAITPID*/
+#endif /* !(Ultrix && mips && _POSIX_VERSION) */
+
+/* getpgrp () varies between systems.  Even systems that claim to be
+   Posix.1 compatible lie sometimes (Ultrix, SunOS4, apollo). */
+#if defined (GETPGRP_VOID)
+#  define getpgid(p) getpgrp ()
+#else
+#  define getpgid(p) getpgrp (p)
+#endif /* !GETPGRP_VOID */
+
+/* If the system needs it, REINSTALL_SIGCHLD_HANDLER will reinstall the
+   handler for SIGCHLD. */
+#if defined (MUST_REINSTALL_SIGHANDLERS)
+#  define REINSTALL_SIGCHLD_HANDLER signal (SIGCHLD, sigchld_handler)
+#else
+#  define REINSTALL_SIGCHLD_HANDLER
+#endif /* !MUST_REINSTALL_SIGHANDLERS */
+
+/* Some systems let waitpid(2) tell callers about stopped children. */
+#if !defined (WCONTINUED) || defined (WCONTINUED_BROKEN)
+#  undef WCONTINUED
+#  define WCONTINUED 0
+#endif
+#if !defined (WIFCONTINUED)
+#  define WIFCONTINUED(s)      (0)
+#endif
+
+/* The number of additional slots to allocate when we run out. */
+#define JOB_SLOTS 8
+
+typedef int sh_job_map_func_t __P((JOB *, int, int, int));
+
+/* Variables used here but defined in other files. */
+extern int subshell_environment, line_number;
+extern int posixly_correct, shell_level;
+extern int last_command_exit_value, last_command_exit_signal;
+extern int loop_level, breaking;
+extern int executing_list;
+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;
+extern procenv_t wait_intr_buf;
+extern int wait_signal_received;
+extern WORD_LIST *subst_assign_varlist;
+
+static struct jobstats zerojs = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
+struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
+
+struct bgpids bgpids = { 0, 0, 0 };
+
+/* The array of known jobs. */
+JOB **jobs = (JOB **)NULL;
+
+#if 0
+/* The number of slots currently allocated to JOBS. */
+int job_slots = 0;
+#endif
+
+/* The controlling tty for this shell. */
+int shell_tty = -1;
+
+/* The shell's process group. */
+pid_t shell_pgrp = NO_PID;
+
+/* The terminal's process group. */
+pid_t terminal_pgrp = NO_PID;
+
+/* The process group of the shell's parent. */
+pid_t original_pgrp = NO_PID;
+
+/* The process group of the pipeline currently being made. */
+pid_t pipeline_pgrp = (pid_t)0;
+
+#if defined (PGRP_PIPE)
+/* Pipes which each shell uses to communicate with the process group leader
+   until all of the processes in a pipeline have been started.  Then the
+   process leader is allowed to continue. */
+int pgrp_pipe[2] = { -1, -1 };
+#endif
+
+#if 0
+/* The job which is current; i.e. the one that `%+' stands for. */
+int current_job = NO_JOB;
+
+/* The previous job; i.e. the one that `%-' stands for. */
+int previous_job = NO_JOB;
+#endif
+
+/* Last child made by the shell.  */
+pid_t last_made_pid = NO_PID;
+
+/* Pid of the last asynchronous child. */
+pid_t last_asynchronous_pid = NO_PID;
+
+/* The pipeline currently being built. */
+PROCESS *the_pipeline = (PROCESS *)NULL;
+
+/* If this is non-zero, do job control. */
+int job_control = 1;
+
+/* Call this when you start making children. */
+int already_making_children = 0;
+
+/* If this is non-zero, $LINES and $COLUMNS are reset after every process
+   exits from get_tty_state(). */
+int check_window_size;
+
+/* Functions local to this file. */
+
+static sighandler wait_sigint_handler __P((int));
+static sighandler sigchld_handler __P((int));
+static sighandler sigcont_sighandler __P((int));
+static sighandler sigstop_sighandler __P((int));
+
+static int waitchld __P((pid_t, int));
+
+static PROCESS *find_pipeline __P((pid_t, int, int *));
+static PROCESS *find_process __P((pid_t, int, int *));
+
+static char *current_working_directory __P((void));
+static char *job_working_directory __P((void));
+static char *j_strsignal __P((int));
+static char *printable_job_status __P((int, PROCESS *, int));
+
+static PROCESS *find_last_proc __P((int, int));
+static pid_t find_last_pid __P((int, int));
+
+static int set_new_line_discipline __P((int));
+static int map_over_jobs __P((sh_job_map_func_t *, int, int));
+static int job_last_stopped __P((int));
+static int job_last_running __P((int));
+static int most_recent_job_in_state __P((int, JOB_STATE));
+static int find_job __P((pid_t, int, PROCESS **));
+static int print_job __P((JOB *, int, int, int));
+static int process_exit_status __P((WAIT));
+static int process_exit_signal __P((WAIT));
+static int set_job_status_and_cleanup __P((int));
+
+static WAIT job_signal_status __P((int));
+static WAIT raw_job_exit_status __P((int));
+
+static void notify_of_job_status __P((void));
+static void reset_job_indices __P((void));
+static void cleanup_dead_jobs __P((void));
+static int processes_in_job __P((int));
+static void realloc_jobs_list __P((void));
+static int compact_jobs_list __P((int));
+static int discard_pipeline __P((PROCESS *));
+static void add_process __P((char *, pid_t));
+static void print_pipeline __P((PROCESS *, int, int, FILE *));
+static void pretty_print_job __P((int, int, FILE *));
+static void set_current_job __P((int));
+static void reset_current __P((void));
+static void set_job_running __P((int));
+static void setjstatus __P((int));
+static int maybe_give_terminal_to __P((pid_t, pid_t, int));
+static void mark_all_jobs_as_dead __P((void));
+static void mark_dead_jobs_as_notified __P((int));
+static void restore_sigint_handler __P((void));
+#if defined (PGRP_PIPE)
+static void pipe_read __P((int *));
+#endif
+
+static struct pidstat *bgp_alloc __P((pid_t, int));
+static struct pidstat *bgp_add __P((pid_t, int));
+static int bgp_delete __P((pid_t));
+static void bgp_clear __P((void));
+static int bgp_search __P((pid_t));
+static void bgp_prune __P((void));
+
+#if defined (ARRAY_VARS)
+static int *pstatuses;         /* list of pipeline statuses */
+static int statsize;
+#endif
+
+/* Used to synchronize between wait_for and other functions and the SIGCHLD
+   signal handler. */
+static int sigchld;
+static int queue_sigchld;
+
+#define QUEUE_SIGCHLD(os)      (os) = sigchld, queue_sigchld++
+
+#define UNQUEUE_SIGCHLD(os) \
+       do { \
+         queue_sigchld--; \
+         if (queue_sigchld == 0 && os != sigchld) \
+           waitchld (-1, 0); \
+       } while (0)
+
+static SigHandler *old_tstp, *old_ttou, *old_ttin;
+static SigHandler *old_cont = (SigHandler *)SIG_DFL;
+
+/* A place to temporarily save the current pipeline. */
+static PROCESS *saved_pipeline;
+static int saved_already_making_children;
+
+/* Set this to non-zero whenever you don't want the jobs list to change at
+   all: no jobs deleted and no status change notifications.  This is used,
+   for example, when executing SIGCHLD traps, which may run arbitrary
+   commands. */
+static int jobs_list_frozen;
+
+static char retcode_name_buffer[64];
+
+/* flags to detect pid wraparound */
+static pid_t first_pid = NO_PID;
+static int pid_wrap = -1;
+
+#if !defined (_POSIX_VERSION)
+
+/* These are definitions to map POSIX 1003.1 functions onto existing BSD
+   library functions and system calls. */
+#define setpgid(pid, pgrp)     setpgrp (pid, pgrp)
+#define tcsetpgrp(fd, pgrp)    ioctl ((fd), TIOCSPGRP, &(pgrp))
+
+pid_t
+tcgetpgrp (fd)
+     int fd;
+{
+  pid_t pgrp;
+
+  /* ioctl will handle setting errno correctly. */
+  if (ioctl (fd, TIOCGPGRP, &pgrp) < 0)
+    return (-1);
+  return (pgrp);
+}
+
+#endif /* !_POSIX_VERSION */
+
+/* Initialize the global job stats structure and other bookkeeping variables */
+void
+init_job_stats ()
+{
+  js = zerojs;
+  first_pid = NO_PID;
+  pid_wrap = -1;
+}
+
+/* Return the working directory for the current process.  Unlike
+   job_working_directory, this does not call malloc (), nor do any
+   of the functions it calls.  This is so that it can safely be called
+   from a signal handler. */
+static char *
+current_working_directory ()
+{
+  char *dir;
+  static char d[PATH_MAX];
+
+  dir = get_string_value ("PWD");
+
+  if (dir == 0 && the_current_working_directory && no_symbolic_links)
+    dir = the_current_working_directory;
+
+  if (dir == 0)
+    {
+      dir = getcwd (d, sizeof(d));
+      if (dir)
+       dir = d;
+    }
+
+  return (dir == 0) ? "<unknown>" : dir;
+}
+
+/* Return the working directory for the current process. */
+static char *
+job_working_directory ()
+{
+  char *dir;
+
+  dir = get_string_value ("PWD");
+  if (dir)
+    return (savestring (dir));
+
+  dir = get_working_directory ("job-working-directory");
+  if (dir)
+    return (dir);
+
+  return (savestring ("<unknown>"));
+}
+
+void
+making_children ()
+{
+  if (already_making_children)
+    return;
+
+  already_making_children = 1;
+  start_pipeline ();
+}
+
+void
+stop_making_children ()
+{
+  already_making_children = 0;
+}
+
+void
+cleanup_the_pipeline ()
+{
+  PROCESS *disposer;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+  disposer = the_pipeline;
+  the_pipeline = (PROCESS *)NULL;
+  UNBLOCK_CHILD (oset);
+
+  if (disposer)
+    discard_pipeline (disposer);
+}
+
+void
+save_pipeline (clear)
+     int clear;
+{
+  saved_pipeline = the_pipeline;
+  if (clear)
+    the_pipeline = (PROCESS *)NULL;
+  saved_already_making_children = already_making_children;
+}
+
+void
+restore_pipeline (discard)
+     int discard;
+{
+  PROCESS *old_pipeline;
+
+  old_pipeline = the_pipeline;
+  the_pipeline = saved_pipeline;
+  already_making_children = saved_already_making_children;
+  if (discard && old_pipeline)
+    discard_pipeline (old_pipeline);
+}
+
+/* Start building a pipeline.  */
+void
+start_pipeline ()
+{
+  if (the_pipeline)
+    {
+      cleanup_the_pipeline ();
+      pipeline_pgrp = 0;
+#if defined (PGRP_PIPE)
+      sh_closepipe (pgrp_pipe);
+#endif
+    }
+
+#if defined (PGRP_PIPE)
+  if (job_control)
+    {
+      if (pipe (pgrp_pipe) == -1)
+       sys_error (_("start_pipeline: pgrp pipe"));
+    }
+#endif
+}
+
+/* Stop building a pipeline.  Install the process list in the job array.
+   This returns the index of the newly installed job.
+   DEFERRED is a command structure to be executed upon satisfactory
+   execution exit of this pipeline. */
+int
+stop_pipeline (async, deferred)
+     int async;
+     COMMAND *deferred;
+{
+  register int i, j;
+  JOB *newjob;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+#if defined (PGRP_PIPE)
+  /* The parent closes the process group synchronization pipe. */
+  sh_closepipe (pgrp_pipe);
+#endif
+
+  cleanup_dead_jobs ();
+
+  if (js.j_jobslots == 0)
+    {
+      js.j_jobslots = JOB_SLOTS;
+      jobs = (JOB **)xmalloc (js.j_jobslots * sizeof (JOB *));
+
+      /* Now blank out these new entries. */
+      for (i = 0; i < js.j_jobslots; i++)
+       jobs[i] = (JOB *)NULL;
+
+      js.j_firstj = js.j_lastj = js.j_njobs = 0;
+    }
+
+  /* Scan from the last slot backward, looking for the next free one. */
+  /* XXX - revisit this interactive assumption */
+  /* XXX - this way for now */
+  if (interactive)
+    {
+      for (i = js.j_jobslots; i; i--)
+       if (jobs[i - 1])
+         break;
+    }
+  else
+    {
+#if 0
+      /* This wraps around, but makes it inconvenient to extend the array */
+      for (i = js.j_lastj+1; i != js.j_lastj; i++)
+       {
+         if (i >= js.j_jobslots)
+           i = 0;
+         if (jobs[i] == 0)
+           break;
+       }       
+      if (i == js.j_lastj)
+        i = js.j_jobslots;
+#else
+      /* This doesn't wrap around yet. */
+      for (i = js.j_lastj ? js.j_lastj + 1 : js.j_lastj; i < js.j_jobslots; i++)
+       if (jobs[i] == 0)
+         break;
+#endif
+    }
+
+  /* Do we need more room? */
+
+  /* First try compaction */
+  if ((interactive_shell == 0 || subshell_environment) && i == js.j_jobslots && js.j_jobslots >= MAX_JOBS_IN_ARRAY)
+    i = compact_jobs_list (0);
+
+  /* If we can't compact, reallocate */
+  if (i == js.j_jobslots)
+    {
+      js.j_jobslots += JOB_SLOTS;
+      jobs = (JOB **)xrealloc (jobs, (js.j_jobslots * sizeof (JOB *)));
+
+      for (j = i; j < js.j_jobslots; j++)
+       jobs[j] = (JOB *)NULL;
+    }
+
+  /* Add the current pipeline to the job list. */
+  if (the_pipeline)
+    {
+      register PROCESS *p;
+      int any_running, any_stopped, n;
+
+      newjob = (JOB *)xmalloc (sizeof (JOB));
+
+      for (n = 1, p = the_pipeline; p->next != the_pipeline; n++, p = p->next)
+       ;
+      p->next = (PROCESS *)NULL;
+      newjob->pipe = REVERSE_LIST (the_pipeline, PROCESS *);
+      for (p = newjob->pipe; p->next; p = p->next)
+       ;
+      p->next = newjob->pipe;
+
+      the_pipeline = (PROCESS *)NULL;
+      newjob->pgrp = pipeline_pgrp;
+      pipeline_pgrp = 0;
+
+      newjob->flags = 0;
+
+      /* Flag to see if in another pgrp. */
+      if (job_control)
+       newjob->flags |= J_JOBCONTROL;
+
+      /* Set the state of this pipeline. */
+      p = newjob->pipe;
+      any_running = any_stopped = 0;
+      do
+       {
+         any_running |= PRUNNING (p);
+         any_stopped |= PSTOPPED (p);
+         p = p->next;
+       }
+      while (p != newjob->pipe);
+
+      newjob->state = any_running ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
+      newjob->wd = job_working_directory ();
+      newjob->deferred = deferred;
+
+      newjob->j_cleanup = (sh_vptrfunc_t *)NULL;
+      newjob->cleanarg = (PTR_T) NULL;
+
+      jobs[i] = newjob;
+      if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))
+       setjstatus (i);
+      if (newjob->state == JDEAD)
+       {
+         js.c_reaped += n;     /* wouldn't have been done since this was not part of a job */
+         js.j_ndead++;
+       }
+      js.c_injobs += n;
+
+      js.j_lastj = i;
+      js.j_njobs++;
+    }
+  else
+    newjob = (JOB *)NULL;
+
+  if (newjob)
+    js.j_lastmade = newjob;
+
+  if (async)
+    {
+      if (newjob)
+       {
+         newjob->flags &= ~J_FOREGROUND;
+         newjob->flags |= J_ASYNC;
+         js.j_lastasync = newjob;
+       }
+      reset_current ();
+    }
+  else
+    {
+      if (newjob)
+       {
+         newjob->flags |= J_FOREGROUND;
+         /*
+          *            !!!!! NOTE !!!!!  (chet@ins.cwru.edu)
+          *
+          * The currently-accepted job control wisdom says to set the
+          * terminal's process group n+1 times in an n-step pipeline:
+          * once in the parent and once in each child.  This is where
+          * the parent gives it away.
+          *
+          * Don't give the terminal away if this shell is an asynchronous
+          * subshell.
+          *
+          */
+         if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0)
+           maybe_give_terminal_to (shell_pgrp, newjob->pgrp, 0);
+       }
+    }
+
+  stop_making_children ();
+  UNBLOCK_CHILD (oset);
+  return (newjob ? i : js.j_current);
+}
+
+/* Functions to manage the list of exited background pids whose status has
+   been saved. */
+
+static struct pidstat *
+bgp_alloc (pid, status)
+     pid_t pid;
+     int status;
+{
+  struct pidstat *ps;
+
+  ps = (struct pidstat *)xmalloc (sizeof (struct pidstat));
+  ps->pid = pid;
+  ps->status = status;
+  ps->next = (struct pidstat *)0;
+  return ps;
+}
+
+static struct pidstat *
+bgp_add (pid, status)
+     pid_t pid;
+     int status;
+{
+  struct pidstat *ps;
+
+  ps = bgp_alloc (pid, status);
+
+  if (bgpids.list == 0)
+    {
+      bgpids.list = bgpids.end = ps;
+      bgpids.npid = 0;                 /* just to make sure */
+    }
+  else
+    {
+      bgpids.end->next = ps;
+      bgpids.end = ps;
+    }
+  bgpids.npid++;
+
+  if (bgpids.npid > js.c_childmax)
+    bgp_prune ();
+
+  return ps;
+}
+
+static int
+bgp_delete (pid)
+     pid_t pid;
+{
+  struct pidstat *prev, *p;
+
+  for (prev = p = bgpids.list; p; prev = p, p = p->next)
+    if (p->pid == pid)
+      {
+       prev->next = p->next;   /* remove from list */
+       break;
+      }
+
+  if (p == 0)
+    return 0;          /* not found */
+
+#if defined (DEBUG)
+  itrace("bgp_delete: deleting %d", pid);
+#endif
+
+  /* Housekeeping in the border cases. */
+  if (p == bgpids.list)
+    bgpids.list = bgpids.list->next;
+  else if (p == bgpids.end)
+    bgpids.end = prev;
+
+  bgpids.npid--;
+  if (bgpids.npid == 0)
+    bgpids.list = bgpids.end = 0;
+  else if (bgpids.npid == 1)
+    bgpids.end = bgpids.list;          /* just to make sure */
+
+  free (p);
+  return 1;
+}
+
+/* Clear out the list of saved statuses */
+static void
+bgp_clear ()
+{
+  struct pidstat *ps, *p;
+
+  for (ps = bgpids.list; ps; )
+    {
+      p = ps;
+      ps = ps->next;
+      free (p);
+    }
+  bgpids.list = bgpids.end = 0;
+  bgpids.npid = 0;
+}
+
+/* Search for PID in the list of saved background pids; return its status if
+   found.  If not found, return -1. */
+static int
+bgp_search (pid)
+     pid_t pid;
+{
+  struct pidstat *ps;
+
+  for (ps = bgpids.list ; ps; ps = ps->next)
+    if (ps->pid == pid)
+      return ps->status;
+  return -1;
+}
+
+static void
+bgp_prune ()
+{
+  struct pidstat *ps;
+
+  while (bgpids.npid > js.c_childmax)
+    {
+      ps = bgpids.list;
+      bgpids.list = bgpids.list->next;
+      free (ps);
+      bgpids.npid--;
+    }
+}
+
+/* Reset the values of js.j_lastj and js.j_firstj after one or both have
+   been deleted.  The caller should check whether js.j_njobs is 0 before
+   calling this.  This wraps around, but the rest of the code does not.  At
+   this point, it should not matter. */
+static void
+reset_job_indices ()
+{
+  int old;
+
+  if (jobs[js.j_firstj] == 0)
+    {
+      old = js.j_firstj++;
+      if (old >= js.j_jobslots)
+       old = js.j_jobslots - 1;
+      while (js.j_firstj != old)
+       {
+         if (js.j_firstj >= js.j_jobslots)
+           js.j_firstj = 0;
+         if (jobs[js.j_firstj] || js.j_firstj == old)  /* needed if old == 0 */
+           break;
+         js.j_firstj++;
+       }
+      if (js.j_firstj == old)
+        js.j_firstj = js.j_lastj = js.j_njobs = 0;
+    }
+  if (jobs[js.j_lastj] == 0)
+    {
+      old = js.j_lastj--;
+      if (old < 0)
+       old = 0;
+      while (js.j_lastj != old)
+       {
+         if (js.j_lastj < 0)
+           js.j_lastj = js.j_jobslots - 1;
+         if (jobs[js.j_lastj] || js.j_lastj == old)    /* needed if old == js.j_jobslots */
+           break;
+         js.j_lastj--;
+       }
+      if (js.j_lastj == old)
+        js.j_firstj = js.j_lastj = js.j_njobs = 0;
+    }
+}
+      
+/* Delete all DEAD jobs that the user had received notification about. */
+static void
+cleanup_dead_jobs ()
+{
+  register int i;
+  int os;
+
+  if (js.j_jobslots == 0 || jobs_list_frozen)
+    return;
+
+  QUEUE_SIGCHLD(os);
+
+  /* XXX could use js.j_firstj and js.j_lastj here */
+  for (i = 0; i < js.j_jobslots; i++)
+    {
+#if defined (DEBUG)
+      if (i < js.j_firstj && jobs[i])
+       itrace("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+      if (i > js.j_lastj && jobs[i])
+       itrace("cleanup_dead_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+
+      if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i))
+       delete_job (i, 0);
+    }
+
+#if defined (COPROCESS_SUPPORT)
+  coproc_reap ();
+#endif
+
+  UNQUEUE_SIGCHLD(os);
+}
+
+static int
+processes_in_job (job)
+     int job;
+{
+  int nproc;
+  register PROCESS *p;
+
+  nproc = 0;
+  p = jobs[job]->pipe;
+  do
+    {
+      p = p->next;
+      nproc++;
+    }
+  while (p != jobs[job]->pipe);
+
+  return nproc;
+}
+
+static void
+delete_old_job (pid)
+     pid_t pid;
+{
+  PROCESS *p;
+  int job;
+
+  job = find_job (pid, 0, &p);
+  if (job != NO_JOB)
+    {
+#ifdef DEBUG
+      itrace ("delete_old_job: found pid %d in job %d with state %d", pid, job, jobs[job]->state);
+#endif
+      if (JOBSTATE (job) == JDEAD)
+       delete_job (job, DEL_NOBGPID);
+      else
+       {
+         internal_warning (_("forked pid %d appears in running job %d"), pid, job);
+         if (p)
+           p->pid = 0;
+       }
+    }
+}
+
+/* Reallocate and compress the jobs list.  This returns with a jobs array
+   whose size is a multiple of JOB_SLOTS and can hold the current number of
+   jobs.  Heuristics are used to minimize the number of new reallocs. */
+static void
+realloc_jobs_list ()
+{
+  sigset_t set, oset;
+  int nsize, i, j, ncur, nprev;
+  JOB **nlist;
+
+  ncur = nprev = NO_JOB;
+  nsize = ((js.j_njobs + JOB_SLOTS - 1) / JOB_SLOTS);
+  nsize *= JOB_SLOTS;
+  i = js.j_njobs % JOB_SLOTS;
+  if (i == 0 || i > (JOB_SLOTS >> 1))
+    nsize += JOB_SLOTS;
+
+  BLOCK_CHILD (set, oset);
+  nlist = (js.j_jobslots == nsize) ? jobs : (JOB **) xmalloc (nsize * sizeof (JOB *));
+
+  js.c_reaped = js.j_ndead = 0;
+  for (i = j = 0; i < js.j_jobslots; i++)
+    if (jobs[i])
+      {
+       if (i == js.j_current)
+         ncur = j;
+       if (i == js.j_previous)
+         nprev = j;
+       nlist[j++] = jobs[i];
+       if (jobs[i]->state == JDEAD)
+         {
+           js.j_ndead++;
+           js.c_reaped += processes_in_job (i);
+         }
+      }
+
+#if defined (DEBUG)
+  itrace ("realloc_jobs_list: resize jobs list from %d to %d", js.j_jobslots, nsize);
+  itrace ("realloc_jobs_list: j_lastj changed from %d to %d", js.j_lastj, (j > 0) ? j - 1 : 0);
+  itrace ("realloc_jobs_list: j_njobs changed from %d to %d", js.j_njobs, j);
+  itrace ("realloc_jobs_list: js.j_ndead %d js.c_reaped %d", js.j_ndead, js.c_reaped);
+#endif
+
+  js.j_firstj = 0;
+  js.j_lastj = (j > 0) ? j - 1 : 0;
+  js.j_njobs = j;
+  js.j_jobslots = nsize;
+
+  /* Zero out remaining slots in new jobs list */
+  for ( ; j < nsize; j++)
+    nlist[j] = (JOB *)NULL;
+
+  if (jobs != nlist)
+    {
+      free (jobs);
+      jobs = nlist;
+    }
+
+  if (ncur != NO_JOB)
+    js.j_current = ncur;
+  if (nprev != NO_JOB)
+    js.j_previous = nprev;
+
+  /* Need to reset these */
+  if (js.j_current == NO_JOB || js.j_previous == NO_JOB || js.j_current > js.j_lastj || js.j_previous > js.j_lastj)
+    reset_current ();
+
+#ifdef DEBUG
+  itrace ("realloc_jobs_list: reset js.j_current (%d) and js.j_previous (%d)", js.j_current, js.j_previous);
+#endif
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Compact the jobs list by removing dead jobs.  Assumed that we have filled
+   the jobs array to some predefined maximum.  Called when the shell is not
+   the foreground process (subshell_environment != 0).  Returns the first
+   available slot in the compacted list.  If that value is js.j_jobslots, then
+   the list needs to be reallocated.  The jobs array may be in new memory if
+   this returns > 0 and < js.j_jobslots.  FLAGS is reserved for future use. */
+static int
+compact_jobs_list (flags)
+     int flags;
+{
+  if (js.j_jobslots == 0 || jobs_list_frozen)
+    return js.j_jobslots;
+
+  reap_dead_jobs ();
+  realloc_jobs_list ();
+
+#ifdef DEBUG
+  itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+#endif
+
+  return ((js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+}
+
+/* Delete the job at INDEX from the job list.  Must be called
+   with SIGCHLD blocked. */
+void
+delete_job (job_index, dflags)
+     int job_index, dflags;
+{
+  register JOB *temp;
+  PROCESS *proc;
+  int ndel;
+
+  if (js.j_jobslots == 0 || jobs_list_frozen)
+    return;
+
+  if ((dflags & DEL_WARNSTOPPED) && subshell_environment == 0 && STOPPED (job_index))
+    internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
+  temp = jobs[job_index];
+  if (temp == 0)
+    return;
+
+  if ((dflags & DEL_NOBGPID) == 0)
+    {
+      proc = find_last_proc (job_index, 0);
+      /* Could do this just for J_ASYNC jobs, but we save all. */
+      if (proc)
+       bgp_add (proc->pid, process_exit_status (proc->status));
+    }
+
+  jobs[job_index] = (JOB *)NULL;
+  if (temp == js.j_lastmade)
+    js.j_lastmade = 0;
+  else if (temp == js.j_lastasync)
+    js.j_lastasync = 0;
+
+  free (temp->wd);
+  ndel = discard_pipeline (temp->pipe);
+
+  js.c_injobs -= ndel;
+  if (temp->state == JDEAD)
+    {
+      js.c_reaped -= ndel;
+      js.j_ndead--;
+      if (js.c_reaped < 0)
+       {
+#ifdef DEBUG
+         itrace("delete_job (%d pgrp %d): js.c_reaped (%d) < 0 ndel = %d js.j_ndead = %d", job_index, temp->pgrp, js.c_reaped, ndel, js.j_ndead);
+#endif
+         js.c_reaped = 0;
+       }
+    }
+
+  if (temp->deferred)
+    dispose_command (temp->deferred);
+
+  free (temp);
+
+  js.j_njobs--;
+  if (js.j_njobs == 0)
+    js.j_firstj = js.j_lastj = 0;
+  else if (jobs[js.j_firstj] == 0 || jobs[js.j_lastj] == 0)
+    reset_job_indices ();
+
+  if (job_index == js.j_current || job_index == js.j_previous)
+    reset_current ();
+}
+
+/* Must be called with SIGCHLD blocked. */
+void
+nohup_job (job_index)
+     int job_index;
+{
+  register JOB *temp;
+
+  if (js.j_jobslots == 0)
+    return;
+
+  if (temp = jobs[job_index])
+    temp->flags |= J_NOHUP;
+}
+
+/* Get rid of the data structure associated with a process chain. */
+static int
+discard_pipeline (chain)
+     register PROCESS *chain;
+{
+  register PROCESS *this, *next;
+  int n;
+
+  this = chain;
+  n = 0;
+  do
+    {
+      next = this->next;
+      FREE (this->command);
+      free (this);
+      n++;
+      this = next;
+    }
+  while (this != chain);
+
+  return n;
+}
+
+/* Add this process to the chain being built in the_pipeline.
+   NAME is the command string that will be exec'ed later.
+   PID is the process id of the child. */
+static void
+add_process (name, pid)
+     char *name;
+     pid_t pid;
+{
+  PROCESS *t, *p;
+
+#if defined (RECYCLES_PIDS)
+  int j;
+  p = find_process (pid, 0, &j);
+  if (p)
+    {
+#  ifdef DEBUG
+      if (j == NO_JOB)
+       internal_warning (_("add_process: process %5ld (%s) in the_pipeline"), (long)p->pid, p->command);
+#  endif
+      if (PALIVE (p))
+        internal_warning (_("add_process: pid %5ld (%s) marked as still alive"), (long)p->pid, p->command);
+      p->running = PS_RECYCLED;                /* mark as recycled */
+    }
+#endif
+
+  t = (PROCESS *)xmalloc (sizeof (PROCESS));
+  t->next = the_pipeline;
+  t->pid = pid;
+  WSTATUS (t->status) = 0;
+  t->running = PS_RUNNING;
+  t->command = name;
+  the_pipeline = t;
+
+  if (t->next == 0)
+    t->next = t;
+  else
+    {
+      p = t->next;
+      while (p->next != t->next)
+       p = p->next;
+      p->next = t;
+    }
+}
+
+/* Create a (dummy) PROCESS with NAME, PID, and STATUS, and make it the last
+   process in jobs[JID]->pipe.  Used by the lastpipe code. */
+void
+append_process (name, pid, status, jid)
+     char *name;
+     pid_t pid;
+     int status;
+     int jid;
+{
+  PROCESS *t, *p;
+
+  t = (PROCESS *)xmalloc (sizeof (PROCESS));
+  t->next = (PROCESS *)NULL;
+  t->pid = pid;
+  /* set process exit status using offset discovered by configure */
+  t->status = (status & 0xff) << WEXITSTATUS_OFFSET;
+  t->running = PS_DONE;
+  t->command = name;
+
+  js.c_reaped++;       /* XXX */
+
+  for (p = jobs[jid]->pipe; p->next != jobs[jid]->pipe; p = p->next)
+    ;
+  p->next = t;
+  t->next = jobs[jid]->pipe;
+}
+
+#if 0
+/* Take the last job and make it the first job.  Must be called with
+   SIGCHLD blocked. */
+int
+rotate_the_pipeline ()
+{
+  PROCESS *p;
+
+  if (the_pipeline->next == the_pipeline)
+    return;
+  for (p = the_pipeline; p->next != the_pipeline; p = p->next)
+    ;
+  the_pipeline = p;
+}
+
+/* Reverse the order of the processes in the_pipeline.  Must be called with
+   SIGCHLD blocked. */
+int
+reverse_the_pipeline ()
+{
+  PROCESS *p, *n;
+
+  if (the_pipeline->next == the_pipeline)
+    return;
+
+  for (p = the_pipeline; p->next != the_pipeline; p = p->next)
+    ;
+  p->next = (PROCESS *)NULL;
+
+  n = REVERSE_LIST (the_pipeline, PROCESS *);
+
+  the_pipeline = n;
+  for (p = the_pipeline; p->next; p = p->next)
+    ;
+  p->next = the_pipeline;
+}
+#endif
+
+/* Map FUNC over the list of jobs.  If FUNC returns non-zero,
+   then it is time to stop mapping, and that is the return value
+   for map_over_jobs.  FUNC is called with a JOB, arg1, arg2,
+   and INDEX. */
+static int
+map_over_jobs (func, arg1, arg2)
+     sh_job_map_func_t *func;
+     int arg1, arg2;
+{
+  register int i;
+  int result;
+  sigset_t set, oset;
+
+  if (js.j_jobslots == 0)
+    return 0;
+
+  BLOCK_CHILD (set, oset);
+
+  /* XXX could use js.j_firstj here */
+  for (i = result = 0; i < js.j_jobslots; i++)
+    {
+#if defined (DEBUG)
+      if (i < js.j_firstj && jobs[i])
+       itrace("map_over_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+      if (i > js.j_lastj && jobs[i])
+       itrace("map_over_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+      if (jobs[i])
+       {
+         result = (*func)(jobs[i], arg1, arg2, i);
+         if (result)
+           break;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+
+  return (result);
+}
+
+/* Cause all the jobs in the current pipeline to exit. */
+void
+terminate_current_pipeline ()
+{
+  if (pipeline_pgrp && pipeline_pgrp != shell_pgrp)
+    {
+      killpg (pipeline_pgrp, SIGTERM);
+      killpg (pipeline_pgrp, SIGCONT);
+    }
+}
+
+/* Cause all stopped jobs to exit. */
+void
+terminate_stopped_jobs ()
+{
+  register int i;
+
+  /* XXX could use js.j_firstj here */
+  for (i = 0; i < js.j_jobslots; i++)
+    {
+      if (jobs[i] && STOPPED (i))
+       {
+         killpg (jobs[i]->pgrp, SIGTERM);
+         killpg (jobs[i]->pgrp, SIGCONT);
+       }
+    }
+}
+
+/* Cause all jobs, running or stopped, to receive a hangup signal.  If
+   a job is marked J_NOHUP, don't send the SIGHUP. */
+void
+hangup_all_jobs ()
+{
+  register int i;
+
+  /* XXX could use js.j_firstj here */
+  for (i = 0; i < js.j_jobslots; i++)
+    {
+      if (jobs[i])
+       {
+         if  (jobs[i]->flags & J_NOHUP)
+           continue;
+         killpg (jobs[i]->pgrp, SIGHUP);
+         if (STOPPED (i))
+           killpg (jobs[i]->pgrp, SIGCONT);
+       }
+    }
+}
+
+void
+kill_current_pipeline ()
+{
+  stop_making_children ();
+  start_pipeline ();
+}
+
+/* Return the pipeline that PID belongs to.  Note that the pipeline
+   doesn't have to belong to a job.  Must be called with SIGCHLD blocked.
+   If JOBP is non-null, return the index of the job containing PID.  */
+static PROCESS *
+find_pipeline (pid, alive_only, jobp)
+     pid_t pid;
+     int alive_only;
+     int *jobp;                /* index into jobs list or NO_JOB */
+{
+  int job;
+  PROCESS *p;
+
+  /* See if this process is in the pipeline that we are building. */
+  if (jobp)
+    *jobp = NO_JOB;
+  if (the_pipeline)
+    {
+      p = the_pipeline;
+      do
+       {
+         /* Return it if we found it.  Don't ever return a recycled pid. */
+         if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
+           return (p);
+
+         p = p->next;
+       }
+      while (p != the_pipeline);
+    }
+
+  job = find_job (pid, alive_only, &p);
+  if (jobp)
+    *jobp = job;
+  return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
+}
+
+/* Return the PROCESS * describing PID.  If JOBP is non-null return the index
+   into the jobs array of the job containing PID.  Must be called with
+   SIGCHLD blocked. */
+static PROCESS *
+find_process (pid, alive_only, jobp)
+     pid_t pid;
+     int alive_only;
+     int *jobp;                /* index into jobs list or NO_JOB */
+{
+  PROCESS *p;
+
+  p = find_pipeline (pid, alive_only, jobp);
+  while (p && p->pid != pid)
+    p = p->next;
+  return p;
+}
+
+/* Return the job index that PID belongs to, or NO_JOB if it doesn't
+   belong to any job.  Must be called with SIGCHLD blocked. */
+static int
+find_job (pid, alive_only, procp)
+     pid_t pid;
+     int alive_only;
+     PROCESS **procp;
+{
+  register int i;
+  PROCESS *p;
+
+  /* XXX could use js.j_firstj here, and should check js.j_lastj */
+  for (i = 0; i < js.j_jobslots; i++)
+    {
+#if defined (DEBUG)
+      if (i < js.j_firstj && jobs[i])
+       itrace("find_job: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+      if (i > js.j_lastj && jobs[i])
+       itrace("find_job: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+      if (jobs[i])
+       {
+         p = jobs[i]->pipe;
+
+         do
+           {
+             if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
+               {
+                 if (procp)
+                   *procp = p;
+                 return (i);
+               }
+
+             p = p->next;
+           }
+         while (p != jobs[i]->pipe);
+       }
+    }
+
+  return (NO_JOB);
+}
+
+/* Find a job given a PID.  If BLOCK is non-zero, block SIGCHLD as
+   required by find_job. */
+int
+get_job_by_pid (pid, block)
+     pid_t pid;
+     int block;
+{
+  int job;
+  sigset_t set, oset;
+
+  if (block)
+    BLOCK_CHILD (set, oset);
+
+  job = find_job (pid, 0, NULL);
+
+  if (block)
+    UNBLOCK_CHILD (oset);
+
+  return job;
+}
+
+/* Print descriptive information about the job with leader pid PID. */
+void
+describe_pid (pid)
+     pid_t pid;
+{
+  int job;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  job = find_job (pid, 0, NULL);
+
+  if (job != NO_JOB)
+    fprintf (stderr, "[%d] %ld\n", job + 1, (long)pid);
+  else
+    programming_error (_("describe_pid: %ld: no such pid"), (long)pid);
+
+  UNBLOCK_CHILD (oset);
+}
+
+static char *
+j_strsignal (s)
+     int s;
+{
+  char *x;
+
+  x = strsignal (s);
+  if (x == 0)
+    {
+      x = retcode_name_buffer;
+      sprintf (x, _("Signal %d"), s);
+    }
+  return x;
+}
+
+static char *
+printable_job_status (j, p, format)
+     int j;
+     PROCESS *p;
+     int format;
+{
+  static char *temp;
+  int es;
+
+  temp = _("Done");
+
+  if (STOPPED (j) && format == 0)
+    {
+      if (posixly_correct == 0 || p == 0 || (WIFSTOPPED (p->status) == 0))
+       temp = _("Stopped");
+      else
+       {
+         temp = retcode_name_buffer;
+         sprintf (temp, _("Stopped(%s)"), signal_name (WSTOPSIG (p->status)));
+       }
+    }
+  else if (RUNNING (j))
+    temp = _("Running");
+  else
+    {
+      if (WIFSTOPPED (p->status))
+       temp = j_strsignal (WSTOPSIG (p->status));
+      else if (WIFSIGNALED (p->status))
+       temp = j_strsignal (WTERMSIG (p->status));
+      else if (WIFEXITED (p->status))
+       {
+         temp = retcode_name_buffer;
+         es = WEXITSTATUS (p->status);
+         if (es == 0)
+           strcpy (temp, _("Done"));
+         else if (posixly_correct)
+           sprintf (temp, _("Done(%d)"), es);
+         else
+           sprintf (temp, _("Exit %d"), es);
+       }
+      else
+       temp = _("Unknown status");
+    }
+
+  return temp;
+}
+
+/* This is the way to print out information on a job if you
+   know the index.  FORMAT is:
+
+    JLIST_NORMAL)   [1]+ Running          emacs
+    JLIST_LONG  )   [1]+ 2378 Running      emacs
+    -1   )   [1]+ 2378       emacs
+
+    JLIST_NORMAL)   [1]+ Stopped          ls | more
+    JLIST_LONG  )   [1]+ 2369 Stopped      ls
+                        2367       | more
+    JLIST_PID_ONLY)
+       Just list the pid of the process group leader (really
+       the process group).
+    JLIST_CHANGED_ONLY)
+       Use format JLIST_NORMAL, but list only jobs about which
+       the user has not been notified. */
+
+/* Print status for pipeline P.  If JOB_INDEX is >= 0, it is the index into
+   the JOBS array corresponding to this pipeline.  FORMAT is as described
+   above.  Must be called with SIGCHLD blocked.
+
+   If you're printing a pipeline that's not in the jobs array, like the
+   current pipeline as it's being created, pass -1 for JOB_INDEX */
+static void
+print_pipeline (p, job_index, format, stream)
+     PROCESS *p;
+     int job_index, format;
+     FILE *stream;
+{
+  PROCESS *first, *last, *show;
+  int es, name_padding;
+  char *temp;
+
+  if (p == 0)
+    return;
+
+  first = last = p;
+  while (last->next != first)
+    last = last->next;
+
+  for (;;)
+    {
+      if (p != first)
+       fprintf (stream, format ? "     " : " |");
+
+      if (format != JLIST_STANDARD)
+       fprintf (stream, "%5ld", (long)p->pid);
+
+      fprintf (stream, " ");
+
+      if (format > -1 && job_index >= 0)
+       {
+         show = format ? p : last;
+         temp = printable_job_status (job_index, show, format);
+
+         if (p != first)
+           {
+             if (format)
+               {
+                 if (show->running == first->running &&
+                     WSTATUS (show->status) == WSTATUS (first->status))
+                   temp = "";
+               }
+             else
+               temp = (char *)NULL;
+           }
+
+         if (temp)
+           {
+             fprintf (stream, "%s", temp);
+
+             es = STRLEN (temp);
+             if (es == 0)
+               es = 2; /* strlen ("| ") */
+             name_padding = LONGEST_SIGNAL_DESC - es;
+
+             fprintf (stream, "%*s", name_padding, "");
+
+             if ((WIFSTOPPED (show->status) == 0) &&
+                 (WIFCONTINUED (show->status) == 0) &&
+                 WIFCORED (show->status))
+               fprintf (stream, _("(core dumped) "));
+           }
+       }
+
+      if (p != first && format)
+       fprintf (stream, "| ");
+
+      if (p->command)
+       fprintf (stream, "%s", p->command);
+
+      if (p == last && job_index >= 0)
+       {
+         temp = current_working_directory ();
+
+         if (RUNNING (job_index) && (IS_FOREGROUND (job_index) == 0))
+           fprintf (stream, " &");
+
+         if (strcmp (temp, jobs[job_index]->wd) != 0)
+           fprintf (stream,
+             _("  (wd: %s)"), polite_directory_format (jobs[job_index]->wd));
+       }
+
+      if (format || (p == last))
+       {
+         /* We need to add a CR only if this is an interactive shell, and
+            we're reporting the status of a completed job asynchronously.
+            We can't really check whether this particular job is being
+            reported asynchronously, so just add the CR if the shell is
+            currently interactive and asynchronous notification is enabled. */
+         if (asynchronous_notification && interactive)
+           fprintf (stream, "\r\n");
+         else
+           fprintf (stream, "\n");
+       }
+
+      if (p == last)
+       break;
+      p = p->next;
+    }
+  fflush (stream);
+}
+
+/* Print information to STREAM about jobs[JOB_INDEX] according to FORMAT.
+   Must be called with SIGCHLD blocked or queued with queue_sigchld */
+static void
+pretty_print_job (job_index, format, stream)
+     int job_index, format;
+     FILE *stream;
+{
+  register PROCESS *p;
+
+  /* Format only pid information about the process group leader? */
+  if (format == JLIST_PID_ONLY)
+    {
+      fprintf (stream, "%ld\n", (long)jobs[job_index]->pipe->pid);
+      return;
+    }
+
+  if (format == JLIST_CHANGED_ONLY)
+    {
+      if (IS_NOTIFIED (job_index))
+       return;
+      format = JLIST_STANDARD;
+    }
+
+  if (format != JLIST_NONINTERACTIVE)
+    fprintf (stream, "[%d]%c ", job_index + 1,
+             (job_index == js.j_current) ? '+':
+               (job_index == js.j_previous) ? '-' : ' ');
+
+  if (format == JLIST_NONINTERACTIVE)
+    format = JLIST_LONG;
+
+  p = jobs[job_index]->pipe;
+
+  print_pipeline (p, job_index, format, stream);
+
+  /* We have printed information about this job.  When the job's
+     status changes, waitchld () sets the notification flag to 0. */
+  jobs[job_index]->flags |= J_NOTIFIED;
+}
+
+static int
+print_job (job, format, state, job_index)
+     JOB *job;
+     int format, state, job_index;
+{
+  if (state == -1 || (JOB_STATE)state == job->state)
+    pretty_print_job (job_index, format, stdout);
+  return (0);
+}
+
+void
+list_one_job (job, format, ignore, job_index)
+     JOB *job;
+     int format, ignore, job_index;
+{
+  pretty_print_job (job_index, format, stdout);
+}
+
+void
+list_stopped_jobs (format)
+     int format;
+{
+  cleanup_dead_jobs ();
+  map_over_jobs (print_job, format, (int)JSTOPPED);
+}
+
+void
+list_running_jobs (format)
+     int format;
+{
+  cleanup_dead_jobs ();
+  map_over_jobs (print_job, format, (int)JRUNNING);
+}
+
+/* List jobs.  If FORMAT is non-zero, then the long form of the information
+   is printed, else just a short version. */
+void
+list_all_jobs (format)
+     int format;
+{
+  cleanup_dead_jobs ();
+  map_over_jobs (print_job, format, -1);
+}
+
+/* Fork, handling errors.  Returns the pid of the newly made child, or 0.
+   COMMAND is just for remembering the name of the command; we don't do
+   anything else with it.  ASYNC_P says what to do with the tty.  If
+   non-zero, then don't give it away. */
+pid_t
+make_child (command, async_p)
+     char *command;
+     int async_p;
+{
+  int forksleep;
+  sigset_t set, oset;
+  pid_t pid;
+
+  sigemptyset (&set);
+  sigaddset (&set, SIGCHLD);
+  sigaddset (&set, SIGINT);
+  sigemptyset (&oset);
+  sigprocmask (SIG_BLOCK, &set, &oset);
+
+  making_children ();
+
+  forksleep = 1;
+
+#if defined (BUFFERED_INPUT)
+  /* If default_buffered_input is active, we are reading a script.  If
+     the command is asynchronous, we have already duplicated /dev/null
+     as fd 0, but have not changed the buffered stream corresponding to
+     the old fd 0.  We don't want to sync the stream in this case. */
+  if (default_buffered_input != -1 &&
+      (!async_p || default_buffered_input > 0))
+    sync_buffered_stream (default_buffered_input);
+#endif /* BUFFERED_INPUT */
+
+  /* Create the child, handle severe errors.  Retry on EAGAIN. */
+  while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX)
+    {
+      /* bash-4.2 */
+      /* If we can't create any children, try to reap some dead ones. */
+      waitchld (-1, 0);
+
+      sys_error ("fork: retry");
+      if (sleep (forksleep) != 0)
+       break;
+      forksleep <<= 1;
+    }
+
+  if (pid < 0)
+    {
+      sys_error ("fork");
+
+      /* Kill all of the processes in the current pipeline. */
+      terminate_current_pipeline ();
+
+      /* Discard the current pipeline, if any. */
+      if (the_pipeline)
+       kill_current_pipeline ();
+
+      last_command_exit_value = EX_NOEXEC;
+      throw_to_top_level ();   /* Reset signals, etc. */
+    }
+
+  if (pid == 0)
+    {
+      /* In the child.  Give this child the right process group, set the
+        signals to the default state for a new process. */
+      pid_t mypid;
+
+      mypid = getpid ();
+#if defined (BUFFERED_INPUT)
+      /* Close default_buffered_input if it's > 0.  We don't close it if it's
+        0 because that's the file descriptor used when redirecting input,
+        and it's wrong to close the file in that case. */
+      unset_bash_input (0);
+#endif /* BUFFERED_INPUT */
+
+      /* Restore top-level signal mask. */
+      sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
+
+      if (job_control)
+       {
+         /* All processes in this pipeline belong in the same
+            process group. */
+
+         if (pipeline_pgrp == 0)       /* This is the first child. */
+           pipeline_pgrp = mypid;
+
+         /* Check for running command in backquotes. */
+         if (pipeline_pgrp == shell_pgrp)
+           ignore_tty_job_signals ();
+         else
+           default_tty_job_signals ();
+
+         /* Set the process group before trying to mess with the terminal's
+            process group.  This is mandated by POSIX. */
+         /* This is in accordance with the Posix 1003.1 standard,
+            section B.7.2.4, which says that trying to set the terminal
+            process group with tcsetpgrp() to an unused pgrp value (like
+            this would have for the first child) is an error.  Section
+            B.4.3.3, p. 237 also covers this, in the context of job control
+            shells. */
+         if (setpgid (mypid, pipeline_pgrp) < 0)
+           sys_error (_("child setpgid (%ld to %ld)"), (long)mypid, (long)pipeline_pgrp);
+
+         /* By convention (and assumption above), if
+            pipeline_pgrp == shell_pgrp, we are making a child for
+            command substitution.
+            In this case, we don't want to give the terminal to the
+            shell's process group (we could be in the middle of a
+            pipeline, for example). */
+         if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&SUBSHELL_ASYNC) == 0))
+           give_terminal_to (pipeline_pgrp, 0);
+
+#if defined (PGRP_PIPE)
+         if (pipeline_pgrp == mypid)
+           pipe_read (pgrp_pipe);
+#endif
+       }
+      else                     /* Without job control... */
+       {
+         if (pipeline_pgrp == 0)
+           pipeline_pgrp = shell_pgrp;
+
+         /* If these signals are set to SIG_DFL, we encounter the curious
+            situation of an interactive ^Z to a running process *working*
+            and stopping the process, but being unable to do anything with
+            that process to change its state.  On the other hand, if they
+            are set to SIG_IGN, jobs started from scripts do not stop when
+            the shell running the script gets a SIGTSTP and stops. */
+
+         default_tty_job_signals ();
+       }
+
+#if defined (PGRP_PIPE)
+      /* Release the process group pipe, since our call to setpgid ()
+        is done.  The last call to sh_closepipe is done in stop_pipeline. */
+      sh_closepipe (pgrp_pipe);
+#endif /* PGRP_PIPE */
+
+#if 0
+      /* Don't set last_asynchronous_pid in the child */
+      if (async_p)
+       last_asynchronous_pid = mypid;          /* XXX */
+      else
+#endif
+#if defined (RECYCLES_PIDS)
+      if (last_asynchronous_pid == mypid)
+        /* Avoid pid aliasing.  1 seems like a safe, unusual pid value. */
+       last_asynchronous_pid = 1;
+#endif
+    }
+  else
+    {
+      /* In the parent.  Remember the pid of the child just created
+        as the proper pgrp if this is the first child. */
+
+      if (first_pid == NO_PID)
+       first_pid = pid;
+      else if (pid_wrap == -1 && pid < first_pid)
+       pid_wrap = 0;
+      else if (pid_wrap == 0 && pid >= first_pid)
+       pid_wrap = 1;
+
+      if (job_control)
+       {
+         if (pipeline_pgrp == 0)
+           {
+             pipeline_pgrp = pid;
+             /* Don't twiddle terminal pgrps in the parent!  This is the bug,
+                not the good thing of twiddling them in the child! */
+             /* give_terminal_to (pipeline_pgrp, 0); */
+           }
+         /* This is done on the recommendation of the Rationale section of
+            the POSIX 1003.1 standard, where it discusses job control and
+            shells.  It is done to avoid possible race conditions. (Ref.
+            1003.1 Rationale, section B.4.3.3, page 236). */
+         setpgid (pid, pipeline_pgrp);
+       }
+      else
+       {
+         if (pipeline_pgrp == 0)
+           pipeline_pgrp = shell_pgrp;
+       }
+
+      /* Place all processes into the jobs array regardless of the
+        state of job_control. */
+      add_process (command, pid);
+
+      if (async_p)
+       last_asynchronous_pid = pid;
+#if defined (RECYCLES_PIDS)
+      else if (last_asynchronous_pid == pid)
+        /* Avoid pid aliasing.  1 seems like a safe, unusual pid value. */
+       last_asynchronous_pid = 1;
+#endif
+
+      if (pid_wrap > 0)
+       delete_old_job (pid);
+
+#if !defined (RECYCLES_PIDS)
+      /* Only check for saved status if we've saved more than CHILD_MAX
+        statuses, unless the system recycles pids. */
+      if ((js.c_reaped + bgpids.npid) >= js.c_childmax)
+#endif
+       bgp_delete (pid);               /* new process, discard any saved status */
+
+      last_made_pid = pid;
+
+      /* keep stats */
+      js.c_totforked++;
+      js.c_living++;
+
+      /* Unblock SIGINT and SIGCHLD unless creating a pipeline, in which case
+        SIGCHLD remains blocked until all commands in the pipeline have been
+        created. */
+      sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+    }
+
+  return (pid);
+}
+
+/* These two functions are called only in child processes. */
+void
+ignore_tty_job_signals ()
+{
+  set_signal_handler (SIGTSTP, SIG_IGN);
+  set_signal_handler (SIGTTIN, SIG_IGN);
+  set_signal_handler (SIGTTOU, SIG_IGN);
+}
+
+void
+default_tty_job_signals ()
+{
+  set_signal_handler (SIGTSTP, SIG_DFL);
+  set_signal_handler (SIGTTIN, SIG_DFL);
+  set_signal_handler (SIGTTOU, SIG_DFL);
+}
+
+/* When we end a job abnormally, or if we stop a job, we set the tty to the
+   state kept in here.  When a job ends normally, we set the state in here
+   to the state of the tty. */
+
+static TTYSTRUCT shell_tty_info;
+
+#if defined (NEW_TTY_DRIVER)
+static struct tchars shell_tchars;
+static struct ltchars shell_ltchars;
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (NEW_TTY_DRIVER) && defined (DRAIN_OUTPUT)
+/* Since the BSD tty driver does not allow us to change the tty modes
+   while simultaneously waiting for output to drain and preserving
+   typeahead, we have to drain the output ourselves before calling
+   ioctl.  We cheat by finding the length of the output queue, and
+   using select to wait for an appropriate length of time.  This is
+   a hack, and should be labeled as such (it's a hastily-adapted
+   mutation of a `usleep' implementation).  It's only reason for
+   existing is the flaw in the BSD tty driver. */
+
+static int ttspeeds[] =
+{
+  0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+  1800, 2400, 4800, 9600, 19200, 38400
+};
+
+static void
+draino (fd, ospeed)
+     int fd, ospeed;
+{
+  register int delay = ttspeeds[ospeed];
+  int n;
+
+  if (!delay)
+    return;
+
+  while ((ioctl (fd, TIOCOUTQ, &n) == 0) && n)
+    {
+      if (n > (delay / 100))
+       {
+         struct timeval tv;
+
+         n *= 10;              /* 2 bits more for conservativeness. */
+         tv.tv_sec = n / delay;
+         tv.tv_usec = ((n % delay) * 1000000) / delay;
+         select (fd, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
+       }
+      else
+       break;
+    }
+}
+#endif /* NEW_TTY_DRIVER && DRAIN_OUTPUT */
+
+/* Return the fd from which we are actually getting input. */
+#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
+
+/* Fill the contents of shell_tty_info with the current tty info. */
+int
+get_tty_state ()
+{
+  int tty;
+
+  tty = input_tty ();
+  if (tty != -1)
+    {
+#if defined (NEW_TTY_DRIVER)
+      ioctl (tty, TIOCGETP, &shell_tty_info);
+      ioctl (tty, TIOCGETC, &shell_tchars);
+      ioctl (tty, TIOCGLTC, &shell_ltchars);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+      ioctl (tty, TCGETA, &shell_tty_info);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+      if (tcgetattr (tty, &shell_tty_info) < 0)
+       {
+#if 0
+         /* Only print an error message if we're really interactive at
+            this time. */
+         if (interactive)
+           sys_error ("[%ld: %d (%d)] tcgetattr", (long)getpid (), shell_level, tty);
+#endif
+         return -1;
+       }
+#endif /* TERMIOS_TTY_DRIVER */
+      if (check_window_size)
+       get_new_window_size (0, (int *)0, (int *)0);
+    }
+  return 0;
+}
+
+/* Make the current tty use the state in shell_tty_info. */
+int
+set_tty_state ()
+{
+  int tty;
+
+  tty = input_tty ();
+  if (tty != -1)
+    {
+#if defined (NEW_TTY_DRIVER)
+#  if defined (DRAIN_OUTPUT)
+      draino (tty, shell_tty_info.sg_ospeed);
+#  endif /* DRAIN_OUTPUT */
+      ioctl (tty, TIOCSETN, &shell_tty_info);
+      ioctl (tty, TIOCSETC, &shell_tchars);
+      ioctl (tty, TIOCSLTC, &shell_ltchars);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+      ioctl (tty, TCSETAW, &shell_tty_info);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+      if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
+       {
+         /* Only print an error message if we're really interactive at
+            this time. */
+         if (interactive)
+           sys_error ("[%ld: %d (%d)] tcsetattr", (long)getpid (), shell_level, tty);
+         return -1;
+       }
+#endif /* TERMIOS_TTY_DRIVER */
+    }
+  return 0;
+}
+
+/* Given an index into the jobs array JOB, return the PROCESS struct of the last
+   process in that job's pipeline.  This is the one whose exit status
+   counts.  Must be called with SIGCHLD blocked or queued. */
+static PROCESS *
+find_last_proc (job, block)
+     int job;
+     int block;
+{
+  register PROCESS *p;
+  sigset_t set, oset;
+
+  if (block)
+    BLOCK_CHILD (set, oset);
+
+  p = jobs[job]->pipe;
+  while (p && p->next != jobs[job]->pipe)
+    p = p->next;
+
+  if (block)
+    UNBLOCK_CHILD (oset);
+
+  return (p);
+}
+
+static pid_t
+find_last_pid (job, block)
+     int job;
+     int block;
+{
+  PROCESS *p;
+
+  p = find_last_proc (job, block);
+  /* Possible race condition here. */
+  return p->pid;
+}     
+
+/* Wait for a particular child of the shell to finish executing.
+   This low-level function prints an error message if PID is not
+   a child of this shell.  It returns -1 if it fails, or whatever
+   wait_for returns otherwise.  If the child is not found in the
+   jobs table, it returns 127. */
+int
+wait_for_single_pid (pid)
+     pid_t pid;
+{
+  register PROCESS *child;
+  sigset_t set, oset;
+  int r, job;
+
+  BLOCK_CHILD (set, oset);
+  child = find_pipeline (pid, 0, (int *)NULL);
+  UNBLOCK_CHILD (oset);
+
+  if (child == 0)
+    {
+      r = bgp_search (pid);
+      if (r >= 0)
+       return r;
+    }
+
+  if (child == 0)
+    {
+      internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
+      return (127);
+    }
+
+  r = wait_for (pid);
+
+  /* POSIX.2: if we just waited for a job, we can remove it from the jobs
+     table. */
+  BLOCK_CHILD (set, oset);
+  job = find_job (pid, 0, NULL);
+  if (job != NO_JOB && jobs[job] && DEADJOB (job))
+    jobs[job]->flags |= J_NOTIFIED;
+  UNBLOCK_CHILD (oset);
+
+  /* If running in posix mode, remove the job from the jobs table immediately */
+  if (posixly_correct)
+    {
+      cleanup_dead_jobs ();
+      bgp_delete (pid);
+    }
+
+  return r;
+}
+
+/* Wait for all of the background processes started by this shell to finish. */
+void
+wait_for_background_pids ()
+{
+  register int i, r, waited_for;
+  sigset_t set, oset;
+  pid_t pid;
+
+  for (waited_for = 0;;)
+    {
+      BLOCK_CHILD (set, oset);
+
+      /* find first running job; if none running in foreground, break */
+      /* XXX could use js.j_firstj and js.j_lastj here */
+      for (i = 0; i < js.j_jobslots; i++)
+       {
+#if defined (DEBUG)
+         if (i < js.j_firstj && jobs[i])
+           itrace("wait_for_background_pids: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+         if (i > js.j_lastj && jobs[i])
+           itrace("wait_for_background_pids: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+         if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
+           break;
+       }
+      if (i == js.j_jobslots)
+       {
+         UNBLOCK_CHILD (oset);
+         break;
+       }
+
+      /* now wait for the last pid in that job. */
+      pid = find_last_pid (i, 0);
+      UNBLOCK_CHILD (oset);
+      QUIT;
+      errno = 0;               /* XXX */
+      r = wait_for_single_pid (pid);
+      if (r == -1)
+       {
+         /* If we're mistaken about job state, compensate. */
+         if (errno == ECHILD)
+           mark_all_jobs_as_dead ();
+       }
+      else
+       waited_for++;
+    }
+
+  /* POSIX.2 says the shell can discard the statuses of all completed jobs if
+     `wait' is called with no arguments. */
+  mark_dead_jobs_as_notified (1);
+  cleanup_dead_jobs ();
+  bgp_clear ();
+}
+
+/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
+#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
+static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
+
+static int wait_sigint_received;
+static int child_caught_sigint;
+static int waiting_for_child;
+
+static void
+restore_sigint_handler ()
+{
+  if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
+    {
+      set_signal_handler (SIGINT, old_sigint_handler);
+      old_sigint_handler = INVALID_SIGNAL_HANDLER;
+      waiting_for_child = 0;
+    }
+}
+
+/* Handle SIGINT while we are waiting for children in a script to exit.
+   The `wait' builtin should be interruptible, but all others should be
+   effectively ignored (i.e. not cause the shell to exit). */
+static sighandler
+wait_sigint_handler (sig)
+     int sig;
+{
+  SigHandler *sigint_handler;
+
+  if (interrupt_immediately ||
+      (this_shell_builtin && this_shell_builtin == wait_builtin))
+    {
+      last_command_exit_value = EXECUTION_FAILURE;
+      restore_sigint_handler ();
+      /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
+        what POSIX.2 says (see builtins/wait.def for more info). */
+      if (this_shell_builtin && this_shell_builtin == wait_builtin &&
+         signal_is_trapped (SIGINT) &&
+         ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
+       {
+         interrupt_immediately = 0;
+         trap_handler (SIGINT);        /* set pending_traps[SIGINT] */
+         wait_signal_received = SIGINT;
+         longjmp (wait_intr_buf, 1);
+       }
+      
+      ADDINTERRUPT;
+      QUIT;
+    }
+
+  /* XXX - should this be interrupt_state?  If it is, the shell will act
+     as if it got the SIGINT interrupt. */
+  if (waiting_for_child)
+    wait_sigint_received = 1;
+  else
+    {
+      last_command_exit_value = 128+SIGINT;
+      restore_sigint_handler ();
+      kill (getpid (), SIGINT);
+    }
+
+  /* Otherwise effectively ignore the SIGINT and allow the running job to
+     be killed. */
+  SIGRETURN (0);
+}
+
+static int
+process_exit_signal (status)
+     WAIT status;
+{
+  return (WIFSIGNALED (status) ? WTERMSIG (status) : 0);
+}
+
+static int
+process_exit_status (status)
+     WAIT status;
+{
+  if (WIFSIGNALED (status))
+    return (128 + WTERMSIG (status));
+  else if (WIFSTOPPED (status) == 0)
+    return (WEXITSTATUS (status));
+  else
+    return (EXECUTION_SUCCESS);
+}
+
+static WAIT
+job_signal_status (job)
+     int job;
+{
+  register PROCESS *p;
+  WAIT s;
+
+  p = jobs[job]->pipe;
+  do
+    {
+      s = p->status;
+      if (WIFSIGNALED(s) || WIFSTOPPED(s))
+       break;
+      p = p->next;
+    }
+  while (p != jobs[job]->pipe);
+
+  return s;
+}
+  
+/* Return the exit status of the last process in the pipeline for job JOB.
+   This is the exit status of the entire job. */
+static WAIT
+raw_job_exit_status (job)
+     int job;
+{
+  register PROCESS *p;
+  int fail;
+  WAIT ret;
+
+  if (pipefail_opt)
+    {
+      fail = 0;
+      p = jobs[job]->pipe;
+      do
+       {
+         if (WSTATUS (p->status) != EXECUTION_SUCCESS)
+           fail = WSTATUS(p->status);
+         p = p->next;
+       }
+      while (p != jobs[job]->pipe);
+      WSTATUS (ret) = fail;
+      return ret;
+    }
+
+  for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
+    ;
+  return (p->status);
+}
+
+/* Return the exit status of job JOB.  This is the exit status of the last
+   (rightmost) process in the job's pipeline, modified if the job was killed
+   by a signal or stopped. */
+int
+job_exit_status (job)
+     int job;
+{
+  return (process_exit_status (raw_job_exit_status (job)));
+}
+
+int
+job_exit_signal (job)
+     int job;
+{
+  return (process_exit_signal (raw_job_exit_status (job)));
+}
+
+#define FIND_CHILD(pid, child) \
+  do \
+    { \
+      child = find_pipeline (pid, 0, (int *)NULL); \
+      if (child == 0) \
+       { \
+         give_terminal_to (shell_pgrp, 0); \
+         UNBLOCK_CHILD (oset); \
+         internal_error (_("wait_for: No record of process %ld"), (long)pid); \
+         restore_sigint_handler (); \
+         return (termination_state = 127); \
+       } \
+    } \
+  while (0)
+
+/* Wait for pid (one of our children) to terminate, then
+   return the termination state.  Returns 127 if PID is not found in
+   the jobs table.  Returns -1 if waitchld() returns -1, indicating
+   that there are no unwaited-for child processes. */
+int
+wait_for (pid)
+     pid_t pid;
+{
+  int job, termination_state, r;
+  WAIT s;
+  register PROCESS *child;
+  sigset_t set, oset;
+
+  /* In the case that this code is interrupted, and we longjmp () out of it,
+     we are relying on the code in throw_to_top_level () to restore the
+     top-level signal mask. */
+  BLOCK_CHILD (set, oset);
+
+  /* Ignore interrupts while waiting for a job run without job control
+     to finish.  We don't want the shell to exit if an interrupt is
+     received, only if one of the jobs run is killed via SIGINT.  If
+     job control is not set, the job will be run in the same pgrp as
+     the shell, and the shell will see any signals the job gets.  In
+     fact, we want this set every time the waiting shell and the waited-
+     for process are in the same process group, including command
+     substitution. */
+
+  /* This is possibly a race condition -- should it go in stop_pipeline? */
+  wait_sigint_received = child_caught_sigint = 0;
+  if (job_control == 0 || (subshell_environment&SUBSHELL_COMSUB))
+    {
+      old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
+      waiting_for_child = 0;
+      if (old_sigint_handler == SIG_IGN)
+       set_signal_handler (SIGINT, old_sigint_handler);
+    }
+
+  termination_state = last_command_exit_value;
+
+  if (interactive && job_control == 0)
+    QUIT;
+  /* Check for terminating signals and exit the shell if we receive one */
+  CHECK_TERMSIG;
+
+  /* If we say wait_for (), then we have a record of this child somewhere.
+     If it and none of its peers are running, don't call waitchld(). */
+
+  job = NO_JOB;
+  do
+    {
+      FIND_CHILD (pid, child);
+
+      /* If this child is part of a job, then we are really waiting for the
+        job to finish.  Otherwise, we are waiting for the child to finish.
+        We check for JDEAD in case the job state has been set by waitchld
+        after receipt of a SIGCHLD. */
+      if (job == NO_JOB)
+       job = find_job (pid, 0, NULL);
+
+      /* waitchld() takes care of setting the state of the job.  If the job
+        has already exited before this is called, sigchld_handler will have
+        called waitchld and the state will be set to JDEAD. */
+
+      if (PRUNNING(child) || (job != NO_JOB && RUNNING (job)))
+       {
+#if defined (WAITPID_BROKEN)    /* SCOv4 */
+         sigset_t suspend_set;
+         sigemptyset (&suspend_set);
+         sigsuspend (&suspend_set);
+#else /* !WAITPID_BROKEN */
+#  if defined (MUST_UNBLOCK_CHLD)
+         struct sigaction act, oact;
+         sigset_t nullset, chldset;
+
+         sigemptyset (&nullset);
+         sigemptyset (&chldset);
+         sigprocmask (SIG_SETMASK, &nullset, &chldset);
+         act.sa_handler = SIG_DFL;
+         sigemptyset (&act.sa_mask);
+         sigemptyset (&oact.sa_mask);
+         act.sa_flags = 0;
+         sigaction (SIGCHLD, &act, &oact);
+#  endif
+         queue_sigchld = 1;
+         waiting_for_child++;
+         r = waitchld (pid, 1);
+         waiting_for_child--;
+#  if defined (MUST_UNBLOCK_CHLD)
+         sigaction (SIGCHLD, &oact, (struct sigaction *)NULL);
+         sigprocmask (SIG_SETMASK, &chldset, (sigset_t *)NULL);
+#  endif
+         queue_sigchld = 0;
+         if (r == -1 && errno == ECHILD && this_shell_builtin == wait_builtin)
+           {
+             termination_state = -1;
+             goto wait_for_return;
+           }
+
+         /* If child is marked as running, but waitpid() returns -1/ECHILD,
+            there is something wrong.  Somewhere, wait should have returned
+            that child's pid.  Mark the child as not running and the job,
+            if it exists, as JDEAD. */
+         if (r == -1 && errno == ECHILD)
+           {
+             child->running = PS_DONE;
+             WSTATUS (child->status) = 0;      /* XXX -- can't find true status */
+             js.c_living = 0;          /* no living child processes */
+             if (job != NO_JOB)
+               {
+                 jobs[job]->state = JDEAD;
+                 js.c_reaped++;
+                 js.j_ndead++;
+               }
+           }
+#endif /* WAITPID_BROKEN */
+       }
+
+      /* If the shell is interactive, and job control is disabled, see
+        if the foreground process has died due to SIGINT and jump out
+        of the wait loop if it has.  waitchld has already restored the
+        old SIGINT signal handler. */
+      if (interactive && job_control == 0)
+       QUIT;
+      /* Check for terminating signals and exit the shell if we receive one */
+      CHECK_TERMSIG;
+    }
+  while (PRUNNING (child) || (job != NO_JOB && RUNNING (job)));
+
+  /* Restore the original SIGINT signal handler before we return. */
+  restore_sigint_handler ();
+
+  /* The exit state of the command is either the termination state of the
+     child, or the termination state of the job.  If a job, the status
+     of the last child in the pipeline is the significant one.  If the command
+     or job was terminated by a signal, note that value also. */
+  termination_state = (job != NO_JOB) ? job_exit_status (job)
+                                     : process_exit_status (child->status);
+  last_command_exit_signal = (job != NO_JOB) ? job_exit_signal (job)
+                                            : process_exit_signal (child->status);
+
+  /* XXX */
+  if ((job != NO_JOB && JOBSTATE (job) == JSTOPPED) || WIFSTOPPED (child->status))
+    termination_state = 128 + WSTOPSIG (child->status);
+
+  if (job == NO_JOB || IS_JOBCONTROL (job))
+    {
+      /* XXX - under what circumstances is a job not present in the jobs
+        table (job == NO_JOB)?
+               1.  command substitution
+
+        In the case of command substitution, at least, it's probably not
+        the right thing to give the terminal to the shell's process group,
+        even though there is code in subst.c:command_substitute to work
+        around it.
+
+        Things that don't:
+               $PROMPT_COMMAND execution
+               process substitution
+       */
+#if 0
+if (job == NO_JOB)
+  itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp);
+#endif
+      give_terminal_to (shell_pgrp, 0);
+    }
+
+  /* If the command did not exit cleanly, or the job is just
+     being stopped, then reset the tty state back to what it
+     was before this command.  Reset the tty state and notify
+     the user of the job termination only if the shell is
+     interactive.  Clean up any dead jobs in either case. */
+  if (job != NO_JOB)
+    {
+      if (interactive_shell && subshell_environment == 0)
+       {
+         /* This used to use `child->status'.  That's wrong, however, for
+            pipelines.  `child' is the first process in the pipeline.  It's
+            likely that the process we want to check for abnormal termination
+            or stopping is the last process in the pipeline, especially if
+            it's long-lived and the first process is short-lived.  Since we
+            know we have a job here, we can check all the processes in this
+            job's pipeline and see if one of them stopped or terminated due
+            to a signal.  We might want to change this later to just check
+            the last process in the pipeline.  If no process exits due to a
+            signal, S is left as the status of the last job in the pipeline. */
+         s = job_signal_status (job);
+
+         if (WIFSIGNALED (s) || WIFSTOPPED (s))
+           {
+             set_tty_state ();
+
+             /* If the current job was stopped or killed by a signal, and
+                the user has requested it, get a possibly new window size */
+             if (check_window_size && (job == js.j_current || IS_FOREGROUND (job)))
+               get_new_window_size (0, (int *)0, (int *)0);
+           }
+         else
+           get_tty_state ();
+
+         /* If job control is enabled, the job was started with job
+            control, the job was the foreground job, and it was killed
+            by SIGINT, then print a newline to compensate for the kernel
+            printing the ^C without a trailing newline. */
+         if (job_control && IS_JOBCONTROL (job) && IS_FOREGROUND (job) &&
+               WIFSIGNALED (s) && WTERMSIG (s) == SIGINT)
+           {
+             /* If SIGINT is not trapped and the shell is in a for, while,
+                or until loop, act as if the shell received SIGINT as
+                well, so the loop can be broken.  This doesn't call the
+                SIGINT signal handler; maybe it should. */
+             if (signal_is_trapped (SIGINT) == 0 && (loop_level || (shell_compatibility_level > 32 && executing_list)))
+               ADDINTERRUPT;
+             else
+               {
+                 putchar ('\n');
+                 fflush (stdout);
+               }
+           }
+       }
+      else if ((subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PIPE)) && wait_sigint_received)
+       {
+         /* If waiting for a job in a subshell started to do command
+            substitution or to run a pipeline element that consists of
+            something like a while loop or a for loop, simulate getting
+            and being killed by the SIGINT to pass the status back to our
+            parent. */
+         s = job_signal_status (job);
+
+         if (child_caught_sigint == 0 && signal_is_trapped (SIGINT) == 0)
+           {
+             UNBLOCK_CHILD (oset);
+             old_sigint_handler = set_signal_handler (SIGINT, SIG_DFL);
+             if (old_sigint_handler == SIG_IGN)
+               restore_sigint_handler ();
+             else
+               kill (getpid (), SIGINT);
+           }
+       }
+      else if (interactive_shell == 0 && IS_FOREGROUND (job) && check_window_size)
+       get_new_window_size (0, (int *)0, (int *)0);
+
+      /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
+         signal handler path */
+      if (DEADJOB (job) && IS_FOREGROUND (job) /*&& subshell_environment == 0*/)
+       setjstatus (job);
+
+      /* If this job is dead, notify the user of the status.  If the shell
+        is interactive, this will display a message on the terminal.  If
+        the shell is not interactive, make sure we turn on the notify bit
+        so we don't get an unwanted message about the job's termination,
+        and so delete_job really clears the slot in the jobs table. */
+      notify_and_cleanup ();
+    }
+
+wait_for_return:
+
+  UNBLOCK_CHILD (oset);
+
+  return (termination_state);
+}
+
+/* Wait for the last process in the pipeline for JOB.  Returns whatever
+   wait_for returns: the last process's termination state or -1 if there
+   are no unwaited-for child processes or an error occurs. */
+int
+wait_for_job (job)
+     int job;
+{
+  pid_t pid;
+  int r;
+  sigset_t set, oset;
+
+  BLOCK_CHILD(set, oset);
+  if (JOBSTATE (job) == JSTOPPED)
+    internal_warning (_("wait_for_job: job %d is stopped"), job+1);
+
+  pid = find_last_pid (job, 0);
+  UNBLOCK_CHILD(oset);
+  r = wait_for (pid);
+
+  /* POSIX.2: we can remove the job from the jobs table if we just waited
+     for it. */
+  BLOCK_CHILD (set, oset);
+  if (job != NO_JOB && jobs[job] && DEADJOB (job))
+    jobs[job]->flags |= J_NOTIFIED;
+  UNBLOCK_CHILD (oset);
+
+  return r;
+}
+
+/* Print info about dead jobs, and then delete them from the list
+   of known jobs.  This does not actually delete jobs when the
+   shell is not interactive, because the dead jobs are not marked
+   as notified. */
+void
+notify_and_cleanup ()
+{
+  if (jobs_list_frozen)
+    return;
+
+  if (interactive || interactive_shell == 0 || sourcelevel)
+    notify_of_job_status ();
+
+  cleanup_dead_jobs ();
+}
+
+/* Make dead jobs disappear from the jobs array without notification.
+   This is used when the shell is not interactive. */
+void
+reap_dead_jobs ()
+{
+  mark_dead_jobs_as_notified (0);
+  cleanup_dead_jobs ();
+}
+
+/* Return the next closest (chronologically) job to JOB which is in
+   STATE.  STATE can be JSTOPPED, JRUNNING.  NO_JOB is returned if
+   there is no next recent job. */
+static int
+most_recent_job_in_state (job, state)
+     int job;
+     JOB_STATE state;
+{
+  register int i, result;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  for (result = NO_JOB, i = job - 1; i >= 0; i--)
+    {
+      if (jobs[i] && (JOBSTATE (i) == state))
+       {
+         result = i;
+         break;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+
+  return (result);
+}
+
+/* Return the newest *stopped* job older than JOB, or NO_JOB if not
+   found. */
+static int
+job_last_stopped (job)
+     int job;
+{
+  return (most_recent_job_in_state (job, JSTOPPED));
+}
+
+/* Return the newest *running* job older than JOB, or NO_JOB if not
+   found. */
+static int
+job_last_running (job)
+     int job;
+{
+  return (most_recent_job_in_state (job, JRUNNING));
+}
+
+/* Make JOB be the current job, and make previous be useful.  Must be
+   called with SIGCHLD blocked. */
+static void
+set_current_job (job)
+     int job;
+{
+  int candidate;
+
+  if (js.j_current != job)
+    {
+      js.j_previous = js.j_current;
+      js.j_current = job;
+    }
+
+  /* First choice for previous job is the old current job. */
+  if (js.j_previous != js.j_current &&
+      js.j_previous != NO_JOB &&
+      jobs[js.j_previous] &&
+      STOPPED (js.j_previous))
+    return;
+
+  /* Second choice:  Newest stopped job that is older than
+     the current job. */
+  candidate = NO_JOB;
+  if (STOPPED (js.j_current))
+    {
+      candidate = job_last_stopped (js.j_current);
+
+      if (candidate != NO_JOB)
+       {
+         js.j_previous = candidate;
+         return;
+       }
+    }
+
+  /* If we get here, there is either only one stopped job, in which case it is
+     the current job and the previous job should be set to the newest running
+     job, or there are only running jobs and the previous job should be set to
+     the newest running job older than the current job.  We decide on which
+     alternative to use based on whether or not JOBSTATE(js.j_current) is
+     JSTOPPED. */
+
+  candidate = RUNNING (js.j_current) ? job_last_running (js.j_current)
+                                   : job_last_running (js.j_jobslots);
+
+  if (candidate != NO_JOB)
+    {
+      js.j_previous = candidate;
+      return;
+    }
+
+  /* There is only a single job, and it is both `+' and `-'. */
+  js.j_previous = js.j_current;
+}
+
+/* Make current_job be something useful, if it isn't already. */
+
+/* Here's the deal:  The newest non-running job should be `+', and the
+   next-newest non-running job should be `-'.  If there is only a single
+   stopped job, the js.j_previous is the newest non-running job.  If there
+   are only running jobs, the newest running job is `+' and the
+   next-newest running job is `-'.  Must be called with SIGCHLD blocked. */
+
+static void
+reset_current ()
+{
+  int candidate;
+
+  if (js.j_jobslots && js.j_current != NO_JOB && jobs[js.j_current] && STOPPED (js.j_current))
+    candidate = js.j_current;
+  else
+    {
+      candidate = NO_JOB;
+
+      /* First choice: the previous job. */
+      if (js.j_previous != NO_JOB && jobs[js.j_previous] && STOPPED (js.j_previous))
+       candidate = js.j_previous;
+
+      /* Second choice: the most recently stopped job. */
+      if (candidate == NO_JOB)
+       candidate = job_last_stopped (js.j_jobslots);
+
+      /* Third choice: the newest running job. */
+      if (candidate == NO_JOB)
+       candidate = job_last_running (js.j_jobslots);
+    }
+
+  /* If we found a job to use, then use it.  Otherwise, there
+     are no jobs period. */
+  if (candidate != NO_JOB)
+    set_current_job (candidate);
+  else
+    js.j_current = js.j_previous = NO_JOB;
+}
+
+/* Set up the job structures so we know the job and its processes are
+   all running. */
+static void
+set_job_running (job)
+     int job;
+{
+  register PROCESS *p;
+
+  /* Each member of the pipeline is now running. */
+  p = jobs[job]->pipe;
+
+  do
+    {
+      if (WIFSTOPPED (p->status))
+       p->running = PS_RUNNING;        /* XXX - could be PS_STOPPED */
+      p = p->next;
+    }
+  while (p != jobs[job]->pipe);
+
+  /* This means that the job is running. */
+  JOBSTATE (job) = JRUNNING;
+}
+
+/* Start a job.  FOREGROUND if non-zero says to do that.  Otherwise,
+   start the job in the background.  JOB is a zero-based index into
+   JOBS.  Returns -1 if it is unable to start a job, and the return
+   status of the job otherwise. */
+int
+start_job (job, foreground)
+     int job, foreground;
+{
+  register PROCESS *p;
+  int already_running;
+  sigset_t set, oset;
+  char *wd, *s;
+  static TTYSTRUCT save_stty;
+
+  BLOCK_CHILD (set, oset);
+
+  if (DEADJOB (job))
+    {
+      internal_error (_("%s: job has terminated"), this_command_name);
+      UNBLOCK_CHILD (oset);
+      return (-1);
+    }
+
+  already_running = RUNNING (job);
+
+  if (foreground == 0 && already_running)
+    {
+      internal_error (_("%s: job %d already in background"), this_command_name, job + 1);
+      UNBLOCK_CHILD (oset);
+      return (0);              /* XPG6/SUSv3 says this is not an error */
+    }
+
+  wd = current_working_directory ();
+
+  /* You don't know about the state of this job.  Do you? */
+  jobs[job]->flags &= ~J_NOTIFIED;
+
+  if (foreground)
+    {
+      set_current_job (job);
+      jobs[job]->flags |= J_FOREGROUND;
+    }
+
+  /* Tell the outside world what we're doing. */
+  p = jobs[job]->pipe;
+
+  if (foreground == 0)
+    {
+      /* POSIX.2 says `bg' doesn't give any indication about current or
+        previous job. */
+      if (posixly_correct == 0)
+       s = (job == js.j_current) ? "+ ": ((job == js.j_previous) ? "- " : " ");       
+      else
+       s = " ";
+      printf ("[%d]%s", job + 1, s);
+    }
+
+  do
+    {
+      printf ("%s%s",
+              p->command ? p->command : "",
+              p->next != jobs[job]->pipe? " | " : "");
+      p = p->next;
+    }
+  while (p != jobs[job]->pipe);
+
+  if (foreground == 0)
+    printf (" &");
+
+  if (strcmp (wd, jobs[job]->wd) != 0)
+    printf ("  (wd: %s)", polite_directory_format (jobs[job]->wd));
+
+  printf ("\n");
+
+  /* Run the job. */
+  if (already_running == 0)
+    set_job_running (job);
+
+  /* Save the tty settings before we start the job in the foreground. */
+  if (foreground)
+    {
+      get_tty_state ();
+      save_stty = shell_tty_info;
+      /* Give the terminal to this job. */
+      if (IS_JOBCONTROL (job))
+       give_terminal_to (jobs[job]->pgrp, 0);
+    }
+  else
+    jobs[job]->flags &= ~J_FOREGROUND;
+
+  /* If the job is already running, then don't bother jump-starting it. */
+  if (already_running == 0)
+    {
+      jobs[job]->flags |= J_NOTIFIED;
+      killpg (jobs[job]->pgrp, SIGCONT);
+    }
+
+  if (foreground)
+    {
+      pid_t pid;
+      int st;
+
+      pid = find_last_pid (job, 0);
+      UNBLOCK_CHILD (oset);
+      st = wait_for (pid);
+      shell_tty_info = save_stty;
+      set_tty_state ();
+      return (st);
+    }
+  else
+    {
+      reset_current ();
+      UNBLOCK_CHILD (oset);
+      return (0);
+    }
+}
+
+/* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
+   If PID does belong to a job, and the job is stopped, then CONTinue the
+   job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
+   then kill the process group associated with PID. */
+int
+kill_pid (pid, sig, group)
+     pid_t pid;
+     int sig, group;
+{
+  register PROCESS *p;
+  int job, result, negative;
+  sigset_t set, oset;
+
+  if (pid < -1)
+    {
+      pid = -pid;
+      group = negative = 1;
+    }
+  else
+    negative = 0;
+
+  result = EXECUTION_SUCCESS;
+  if (group)
+    {
+      BLOCK_CHILD (set, oset);
+      p = find_pipeline (pid, 0, &job);
+
+      if (job != NO_JOB)
+       {
+         jobs[job]->flags &= ~J_NOTIFIED;
+
+         /* Kill process in backquotes or one started without job control? */
+
+         /* If we're passed a pid < -1, just call killpg and see what happens  */
+         if (negative && jobs[job]->pgrp == shell_pgrp)
+           result = killpg (pid, sig);
+         /* If we're killing using job control notification, for example,
+            without job control active, we have to do things ourselves. */
+         else if (jobs[job]->pgrp == shell_pgrp)
+           {
+             p = jobs[job]->pipe;
+             do
+               {
+                 if (PALIVE (p) == 0)
+                   continue;           /* avoid pid recycling problem */
+                 kill (p->pid, sig);
+                 if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
+                   kill (p->pid, SIGCONT);
+                 p = p->next;
+               }
+             while  (p != jobs[job]->pipe);
+           }
+         else
+           {
+             result = killpg (jobs[job]->pgrp, sig);
+             if (p && STOPPED (job) && (sig == SIGTERM || sig == SIGHUP))
+               killpg (jobs[job]->pgrp, SIGCONT);
+             /* If we're continuing a stopped job via kill rather than bg or
+                fg, emulate the `bg' behavior. */
+             if (p && STOPPED (job) && (sig == SIGCONT))
+               {
+                 set_job_running (job);
+                 jobs[job]->flags &= ~J_FOREGROUND;
+                 jobs[job]->flags |= J_NOTIFIED;
+               }
+           }
+       }
+      else
+       result = killpg (pid, sig);
+
+      UNBLOCK_CHILD (oset);
+    }
+  else
+    result = kill (pid, sig);
+
+  return (result);
+}
+
+/* sigchld_handler () flushes at least one of the children that we are
+   waiting for.  It gets run when we have gotten a SIGCHLD signal. */
+static sighandler
+sigchld_handler (sig)
+     int sig;
+{
+  int n, oerrno;
+
+  oerrno = errno;
+  REINSTALL_SIGCHLD_HANDLER;
+  sigchld++;
+  n = 0;
+  if (queue_sigchld == 0)
+    n = waitchld (-1, 0);
+  errno = oerrno;
+  SIGRETURN (n);
+}
+
+/* waitchld() reaps dead or stopped children.  It's called by wait_for and
+   sigchld_handler, and runs until there aren't any children terminating any
+   more.
+   If BLOCK is 1, this is to be a blocking wait for a single child, although
+   an arriving SIGCHLD could cause the wait to be non-blocking.  It returns
+   the number of children reaped, or -1 if there are no unwaited-for child
+   processes. */
+static int
+waitchld (wpid, block)
+     pid_t wpid;
+     int block;
+{
+  WAIT status;
+  PROCESS *child;
+  pid_t pid;
+  int call_set_current, last_stopped_job, job, children_exited, waitpid_flags;
+  static int wcontinued = WCONTINUED;  /* run-time fix for glibc problem */
+
+  call_set_current = children_exited = 0;
+  last_stopped_job = NO_JOB;
+
+  do
+    {
+      /* We don't want to be notified about jobs stopping if job control
+        is not active.  XXX - was interactive_shell instead of job_control */
+      waitpid_flags = (job_control && subshell_environment == 0)
+                       ? (WUNTRACED|wcontinued)
+                       : 0;
+      if (sigchld || block == 0)
+       waitpid_flags |= WNOHANG;
+      /* Check for terminating signals and exit the shell if we receive one */
+      CHECK_TERMSIG;
+
+      if (block == 1 && queue_sigchld == 0 && (waitpid_flags & WNOHANG) == 0)
+       {
+         internal_warning (_("waitchld: turning on WNOHANG to avoid indefinite block"));
+         waitpid_flags |= WNOHANG;
+       }
+
+      pid = WAITPID (-1, &status, waitpid_flags);
+
+      /* WCONTINUED may be rejected by waitpid as invalid even when defined */
+      if (wcontinued && pid < 0 && errno == EINVAL)
+       {
+         wcontinued = 0;
+         continue;     /* jump back to the test and retry without WCONTINUED */
+       }
+
+      /* The check for WNOHANG is to make sure we decrement sigchld only
+        if it was non-zero before we called waitpid. */
+      if (sigchld > 0 && (waitpid_flags & WNOHANG))
+       sigchld--;
+  
+      /* If waitpid returns -1 with errno == ECHILD, there are no more
+        unwaited-for child processes of this shell. */
+      if (pid < 0 && errno == ECHILD)
+       {
+         if (children_exited == 0)
+           return -1;
+         else
+           break;
+       }
+
+      /* 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 waitpid returns -1/EINTR and the shell saw a SIGINT, then we
+        assume the child has blocked or handled SIGINT.  In that case, we
+        require the child to actually die due to SIGINT to act on the
+        SIGINT we received; otherwise we assume the child handled it and
+        let it go. */
+      if (pid < 0 && errno == EINTR && wait_sigint_received)
+       child_caught_sigint = 1;
+
+      if (pid <= 0)
+       continue;       /* jumps right to the test */
+
+      /* If the child process did die due to SIGINT, forget our assumption
+        that it caught or otherwise handled it. */
+      if (WIFSIGNALED (status) && WTERMSIG (status) == SIGINT)
+        child_caught_sigint = 0;
+
+      /* children_exited is used to run traps on SIGCHLD.  We don't want to
+         run the trap if a process is just being continued. */
+      if (WIFCONTINUED(status) == 0)
+       {
+         children_exited++;
+         js.c_living--;
+       }
+
+      /* Locate our PROCESS for this pid. */
+      child = find_process (pid, 1, &job);     /* want living procs only */
+
+#if defined (COPROCESS_SUPPORT)
+      coproc_pidchk (pid, status);
+#endif
+
+      /* It is not an error to have a child terminate that we did
+        not have a record of.  This child could have been part of
+        a pipeline in backquote substitution.  Even so, I'm not
+        sure child is ever non-zero. */
+      if (child == 0)
+       {
+         if (WIFEXITED (status) || WIFSIGNALED (status))
+           js.c_reaped++;
+         continue;
+       }
+
+      /* Remember status, and whether or not the process is running. */
+      child->status = status;
+      child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
+
+      if (PEXITED (child))
+       {
+         js.c_totreaped++;
+         if (job != NO_JOB)
+           js.c_reaped++;
+       }
+        
+      if (job == NO_JOB)
+       continue;
+
+      call_set_current += set_job_status_and_cleanup (job);
+
+      if (STOPPED (job))
+       last_stopped_job = job;
+      else if (DEADJOB (job) && last_stopped_job == job)
+       last_stopped_job = NO_JOB;
+    }
+  while ((sigchld || block == 0) && pid > (pid_t)0);
+
+  /* If a job was running and became stopped, then set the current
+     job.  Otherwise, don't change a thing. */
+  if (call_set_current)
+    {
+      if (last_stopped_job != NO_JOB)
+       set_current_job (last_stopped_job);
+      else
+       reset_current ();
+    }
+
+  /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
+  if (job_control && signal_is_trapped (SIGCHLD) && children_exited &&
+      trap_list[SIGCHLD] != (char *)IGNORE_SIG)
+    {
+      if (posixly_correct && this_shell_builtin && this_shell_builtin == wait_builtin)
+       {
+         interrupt_immediately = 0;
+         trap_handler (SIGCHLD);       /* set pending_traps[SIGCHLD] */
+         wait_signal_received = SIGCHLD;
+         longjmp (wait_intr_buf, 1);
+       }
+
+      run_sigchld_trap (children_exited);
+    }
+
+  /* We have successfully recorded the useful information about this process
+     that has just changed state.  If we notify asynchronously, and the job
+     that this process belongs to is no longer running, then notify the user
+     of that fact now. */
+  if (asynchronous_notification && interactive)
+    notify_of_job_status ();
+
+  return (children_exited);
+}
+
+/* Set the status of JOB and perform any necessary cleanup if the job is
+   marked as JDEAD.
+
+   Currently, the cleanup activity is restricted to handling any SIGINT
+   received while waiting for a foreground job to finish. */
+static int
+set_job_status_and_cleanup (job)
+     int job;
+{
+  PROCESS *child;
+  int tstatus, job_state, any_stopped, any_tstped, call_set_current;
+  SigHandler *temp_handler;
+
+  child = jobs[job]->pipe;
+  jobs[job]->flags &= ~J_NOTIFIED;
+
+  call_set_current = 0;
+
+  /*
+   * COMPUTE JOB STATUS
+   */
+
+  /* If all children are not running, but any of them is  stopped, then
+     the job is stopped, not dead. */
+  job_state = any_stopped = any_tstped = 0;
+  do
+    {
+      job_state |= PRUNNING (child);
+#if 0
+      if (PEXITED (child) && (WIFSTOPPED (child->status)))
+#else
+      /* Only checking for WIFSTOPPED now, not for PS_DONE */
+      if (PSTOPPED (child))
+#endif
+       {
+         any_stopped = 1;
+         any_tstped |= interactive && job_control &&
+                           (WSTOPSIG (child->status) == SIGTSTP);
+       }
+      child = child->next;
+    }
+  while (child != jobs[job]->pipe);
+
+  /* If job_state != 0, the job is still running, so don't bother with
+     setting the process exit status and job state unless we're
+     transitioning from stopped to running. */
+  if (job_state != 0 && JOBSTATE(job) != JSTOPPED)
+    return 0;
+
+  /*
+   * SET JOB STATUS
+   */
+
+  /* The job is either stopped or dead.  Set the state of the job accordingly. */
+  if (any_stopped)
+    {
+      jobs[job]->state = JSTOPPED;
+      jobs[job]->flags &= ~J_FOREGROUND;
+      call_set_current++;
+      /* Suspending a job with SIGTSTP breaks all active loops. */
+      if (any_tstped && loop_level)
+       breaking = loop_level;
+    }
+  else if (job_state != 0)     /* was stopped, now running */
+    {
+      jobs[job]->state = JRUNNING;
+      call_set_current++;
+    }
+  else
+    {
+      jobs[job]->state = JDEAD;
+      js.j_ndead++;
+
+#if 0
+      if (IS_FOREGROUND (job))
+       setjstatus (job);
+#endif
+
+      /* If this job has a cleanup function associated with it, call it
+        with `cleanarg' as the single argument, then set the function
+        pointer to NULL so it is not inadvertently called twice.  The
+        cleanup function is responsible for deallocating cleanarg. */
+      if (jobs[job]->j_cleanup)
+       {
+         (*jobs[job]->j_cleanup) (jobs[job]->cleanarg);
+         jobs[job]->j_cleanup = (sh_vptrfunc_t *)NULL;
+       }
+    }
+
+  /*
+   * CLEANUP
+   *
+   * Currently, we just do special things if we got a SIGINT while waiting
+   * for a foreground job to complete
+   */
+
+  if (JOBSTATE (job) == JDEAD)
+    {
+      /* If we're running a shell script and we get a SIGINT with a
+        SIGINT trap handler, but the foreground job handles it and
+        does not exit due to SIGINT, run the trap handler but do not
+        otherwise act as if we got the interrupt. */
+      if (wait_sigint_received && interactive_shell == 0 &&
+         child_caught_sigint && IS_FOREGROUND (job) &&
+         signal_is_trapped (SIGINT))
+       {
+         int old_frozen;
+         wait_sigint_received = 0;
+         last_command_exit_value = process_exit_status (child->status);
+
+         old_frozen = jobs_list_frozen;
+         jobs_list_frozen = 1;
+         tstatus = maybe_call_trap_handler (SIGINT);
+         jobs_list_frozen = old_frozen;
+       }
+
+      /* If the foreground job is killed by SIGINT when job control is not
+        active, we need to perform some special handling.
+
+        The check of wait_sigint_received is a way to determine if the
+        SIGINT came from the keyboard (in which case the shell has already
+        seen it, and wait_sigint_received is non-zero, because keyboard
+        signals are sent to process groups) or via kill(2) to the foreground
+        process by another process (or itself).  If the shell did receive the
+        SIGINT, it needs to perform normal SIGINT processing. */
+      else if (wait_sigint_received &&
+             child_caught_sigint == 0 &&
+             IS_FOREGROUND (job) && IS_JOBCONTROL (job) == 0)
+       {
+         int old_frozen;
+
+         wait_sigint_received = 0;
+
+         /* If SIGINT is trapped, set the exit status so that the trap
+            handler can see it. */
+         if (signal_is_trapped (SIGINT))
+           last_command_exit_value = process_exit_status (child->status);
+
+         /* If the signal is trapped, let the trap handler get it no matter
+            what and simply return if the trap handler returns.
+           maybe_call_trap_handler() may cause dead jobs to be removed from
+           the job table because of a call to execute_command.  We work
+           around this by setting JOBS_LIST_FROZEN. */
+         old_frozen = jobs_list_frozen;
+         jobs_list_frozen = 1;
+         tstatus = maybe_call_trap_handler (SIGINT);
+         jobs_list_frozen = old_frozen;
+         if (tstatus == 0 && old_sigint_handler != INVALID_SIGNAL_HANDLER)
+           {
+             /* wait_sigint_handler () has already seen SIGINT and
+                allowed the wait builtin to jump out.  We need to
+                call the original SIGINT handler, if necessary.  If
+                the original handler is SIG_DFL, we need to resend
+                the signal to ourselves. */
+
+             temp_handler = old_sigint_handler;
+
+             /* Bogus.  If we've reset the signal handler as the result
+                of a trap caught on SIGINT, then old_sigint_handler
+                will point to trap_handler, which now knows nothing about
+                SIGINT (if we reset the sighandler to the default).
+                In this case, we have to fix things up.  What a crock. */
+             if (temp_handler == trap_handler && signal_is_trapped (SIGINT) == 0)
+                 temp_handler = trap_to_sighandler (SIGINT);
+               restore_sigint_handler ();
+             if (temp_handler == SIG_DFL)
+               termsig_handler (SIGINT);       /* XXX */
+             else if (temp_handler != SIG_IGN)
+               (*temp_handler) (SIGINT);
+           }
+       }
+    }
+
+  return call_set_current;
+}
+
+/* Build the array of values for the $PIPESTATUS variable from the set of
+   exit statuses of all processes in the job J. */
+static void
+setjstatus (j)
+     int j;
+{
+#if defined (ARRAY_VARS)
+  register int i;
+  register PROCESS *p;
+
+  for (i = 1, p = jobs[j]->pipe; p->next != jobs[j]->pipe; p = p->next, i++)
+    ;
+  i++;
+  if (statsize < i)
+    {
+      pstatuses = (int *)xrealloc (pstatuses, i * sizeof (int));
+      statsize = i;
+    }
+  i = 0;
+  p = jobs[j]->pipe;
+  do
+    {
+      pstatuses[i++] = process_exit_status (p->status);
+      p = p->next;
+    }
+  while (p != jobs[j]->pipe);
+
+  pstatuses[i] = -1;   /* sentinel */
+  set_pipestatus_array (pstatuses, i);
+#endif
+}
+
+void
+run_sigchld_trap (nchild)
+     int nchild;
+{
+  char *trap_command;
+  int i;
+
+  /* Turn off the trap list during the call to parse_and_execute ()
+     to avoid potentially infinite recursive calls.  Preserve the
+     values of last_command_exit_value, last_made_pid, and the_pipeline
+     around the execution of the trap commands. */
+  trap_command = savestring (trap_list[SIGCHLD]);
+
+  begin_unwind_frame ("SIGCHLD trap");
+  unwind_protect_int (last_command_exit_value);
+  unwind_protect_int (last_command_exit_signal);
+  unwind_protect_var (last_made_pid);
+  unwind_protect_int (interrupt_immediately);
+  unwind_protect_int (jobs_list_frozen);
+  unwind_protect_pointer (the_pipeline);
+  unwind_protect_pointer (subst_assign_varlist);
+
+  /* We have to add the commands this way because they will be run
+     in reverse order of adding.  We don't want maybe_set_sigchld_trap ()
+     to reference freed memory. */
+  add_unwind_protect (xfree, trap_command);
+  add_unwind_protect (maybe_set_sigchld_trap, trap_command);
+
+  subst_assign_varlist = (WORD_LIST *)NULL;
+  the_pipeline = (PROCESS *)NULL;
+
+  set_impossible_sigchld_trap ();
+  jobs_list_frozen = 1;
+  for (i = 0; i < nchild; i++)
+    {
+      interrupt_immediately = 1;
+      parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE);
+    }
+
+  run_unwind_frame ("SIGCHLD trap");
+}
+
+/* Function to call when you want to notify people of changes
+   in job status.  This prints out all jobs which are pending
+   notification to stderr, and marks those printed as already
+   notified, thus making them candidates for cleanup. */
+static void
+notify_of_job_status ()
+{
+  register int job, termsig;
+  char *dir;
+  sigset_t set, oset;
+  WAIT s;
+
+  if (jobs == 0 || js.j_jobslots == 0)
+    return;
+
+  if (old_ttou != 0)
+    {
+      sigemptyset (&set);
+      sigaddset (&set, SIGCHLD);
+      sigaddset (&set, SIGTTOU);
+      sigemptyset (&oset);
+      sigprocmask (SIG_BLOCK, &set, &oset);
+    }
+  else
+    queue_sigchld++;
+
+  /* XXX could use js.j_firstj here */
+  for (job = 0, dir = (char *)NULL; job < js.j_jobslots; job++)
+    {
+      if (jobs[job] && IS_NOTIFIED (job) == 0)
+       {
+         s = raw_job_exit_status (job);
+         termsig = WTERMSIG (s);
+
+         /* POSIX.2 says we have to hang onto the statuses of at most the
+            last CHILD_MAX background processes if the shell is running a
+            script.  If the shell is running a script, either from a file
+            or standard input, don't print anything unless the job was
+            killed by a signal. */
+         if (startup_state == 0 && WIFSIGNALED (s) == 0 &&
+               ((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job)))
+           continue;
+         
+#if 0
+         /* If job control is disabled, don't print the status messages.
+            Mark dead jobs as notified so that they get cleaned up.  If
+            startup_state == 2, we were started to run `-c command', so
+            don't print anything. */
+         if ((job_control == 0 && interactive_shell) || startup_state == 2)
+#else
+         /* If job control is disabled, don't print the status messages.
+            Mark dead jobs as notified so that they get cleaned up.  If
+            startup_state == 2 and subshell_environment has the
+            SUBSHELL_COMSUB bit turned on, we were started to run a command
+            substitution, so don't print anything. */
+         if ((job_control == 0 && interactive_shell) ||
+             (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)))
+#endif
+           {
+             /* POSIX.2 compatibility:  if the shell is not interactive,
+                hang onto the job corresponding to the last asynchronous
+                pid until the user has been notified of its status or does
+                a `wait'. */
+             if (DEADJOB (job) && (interactive_shell || (find_last_pid (job, 0) != last_asynchronous_pid)))
+               jobs[job]->flags |= J_NOTIFIED;
+             continue;
+           }
+
+         /* Print info on jobs that are running in the background,
+            and on foreground jobs that were killed by anything
+            except SIGINT (and possibly SIGPIPE). */
+         switch (JOBSTATE (job))
+           {
+           case JDEAD:
+             if (interactive_shell == 0 && termsig && WIFSIGNALED (s) &&
+                 termsig != SIGINT &&
+#if defined (DONT_REPORT_SIGTERM)
+                 termsig != SIGTERM &&
+#endif
+#if defined (DONT_REPORT_SIGPIPE)
+                 termsig != SIGPIPE &&
+#endif
+                 signal_is_trapped (termsig) == 0)
+               {
+                 /* Don't print `0' for a line number. */
+                 fprintf (stderr, _("%s: line %d: "), get_name_for_error (), (line_number == 0) ? 1 : line_number);
+                 pretty_print_job (job, JLIST_NONINTERACTIVE, stderr);
+               }
+             else if (IS_FOREGROUND (job))
+               {
+#if !defined (DONT_REPORT_SIGPIPE)
+                 if (termsig && WIFSIGNALED (s) && termsig != SIGINT)
+#else
+                 if (termsig && WIFSIGNALED (s) && termsig != SIGINT && termsig != SIGPIPE)
+#endif
+                   {
+                     fprintf (stderr, "%s", j_strsignal (termsig));
+
+                     if (WIFCORED (s))
+                       fprintf (stderr, _(" (core dumped)"));
+
+                     fprintf (stderr, "\n");
+                   }
+               }
+             else if (job_control)     /* XXX job control test added */
+               {
+                 if (dir == 0)
+                   dir = current_working_directory ();
+                 pretty_print_job (job, JLIST_STANDARD, stderr);
+                 if (dir && strcmp (dir, jobs[job]->wd) != 0)
+                   fprintf (stderr,
+                            _("(wd now: %s)\n"), polite_directory_format (dir));
+               }
+
+             jobs[job]->flags |= J_NOTIFIED;
+             break;
+
+           case JSTOPPED:
+             fprintf (stderr, "\n");
+             if (dir == 0)
+               dir = current_working_directory ();
+             pretty_print_job (job, JLIST_STANDARD, stderr);
+             if (dir && (strcmp (dir, jobs[job]->wd) != 0))
+               fprintf (stderr,
+                        _("(wd now: %s)\n"), polite_directory_format (dir));
+             jobs[job]->flags |= J_NOTIFIED;
+             break;
+
+           case JRUNNING:
+           case JMIXED:
+             break;
+
+           default:
+             programming_error ("notify_of_job_status");
+           }
+       }
+    }
+  if (old_ttou != 0)
+    sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+  else
+    queue_sigchld--;
+}
+
+/* Initialize the job control mechanism, and set up the tty stuff. */
+int
+initialize_job_control (force)
+     int force;
+{
+  pid_t t;
+  int t_errno;
+
+  t_errno = -1;
+  shell_pgrp = getpgid (0);
+
+  if (shell_pgrp == -1)
+    {
+      sys_error (_("initialize_job_control: getpgrp failed"));
+      exit (1);
+    }
+
+  /* We can only have job control if we are interactive. */
+  if (interactive == 0)
+    {
+      job_control = 0;
+      original_pgrp = NO_PID;
+      shell_tty = fileno (stderr);
+    }
+  else
+    {
+      shell_tty = -1;
+
+      /* If forced_interactive is set, we skip the normal check that stderr
+        is attached to a tty, so we need to check here.  If it's not, we
+        need to see whether we have a controlling tty by opening /dev/tty,
+        since trying to use job control tty pgrp manipulations on a non-tty
+        is going to fail. */
+      if (forced_interactive && isatty (fileno (stderr)) == 0)
+       shell_tty = open ("/dev/tty", O_RDWR|O_NONBLOCK);
+
+      /* Get our controlling terminal.  If job_control is set, or
+        interactive is set, then this is an interactive shell no
+        matter where fd 2 is directed. */
+      if (shell_tty == -1)
+       shell_tty = dup (fileno (stderr));      /* fd 2 */
+
+      shell_tty = move_to_high_fd (shell_tty, 1, -1);
+
+      /* Compensate for a bug in systems that compiled the BSD
+        rlogind with DEBUG defined, like NeXT and Alliant. */
+      if (shell_pgrp == 0)
+       {
+         shell_pgrp = getpid ();
+         setpgid (0, shell_pgrp);
+         tcsetpgrp (shell_tty, shell_pgrp);
+       }
+
+      while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1)
+       {
+         if (shell_pgrp != terminal_pgrp)
+           {
+             SigHandler *ottin;
+
+             ottin = set_signal_handler(SIGTTIN, SIG_DFL);
+             kill (0, SIGTTIN);
+             set_signal_handler (SIGTTIN, ottin);
+             continue;
+           }
+         break;
+       }
+
+      if (terminal_pgrp == -1)
+       t_errno = errno;
+
+      /* Make sure that we are using the new line discipline. */
+      if (set_new_line_discipline (shell_tty) < 0)
+       {
+         sys_error (_("initialize_job_control: line discipline"));
+         job_control = 0;
+       }
+      else
+       {
+         original_pgrp = shell_pgrp;
+         shell_pgrp = getpid ();
+
+         if ((original_pgrp != shell_pgrp) && (setpgid (0, shell_pgrp) < 0))
+           {
+             sys_error (_("initialize_job_control: setpgid"));
+             shell_pgrp = original_pgrp;
+           }
+
+         job_control = 1;
+
+         /* If (and only if) we just set our process group to our pid,
+            thereby becoming a process group leader, and the terminal
+            is not in the same process group as our (new) process group,
+            then set the terminal's process group to our (new) process
+            group.  If that fails, set our process group back to what it
+            was originally (so we can still read from the terminal) and
+            turn off job control.  */
+         if (shell_pgrp != original_pgrp && shell_pgrp != terminal_pgrp)
+           {
+             if (give_terminal_to (shell_pgrp, 0) < 0)
+               {
+                 t_errno = errno;
+                 setpgid (0, original_pgrp);
+                 shell_pgrp = original_pgrp;
+                 job_control = 0;
+               }
+           }
+
+         if (job_control && ((t = tcgetpgrp (shell_tty)) == -1 || t != shell_pgrp))
+           {
+             if (t_errno != -1)
+               errno = t_errno;
+             sys_error (_("cannot set terminal process group (%d)"), t);
+             job_control = 0;
+           }
+       }
+      if (job_control == 0)
+       internal_error (_("no job control in this shell"));
+    }
+
+  if (shell_tty != fileno (stderr))
+    SET_CLOSE_ON_EXEC (shell_tty);
+
+  set_signal_handler (SIGCHLD, sigchld_handler);
+
+  change_flag ('m', job_control ? '-' : '+');
+
+  if (interactive)
+    get_tty_state ();
+
+  if (js.c_childmax < 0)
+    js.c_childmax = getmaxchild ();
+  if (js.c_childmax < 0)
+    js.c_childmax = DEFAULT_CHILD_MAX;
+
+  return job_control;
+}
+
+#ifdef DEBUG
+void
+debug_print_pgrps ()
+{
+  itrace("original_pgrp = %ld shell_pgrp = %ld terminal_pgrp = %ld",
+        (long)original_pgrp, (long)shell_pgrp, (long)terminal_pgrp);
+  itrace("tcgetpgrp(%d) -> %ld, getpgid(0) -> %ld",
+        shell_tty, (long)tcgetpgrp (shell_tty), (long)getpgid(0));
+}
+#endif
+
+/* Set the line discipline to the best this system has to offer.
+   Return -1 if this is not possible. */
+static int
+set_new_line_discipline (tty)
+     int tty;
+{
+#if defined (NEW_TTY_DRIVER)
+  int ldisc;
+
+  if (ioctl (tty, TIOCGETD, &ldisc) < 0)
+    return (-1);
+
+  if (ldisc != NTTYDISC)
+    {
+      ldisc = NTTYDISC;
+
+      if (ioctl (tty, TIOCSETD, &ldisc) < 0)
+       return (-1);
+    }
+  return (0);
+#endif /* NEW_TTY_DRIVER */
+
+#if defined (TERMIO_TTY_DRIVER)
+#  if defined (TERMIO_LDISC) && (NTTYDISC)
+  if (ioctl (tty, TCGETA, &shell_tty_info) < 0)
+    return (-1);
+
+  if (shell_tty_info.c_line != NTTYDISC)
+    {
+      shell_tty_info.c_line = NTTYDISC;
+      if (ioctl (tty, TCSETAW, &shell_tty_info) < 0)
+       return (-1);
+    }
+#  endif /* TERMIO_LDISC && NTTYDISC */
+  return (0);
+#endif /* TERMIO_TTY_DRIVER */
+
+#if defined (TERMIOS_TTY_DRIVER)
+#  if defined (TERMIOS_LDISC) && defined (NTTYDISC)
+  if (tcgetattr (tty, &shell_tty_info) < 0)
+    return (-1);
+
+  if (shell_tty_info.c_line != NTTYDISC)
+    {
+      shell_tty_info.c_line = NTTYDISC;
+      if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
+       return (-1);
+    }
+#  endif /* TERMIOS_LDISC && NTTYDISC */
+  return (0);
+#endif /* TERMIOS_TTY_DRIVER */
+
+#if !defined (NEW_TTY_DRIVER) && !defined (TERMIO_TTY_DRIVER) && !defined (TERMIOS_TTY_DRIVER)
+  return (-1);
+#endif
+}
+
+/* Setup this shell to handle C-C, etc. */
+void
+initialize_job_signals ()
+{
+  if (interactive)
+    {
+      set_signal_handler (SIGINT, sigint_sighandler);
+      set_signal_handler (SIGTSTP, SIG_IGN);
+      set_signal_handler (SIGTTOU, SIG_IGN);
+      set_signal_handler (SIGTTIN, SIG_IGN);
+    }
+  else if (job_control)
+    {
+      old_tstp = set_signal_handler (SIGTSTP, sigstop_sighandler);
+      old_ttin = set_signal_handler (SIGTTIN, sigstop_sighandler);
+      old_ttou = set_signal_handler (SIGTTOU, sigstop_sighandler);
+    }
+  /* Leave these things alone for non-interactive shells without job
+     control. */
+}
+
+/* Here we handle CONT signals. */
+static sighandler
+sigcont_sighandler (sig)
+     int sig;
+{
+  initialize_job_signals ();
+  set_signal_handler (SIGCONT, old_cont);
+  kill (getpid (), SIGCONT);
+
+  SIGRETURN (0);
+}
+
+/* Here we handle stop signals while we are running not as a login shell. */
+static sighandler
+sigstop_sighandler (sig)
+     int sig;
+{
+  set_signal_handler (SIGTSTP, old_tstp);
+  set_signal_handler (SIGTTOU, old_ttou);
+  set_signal_handler (SIGTTIN, old_ttin);
+
+  old_cont = set_signal_handler (SIGCONT, sigcont_sighandler);
+
+  give_terminal_to (shell_pgrp, 0);
+
+  kill (getpid (), sig);
+
+  SIGRETURN (0);
+}
+
+/* Give the terminal to PGRP.  */
+int
+give_terminal_to (pgrp, force)
+     pid_t pgrp;
+     int force;
+{
+  sigset_t set, oset;
+  int r, e;
+
+  r = 0;
+  if (job_control || force)
+    {
+      sigemptyset (&set);
+      sigaddset (&set, SIGTTOU);
+      sigaddset (&set, SIGTTIN);
+      sigaddset (&set, SIGTSTP);
+      sigaddset (&set, SIGCHLD);
+      sigemptyset (&oset);
+      sigprocmask (SIG_BLOCK, &set, &oset);
+
+      if (tcsetpgrp (shell_tty, pgrp) < 0)
+       {
+         /* Maybe we should print an error message? */
+#if 0
+         sys_error ("tcsetpgrp(%d) failed: pid %ld to pgrp %ld",
+           shell_tty, (long)getpid(), (long)pgrp);
+#endif
+         r = -1;
+         e = errno;
+       }
+      else
+       terminal_pgrp = pgrp;
+      sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+    }
+
+  if (r == -1)
+    errno = e;
+
+  return r;
+}
+
+/* Give terminal to NPGRP iff it's currently owned by OPGRP.  FLAGS are the
+   flags to pass to give_terminal_to(). */
+static int
+maybe_give_terminal_to (opgrp, npgrp, flags)
+     pid_t opgrp, npgrp;
+     int flags;
+{
+  int tpgrp;
+
+  tpgrp = tcgetpgrp (shell_tty);
+  if (tpgrp < 0 && errno == ENOTTY)
+    return -1;
+  if (tpgrp == npgrp)
+    {
+      terminal_pgrp = npgrp;
+      return 0;
+    }
+  else if (tpgrp != opgrp)
+    {
+#if defined (DEBUG)
+      internal_warning ("maybe_give_terminal_to: terminal pgrp == %d shell pgrp = %d new pgrp = %d", tpgrp, opgrp, npgrp);
+#endif
+      return -1;
+    }
+  else
+    return (give_terminal_to (npgrp, flags));     
+}
+
+/* Clear out any jobs in the job array.  This is intended to be used by
+   children of the shell, who should not have any job structures as baggage
+   when they start executing (forking subshells for parenthesized execution
+   and functions with pipes are the two that spring to mind).  If RUNNING_ONLY
+   is nonzero, only running jobs are removed from the table. */
+void
+delete_all_jobs (running_only)
+     int running_only;
+{
+  register int i;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  /* XXX - need to set j_lastj, j_firstj appropriately if running_only != 0. */
+  if (js.j_jobslots)
+    {
+      js.j_current = js.j_previous = NO_JOB;
+
+      /* XXX could use js.j_firstj here */
+      for (i = 0; i < js.j_jobslots; i++)
+       {
+#if defined (DEBUG)
+         if (i < js.j_firstj && jobs[i])
+           itrace("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+         if (i > js.j_lastj && jobs[i])
+           itrace("delete_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+         if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
+           delete_job (i, DEL_WARNSTOPPED);
+       }
+      if (running_only == 0)
+       {
+         free ((char *)jobs);
+         js.j_jobslots = 0;
+         js.j_firstj = js.j_lastj = js.j_njobs = 0;
+       }
+    }
+
+  if (running_only == 0)
+    bgp_clear ();
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Mark all jobs in the job array so that they don't get a SIGHUP when the
+   shell gets one.  If RUNNING_ONLY is nonzero, mark only running jobs. */
+void
+nohup_all_jobs (running_only)
+     int running_only;
+{
+  register int i;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+
+  if (js.j_jobslots)
+    {
+      /* XXX could use js.j_firstj here */
+      for (i = 0; i < js.j_jobslots; i++)
+       if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
+         nohup_job (i);
+    }
+
+  UNBLOCK_CHILD (oset);
+}
+
+int
+count_all_jobs ()
+{
+  int i, n;
+  sigset_t set, oset;
+
+  /* This really counts all non-dead jobs. */
+  BLOCK_CHILD (set, oset);
+  /* XXX could use js.j_firstj here */
+  for (i = n = 0; i < js.j_jobslots; i++)
+    {
+#if defined (DEBUG)
+      if (i < js.j_firstj && jobs[i])
+       itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+      if (i > js.j_lastj && jobs[i])
+       itrace("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+      if (jobs[i] && DEADJOB(i) == 0)
+       n++;
+    }
+  UNBLOCK_CHILD (oset);
+  return n;
+}
+
+static void
+mark_all_jobs_as_dead ()
+{
+  register int i;
+  sigset_t set, oset;
+
+  if (js.j_jobslots == 0)
+    return;
+
+  BLOCK_CHILD (set, oset);
+
+  /* XXX could use js.j_firstj here */
+  for (i = 0; i < js.j_jobslots; i++)
+    if (jobs[i])
+      {
+       jobs[i]->state = JDEAD;
+       js.j_ndead++;
+      }
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Mark all dead jobs as notified, so delete_job () cleans them out
+   of the job table properly.  POSIX.2 says we need to save the
+   status of the last CHILD_MAX jobs, so we count the number of dead
+   jobs and mark only enough as notified to save CHILD_MAX statuses. */
+static void
+mark_dead_jobs_as_notified (force)
+     int force;
+{
+  register int i, ndead, ndeadproc;
+  sigset_t set, oset;
+
+  if (js.j_jobslots == 0)
+    return;
+
+  BLOCK_CHILD (set, oset);
+
+  /* If FORCE is non-zero, we don't have to keep CHILD_MAX statuses
+     around; just run through the array. */
+  if (force)
+    {
+    /* XXX could use js.j_firstj here */
+      for (i = 0; i < js.j_jobslots; i++)
+       {
+         if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
+           jobs[i]->flags |= J_NOTIFIED;
+       }
+      UNBLOCK_CHILD (oset);
+      return;
+    }
+
+  /* Mark enough dead jobs as notified to keep CHILD_MAX processes left in the
+     array with the corresponding not marked as notified.  This is a better
+     way to avoid pid aliasing and reuse problems than keeping the POSIX-
+     mandated CHILD_MAX jobs around.  delete_job() takes care of keeping the
+     bgpids list regulated. */
+          
+  /* Count the number of dead jobs */
+  /* XXX could use js.j_firstj here */
+  for (i = ndead = ndeadproc = 0; i < js.j_jobslots; i++)
+    {
+#if defined (DEBUG)
+      if (i < js.j_firstj && jobs[i])
+       itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+      if (i > js.j_lastj && jobs[i])
+       itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+      if (jobs[i] && DEADJOB (i))
+       {
+         ndead++;
+         ndeadproc += processes_in_job (i);
+       }
+    }
+
+#ifdef DEBUG
+  if (ndeadproc != js.c_reaped)
+    itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
+  if (ndead != js.j_ndead)
+    itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
+#endif
+
+  if (js.c_childmax < 0)
+    js.c_childmax = getmaxchild ();
+  if (js.c_childmax < 0)
+    js.c_childmax = DEFAULT_CHILD_MAX;
+
+  /* Don't do anything if the number of dead processes is less than CHILD_MAX
+     and we're not forcing a cleanup. */
+  if (ndeadproc <= js.c_childmax)
+    {
+      UNBLOCK_CHILD (oset);
+      return;
+    }
+
+#if 0
+itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", js.c_childmax, ndead, ndeadproc);
+#endif
+
+  /* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
+     the list.  This isn't exactly right yet; changes need to be made
+     to stop_pipeline so we don't mark the newer jobs after we've
+     created CHILD_MAX slots in the jobs array.  This needs to be
+     integrated with a way to keep the jobs array from growing without
+     bound.  Maybe we wrap back around to 0 after we reach some max
+     limit, and there are sufficient job slots free (keep track of total
+     size of jobs array (js.j_jobslots) and running count of number of jobs
+     in jobs array.  Then keep a job index corresponding to the `oldest job'
+     and start this loop there, wrapping around as necessary.  In effect,
+     we turn the list into a circular buffer. */
+  /* XXX could use js.j_firstj here */
+  for (i = 0; i < js.j_jobslots; i++)
+    {
+      if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
+       {
+#if defined (DEBUG)
+         if (i < js.j_firstj && jobs[i])
+           itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
+         if (i > js.j_lastj && jobs[i])
+           itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
+#endif
+         /* If marking this job as notified would drop us down below
+            child_max, don't mark it so we can keep at least child_max
+            statuses.  XXX -- need to check what Posix actually says
+            about keeping statuses. */
+         if ((ndeadproc -= processes_in_job (i)) <= js.c_childmax)
+           break;
+         jobs[i]->flags |= J_NOTIFIED;
+       }
+    }
+
+  UNBLOCK_CHILD (oset);
+}
+
+/* Here to allow other parts of the shell (like the trap stuff) to
+   freeze and unfreeze the jobs list. */
+void
+freeze_jobs_list ()
+{
+  jobs_list_frozen = 1;
+}
+
+void
+unfreeze_jobs_list ()
+{
+  jobs_list_frozen = 0;
+}
+
+/* Allow or disallow job control to take place.  Returns the old value
+   of job_control. */
+int
+set_job_control (arg)
+     int arg;
+{
+  int old;
+
+  old = job_control;
+  job_control = arg;
+
+  /* If we're turning on job control, reset pipeline_pgrp so make_child will
+     put new child processes into the right pgrp */
+  if (job_control != old && job_control)
+    pipeline_pgrp = 0;
+
+  return (old);
+}
+
+/* Turn off all traces of job control.  This is run by children of the shell
+   which are going to do shellsy things, like wait (), etc. */
+void
+without_job_control ()
+{
+  stop_making_children ();
+  start_pipeline ();
+#if defined (PGRP_PIPE)
+  sh_closepipe (pgrp_pipe);
+#endif
+  delete_all_jobs (0);
+  set_job_control (0);
+}
+
+/* If this shell is interactive, terminate all stopped jobs and
+   restore the original terminal process group.  This is done
+   before the `exec' builtin calls shell_execve. */
+void
+end_job_control ()
+{
+  if (interactive_shell)               /* XXX - should it be interactive? */
+    {
+      terminate_stopped_jobs ();
+
+      if (original_pgrp >= 0)
+       give_terminal_to (original_pgrp, 1);
+    }
+
+  if (original_pgrp >= 0)
+    setpgid (0, original_pgrp);
+}
+
+/* Restart job control by closing shell tty and reinitializing.  This is
+   called after an exec fails in an interactive shell and we do not exit. */
+void
+restart_job_control ()
+{
+  if (shell_tty != -1)
+    close (shell_tty);
+  initialize_job_control (0);
+}
+
+/* Set the handler to run when the shell receives a SIGCHLD signal. */
+void
+set_sigchld_handler ()
+{
+  set_signal_handler (SIGCHLD, sigchld_handler);
+}
+
+#if defined (PGRP_PIPE)
+/* Read from the read end of a pipe.  This is how the process group leader
+   blocks until all of the processes in a pipeline have been made. */
+static void
+pipe_read (pp)
+     int *pp;
+{
+  char ch;
+
+  if (pp[1] >= 0)
+    {
+      close (pp[1]);
+      pp[1] = -1;
+    }
+
+  if (pp[0] >= 0)
+    {
+      while (read (pp[0], &ch, 1) == -1 && errno == EINTR)
+       ;
+    }
+}
+
+/* Functional interface closes our local-to-job-control pipes. */
+void
+close_pgrp_pipe ()
+{
+  sh_closepipe (pgrp_pipe);
+}
+
+void
+save_pgrp_pipe (p, clear)
+     int *p;
+     int clear;
+{
+  p[0] = pgrp_pipe[0];
+  p[1] = pgrp_pipe[1];
+  if (clear)
+    pgrp_pipe[0] = pgrp_pipe[1] = -1;
+}
+
+void
+restore_pgrp_pipe (p)
+     int *p;
+{
+  pgrp_pipe[0] = p[0];
+  pgrp_pipe[1] = p[1];
+}
+
+#endif /* PGRP_PIPE */
index d97cd99b61fbc36e310d2ddf7ed7779654958ec8..524825527c231a21b8f652250f612ce922888318 100644 (file)
@@ -291,7 +291,7 @@ getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
 getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
-getenv.o: ${BUILD_DIR}/version.h
+#getenv.o: ${BUILD_DIR}/version.h
 
 inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 inet_aton.o: ${BASHINCDIR}/stdc.h
@@ -303,7 +303,8 @@ itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir
 itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#itos.o: ${BUILD_DIR}/version.h
 
 makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
 makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@@ -312,7 +313,8 @@ makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
 makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#makepath.o: ${BUILD_DIR}/version.h
 
 netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
 netconn.o: ${topdir}/bashtypes.h
@@ -324,8 +326,9 @@ netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
 netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
 netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+#netopen.o: ${BUILD_DIR}/version.h
 
 oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
 oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@@ -334,9 +337,10 @@ oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdi
 oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
 oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
 oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+#oslib.o: ${BUILD_DIR}/version.h
 
 pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
 pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@@ -345,9 +349,10 @@ pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
 pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
 pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
 pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+#pathcanon.o: ${BUILD_DIR}/version.h
 
 pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
 pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@@ -356,9 +361,10 @@ pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
 pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
 pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
 pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+#pathphys.o: ${BUILD_DIR}/version.h
 
 rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
 rename.o: ${BASHINCDIR}/posixstat.h
@@ -377,7 +383,8 @@ eaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
 eaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 eaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 eaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#eaccess.o: ${BUILD_DIR}/version.h
 
 shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
 shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
@@ -403,7 +410,8 @@ strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
 strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#strerror.o: ${BUILD_DIR}/version.h
 
 strcasestr.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
 strcasestr.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
@@ -415,7 +423,8 @@ stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${
 stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#stringlist.o: ${BUILD_DIR}/version.h
 
 stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
 stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@@ -424,7 +433,8 @@ stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
 stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#stringvec.o: ${BUILD_DIR}/version.h
 
 strnlen.o: ${BASHINCDIR}/stdc.h
 
@@ -461,7 +471,8 @@ strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
 strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
 strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
 strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+#strtrans.o: ${BUILD_DIR}/version.h
 
 times.o: ${BASHINCDIR}/systimes.h
 times.o: ${BASHINCDIR}/posixtime.h
diff --git a/lib/sh/Makefile.in~ b/lib/sh/Makefile.in~
new file mode 100644 (file)
index 0000000..d97cd99
--- /dev/null
@@ -0,0 +1,554 @@
+#
+# Makefile for the Bash library
+#
+#
+# Copyright (C) 1998-2010 Free Software Foundation, Inc.
+
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+PACKAGE = @PACKAGE_NAME@
+VERSION = @PACKAGE_VERSION@
+
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+srcdir = @srcdir@
+VPATH = .:@srcdir@
+topdir = @top_srcdir@
+BUILD_DIR = @BUILD_DIR@
+
+LIBBUILD = ${BUILD_DIR}/lib
+
+BASHINCDIR = ${topdir}/include
+
+INTL_LIBSRC = ${topdir}/lib/intl
+INTL_BUILDDIR = ${LIBBUILD}/intl
+INTL_INC = @INTL_INC@
+LIBINTL_H = @LIBINTL_H@
+
+datarootdir = @datarootdir@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+CC = @CC@
+RANLIB = @RANLIB@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RM = rm -f
+CP = cp
+MV = mv
+
+SHELL = @MAKE_SHELL@
+
+CFLAGS = @CFLAGS@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
+
+PROFILE_FLAGS = @PROFILE_FLAGS@
+
+DEFS = @DEFS@
+LOCAL_DEFS = @LOCAL_DEFS@
+
+INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(BASHINCDIR) -I$(srcdir) $(INTL_INC)
+
+CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \
+         $(CFLAGS) $(CPPFLAGS) 
+
+GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
+                -Wcast-align -Wstrict-prototypes -Wconversion \
+                -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
+
+.c.o:
+       $(CC) -c $(CCFLAGS) $<
+
+# The name of the library target.
+LIBRARY_NAME = libsh.a
+
+# The C code source files for this library.
+CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
+          strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
+          vprint.c itos.c rename.c zread.c zwrite.c shtty.c \
+          inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
+          pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
+          shquote.c strtrans.c strcasestr.c snprintf.c mailstat.c \
+          fmtulong.c fmtullong.c fmtumax.c shmatch.c strnlen.c \
+          strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
+          mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
+          wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
+          casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \
+          strchrnul.c unicode.c wcswidth.c shmbchar.c
+
+# The header files for this library.
+HSOURCES = 
+
+# The object files contained in $(LIBRARY_NAME)
+LIBOBJS = @LIBOBJS@
+OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
+         itos.o zread.o zwrite.o shtty.o shmatch.o eaccess.o \
+         netconn.o netopen.o timeval.o makepath.o pathcanon.o \
+         pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
+         strtrans.o snprintf.o mailstat.o fmtulong.o \
+         fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
+         fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
+         input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o ${LIBOBJS}
+
+SUPPORT = Makefile
+
+all: $(LIBRARY_NAME)
+
+$(LIBRARY_NAME): $(OBJECTS)
+       $(RM) $@
+       $(AR) $(ARFLAGS) $@ $(OBJECTS)
+       -test -n "$(RANLIB)" && $(RANLIB) $@
+
+force:
+
+# The rule for 'includes' is written funny so that the if statement
+# always returns TRUE unless there really was an error installing the
+# include files.
+install:
+
+clean:
+       $(RM) $(OBJECTS) $(LIBRARY_NAME)
+
+realclean distclean maintainer-clean: clean
+       $(RM) Makefile
+
+mostlyclean: clean
+
+# Dependencies
+
+${BUILD_DIR}/version.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
+       -( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} version.h )
+
+${BUILD_DIR}/pathnames.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
+       -( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} pathnames.h )
+
+# rules for losing makes, like SunOS
+casemod.o: casemod.c
+clktck.o: clktck.c
+clock.o: clock.c
+eaccess.o: eaccess.c
+dprintf.o: dprintf.c
+fmtullong.o: fmtullong.c
+fmtulong.o: fmtulong.c
+fmtumax.o: fmtumax.c
+fnxform.o: fnxform.c
+fpurge.o: fpurge.c
+getcwd.o: getcwd.c
+getenv.o: getenv.c
+inet_aton.o: inet_aton.c
+input_avail.o: input_avail.c
+itos.o: itos.c
+mailstat.o: mailstat.c
+makepath.o: makepath.c
+mbscasecmp.o: mbscasecmp.c
+mbscmp.o: mbscmp.c
+memset.o: memset.c
+mktime.o: mktime.c
+netconn.o: netconn.c
+netopen.o: netopen.c
+oslib.o: oslib.c
+pathcanon.o: pathcanon.c
+pathphys.o: pathphys.c
+rename.o: rename.c
+setlinebuf.o: setlinebuf.c
+shmbchar.o: shmbchar.c
+shquote.o: shquote.c
+shtty.o: shtty.c
+snprintf.o: snprintf.c
+spell.o: spell.c
+strcasecmp.o: strcasecmp.c
+strerror.o: strerror.c
+strftime.o: strftime.c
+strcasestr.o: strcasestr.c
+stringlist.o: stringlist.c
+stringvec.o: stringvec.c
+strnlen.o: strnlen.c
+strpbrk.o: strpbrk.c
+strtod.o: strtod.c
+strtoimax.o: strtoimax.c
+strtol.o: strtol.c
+strtoll.o: strtoll.c
+strtoul.o: strtoul.c
+strtoull.o: strtoull.c
+strtoumax.o: strtoumax.c
+strtrans.o: strtrans.c
+times.o: times.c
+timeval.o: timeval.c
+tmpfile.o: tmpfile.c
+uconvert.o: uconvert.c
+ufuncs.o: ufuncs.c
+vprint.o: vprint.c
+wcsdup.o: wcsdup.c
+wcswidth.o: wcswidth.c
+mbschr.o: mbschr.c
+zcatfd.o: zcatfd.c
+zmapfd.o: zmapfd.c
+zgetline.o: zgetline.c
+zread.o: zread.c
+zwrite.o: zwrite.c
+
+# dependencies for c files that include other c files
+fmtullong.o: fmtulong.c
+fmtumax.o: fmtulong.c
+strtoll.o: strtol.c
+strtoul.o: strtol.c
+strtoull.o: strtol.c
+
+# all files in the library depend on config.h
+casemod.o: ${BUILD_DIR}/config.h
+clktck.o: ${BUILD_DIR}/config.h
+clock.o: ${BUILD_DIR}/config.h
+eaccess.o: ${BUILD_DIR}/config.h
+dprintf.o: ${BUILD_DIR}/config.h
+fmtullong.o: ${BUILD_DIR}/config.h
+fmtulong.o: ${BUILD_DIR}/config.h
+fmtumax.o: ${BUILD_DIR}/config.h
+fnxform.o: ${BUILD_DIR}/config.h
+fpurge.o: ${BUILD_DIR}/config.h
+getcwd.o: ${BUILD_DIR}/config.h
+getenv.o: ${BUILD_DIR}/config.h
+inet_aton.o: ${BUILD_DIR}/config.h
+input_avail.o: ${BUILD_DIR}/config.h
+itos.o: ${BUILD_DIR}/config.h
+mailstat.o: ${BUILD_DIR}/config.h
+makepath.o: ${BUILD_DIR}/config.h
+mbscasecmp.o: ${BUILD_DIR}/config.h
+mbscmp.o: ${BUILD_DIR}/config.h
+memset.o: ${BUILD_DIR}/config.h
+mktime.o: ${BUILD_DIR}/config.h
+netconn.o: ${BUILD_DIR}/config.h
+netopen.o: ${BUILD_DIR}/config.h
+oslib.o: ${BUILD_DIR}/config.h
+pathcanon.o: ${BUILD_DIR}/config.h
+pathphys.o: ${BUILD_DIR}/config.h
+rename.o: ${BUILD_DIR}/config.h
+setlinebuf.o: ${BUILD_DIR}/config.h
+shmbchare.o: ${BUILD_DIR}/config.h
+shquote.o: ${BUILD_DIR}/config.h
+shtty.o: ${BUILD_DIR}/config.h
+snprintf.o: ${BUILD_DIR}/config.h
+spell.o: ${BUILD_DIR}/config.h
+strcasecmp.o: ${BUILD_DIR}/config.h
+strerror.o: ${BUILD_DIR}/config.h
+strftime.o: ${BUILD_DIR}/config.h
+strcasestr.o: ${BUILD_DIR}/config.h
+stringlist.o: ${BUILD_DIR}/config.h
+stringvec.o: ${BUILD_DIR}/config.h
+strnlen.o: ${BUILD_DIR}/config.h
+strpbrk.o: ${BUILD_DIR}/config.h
+strtod.o: ${BUILD_DIR}/config.h
+strtoimax.o: ${BUILD_DIR}/config.h
+strtol.o: ${BUILD_DIR}/config.h
+strtoll.o: ${BUILD_DIR}/config.h
+strtoul.o: ${BUILD_DIR}/config.h
+strtoull.o: ${BUILD_DIR}/config.h
+strtoumax.o: ${BUILD_DIR}/config.h
+strtrans.o: ${BUILD_DIR}/config.h
+times.o: ${BUILD_DIR}/config.h
+timeval.o: ${BUILD_DIR}/config.h
+tmpfile.o: ${BUILD_DIR}/config.h
+uconvert.o: ${BUILD_DIR}/config.h
+ufuncs.o: ${BUILD_DIR}/config.h
+vprint.o: ${BUILD_DIR}/config.h
+wcsdup.o: ${BUILD_DIR}/config.h
+wcswidth.o: ${BUILD_DIR}/config.h
+mbschr.o: ${BUILD_DIR}/config.h
+zcatfd.o: ${BUILD_DIR}/config.h
+zgetline.o: ${BUILD_DIR}/config.h
+zmapfd.o: ${BUILD_DIR}/config.h
+zread.o: ${BUILD_DIR}/config.h
+zwrite.o: ${BUILD_DIR}/config.h
+
+clktck.o: ${topdir}/bashtypes.h
+
+getcwd.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
+getcwd.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
+getcwd.o: ${BASHINCDIR}/memalloc.h ${BASHINCDIR}/ansi_stdlib.h
+
+getenv.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+getenv.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+getenv.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
+getenv.o: ${BUILD_DIR}/version.h
+
+inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+inet_aton.o: ${BASHINCDIR}/stdc.h
+
+itos.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+itos.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+itos.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+
+makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+makepath.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+
+netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+netconn.o: ${topdir}/bashtypes.h
+
+netopen.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
+netopen.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+netopen.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+
+oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
+oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+oslib.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+
+pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
+pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+pathcanon.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+
+pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
+pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+pathphys.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+
+rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
+rename.o: ${BASHINCDIR}/posixstat.h
+
+setlinebuf.o: ${topdir}/xmalloc.h ${topdir}/bashansi.h
+setlinebuf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/stdc.h
+
+eaccess.o: ${topdir}/bashtypes.h
+eaccess.o: ${BASHINCDIR}/posixstat.h
+eaccess.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+eaccess.o: ${BASHINCDIR}/filecntl.h
+eaccess.o: ${BASHINCDIR}/stdc.h
+eaccess.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+eaccess.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+eaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+eaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+eaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+eaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+
+shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
+shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
+
+shtty.o: ${BASHINCDIR}/shtty.h
+shtty.o: ${BASHINCDIR}/stdc.h
+
+snprintf.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h ${topdir}/xmalloc.h
+snprintf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+snprintf.o: ${BASHINCDIR}/typemax.h
+
+spell.o: ${topdir}/bashtypes.h
+spell.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
+spell.o: ${BASHINCDIR}/ansi_stdlib.h
+
+strcasecmp.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
+strcasecmp.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+
+strerror.o: ${topdir}/bashtypes.h
+strerror.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+strerror.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+
+strcasestr.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
+strcasestr.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+
+stringlist.o: ${topdir}/bashansi.h
+stringlist.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+stringlist.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+
+stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
+stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+stringvec.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+
+strnlen.o: ${BASHINCDIR}/stdc.h
+
+strpbrk.o: ${BASHINCDIR}/stdc.h
+
+strtod.o: ${topdir}/bashansi.h
+strtod.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+
+strtoimax.o: ${BASHINCDIR}/stdc.h
+
+strtol.o: ${topdir}/bashansi.h
+strtol.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+strtol.o: ${BASHINCDIR}/typemax.h
+
+strtoll.o: ${topdir}/bashansi.h
+strtoll.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+strtoll.o: ${BASHINCDIR}/typemax.h
+
+strtoul.o: ${topdir}/bashansi.h
+strtoul.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+strtoul.o: ${BASHINCDIR}/typemax.h
+
+strtoull.o: ${topdir}/bashansi.h
+strtoull.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+strtoull.o: ${BASHINCDIR}/typemax.h
+
+strtoumax.o: ${BASHINCDIR}/stdc.h
+
+strtrans.o: ${topdir}/bashansi.h
+strtrans.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
+strtrans.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
+strtrans.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
+strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
+strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
+strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
+strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
+strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
+
+times.o: ${BASHINCDIR}/systimes.h
+times.o: ${BASHINCDIR}/posixtime.h
+
+timeval.o: ${BASHINCDIR}/posixtime.h
+
+tmpfile.o: ${topdir}/bashtypes.h
+tmpfile.o: ${BASHINCDIR}/posixstat.h
+tmpfile.o: ${BASHINCDIR}/filecntl.h
+
+uconvert.o: ${topdir}/bashtypes.h
+
+ufuncs.o: ${topdir}/bashtypes.h
+
+clock.o: ${BASHINCDIR}/posixtime.h
+
+mailstat.o: ${topdir}/bashansi.h
+mailstat.o: ${topdir}/bashtypes.h
+mailstat.o: ${BASHINCDIR}/ansi_stdlib.h
+mailstat.o: ${BASHINCDIR}/posixstat.h
+mailstat.o: ${BASHINCDIR}/posixdir.h
+mailstat.o: ${BASHINCDIR}/maxpath.h
+
+fmtulong.o: ${topdir}/bashansi.h
+fmtulong.o: ${BASHINCDIR}/ansi_stdlib.h
+fmtulong.o: ${BASHINCDIR}/chartypes.h
+fmtulong.o: ${BASHINCDIR}/stdc.h
+fmtulong.o: ${BASHINCDIR}/typemax.h
+fmtulong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
+
+fmtullong.o: ${topdir}/bashansi.h
+fmtullong.o: ${BASHINCDIR}/ansi_stdlib.h
+fmtullong.o: ${BASHINCDIR}/chartypes.h
+fmtullong.o: ${BASHINCDIR}/stdc.h
+fmtullong.o: ${BASHINCDIR}/typemax.h
+fmtullong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
+
+fmtumax.o: ${topdir}/bashansi.h
+fmtumax.o: ${BASHINCDIR}/ansi_stdlib.h
+fmtumax.o: ${BASHINCDIR}/chartypes.h
+fmtumax.o: ${BASHINCDIR}/stdc.h
+fmtumax.o: ${BASHINCDIR}/typemax.h
+fmtumax.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
+
+wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+wcsdup.o: ${BASHINCDIR}/stdc.h
+wcsdup.o: ${topdir}/xmalloc.h
+
+wcswidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+wcswidth.o: ${BASHINCDIR}/stdc.h
+
+mbschr.o: ${topdir}/bashansi.h
+mbschr.o: ${BASHINCDIR}/ansi_stdlib.h
+mbschr.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+
+zgetline.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+zgetline.o: ${BASHINCDIR}/stdc.h
+zgetline.o: ${topdir}/xmalloc.h
+zgetline.o: ${topdir}/bashtypes.h
+
+mbscasecmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+mbscasecmp.o: ${BASHINCDIR}/stdc.h
+mbscasecmp.o: ${topdir}/xmalloc.h
+
+mbscmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+mbscmp.o: ${BASHINCDIR}/stdc.h
+mbscmp.o: ${topdir}/xmalloc.h
+
+casemod.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+casemod.o: ${BASHINCDIR}/stdc.h
+casemod.o: ${topdir}/xmalloc.h
+casemod.o: ${topdir}/bashtypes.h
+casemod.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
+casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
+
+dprintf.o: ${BASHINCDIR}/stdc.h
+
+input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+input_avail.o: ${BASHINCDIR}/stdc.h
+input_avail.o: ${topdir}/xmalloc.h ${BASHINCDIR}/posixselect.h
+
+mktime.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+mktime.o: ${BASHINCDIR}/stdc.h
+
+fnxform.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+fnxform.o: ${BASHINCDIR}/stdc.h
+fnxform.o: ${topdir}/bashtypes.h
+fnxform.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
+
+shmbchar.o: ${BASHINCDIR}/shmbchar.h
index f23995684acbe42a25af6bb4e7e68594890edc11..31d730a0a4377652fd31a02b94bc9449fc60d8d9 100644 (file)
--- a/pathexp.c
+++ b/pathexp.c
@@ -173,7 +173,9 @@ glob_char_p (s)
    removal has not been done (for example, before attempting to match a
    pattern while executing a case statement), flags should include
    QGLOB_CVTNULL.  If flags includes QGLOB_FILENAME, appropriate quoting
-   to match a filename should be performed. */
+   to match a filename should be performed.  QGLOB_REGEXP means we're
+   quoting for a Posix ERE (for [[ string =~ pat ]]) and that requires
+   some special handling. */
 char *
 quote_string_for_globbing (pathname, qflags)
      const char *pathname;
index a0d27bab4d6f3ee518f6619954c5651596c4bf9f..1ed5ac934104e9c7d2797fba3fa4fa6def360683 100644 (file)
@@ -58,6 +58,7 @@
 
 #include "builtins.h"
 #include "builtins/common.h"
+#include "builtins/builtext.h"
 
 #include <glob/glob.h>
 #include <glob/strmatch.h>
@@ -82,6 +83,7 @@ extern char *strpbrk __P((char *, char *));
 extern int array_needs_making;
 extern STRING_INT_ALIST word_token_alist[];
 extern char *signal_names[];
+extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
 
 #if defined (DEBUG)
 #if defined (PREFER_STDARG)
@@ -713,12 +715,28 @@ pcomp_filename_completion_function (text, state)
 {
   static char *dfn;    /* dequoted filename */
   int qc;
+  int iscompgen, iscompleting;
 
   if (state == 0)
     {
       FREE (dfn);
       /* remove backslashes quoting special characters in filenames. */
-      if (RL_ISSTATE (RL_STATE_COMPLETING) && rl_filename_dequoting_function)
+      /* There are roughtly three paths we can follow to get here:
+               1.  complete -f
+               2.  compgen -f "$word" from a completion function
+               3.  compgen -f "$word" from the command line
+        They all need to be handled.
+
+        In the first two cases, readline will run the filename dequoting
+        function in rl_filename_completion_function if it found a filename
+        quoting character in the word to be completed
+        (rl_completion_found_quote).  We run the dequoting function here
+        if we're running compgen, we're not completing, and the
+        rl_filename_completion_function won't dequote the filename
+        (rl_completion_found_quote == 0). */
+      iscompgen = this_shell_builtin == compgen_builtin;
+      iscompleting = RL_ISSTATE (RL_STATE_COMPLETING);
+      if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0)
        {
          /* Use rl_completion_quote_character because any single or
             double quotes have been removed by the time TEXT makes it
index 942aae4dcbb300d6e04dc980b6b81c470e2b8711..522f765b4312300f8db9b313577f13bee69a2f0a 100644 (file)
@@ -58,6 +58,7 @@
 
 #include "builtins.h"
 #include "builtins/common.h"
+#include "builtins/builtext.h"
 
 #include <glob/glob.h>
 #include <glob/strmatch.h>
@@ -713,12 +714,28 @@ pcomp_filename_completion_function (text, state)
 {
   static char *dfn;    /* dequoted filename */
   int qc;
+  int iscompgen, iscompleting;
 
   if (state == 0)
     {
       FREE (dfn);
       /* remove backslashes quoting special characters in filenames. */
-      if (RL_ISSTATE (RL_STATE_COMPLETING) && rl_filename_dequoting_function)
+      /* There are roughtly three paths we can follow to get here:
+               1.  complete -f
+               2.  compgen -f "$word" from a completion function
+               3.  compgen -f "$word" from the command line
+        They all need to be handled.
+
+        In the first two cases, readline will run the filename dequoting
+        function in rl_filename_completion_function if it found a filename
+        quoting character in the word to be completed
+        (rl_completion_found_quote).  We run the dequoting function here
+        if we're running compgen, we're not completing, and the
+        rl_filename_completion_function won't dequote the filename
+        (rl_completion_found_quote == 0). */
+      iscompgen = this_shell_builtin == compgen_builtin;
+      iscompleting = RL_ISSTATE (RL_STATE_COMPLETING);
+      if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0)
        {
          /* Use rl_completion_quote_character because any single or
             double quotes have been removed by the time TEXT makes it
@@ -801,15 +818,15 @@ gen_action_completions (cs, text)
   /* And lastly, the special case for directories */
   if (flags & CA_DIRECTORY)
     {
-      t = rl_filename_quoting_desired;
+      t = rl_filename_completion_desired;
       rl_completion_mark_symlink_dirs = 1;     /* override user preference */
       cmatches = bash_directory_completion_matches (text);
       /* If we did not want filename completion before this, and there are
-        no matches, turn off rl_filename_quoting_desired so whatever
+        no matches, turn off rl_filename_completion_desired so whatever
         matches we get are not treated as filenames (it gets turned on by
         rl_filename_completion_function unconditionally). */
-      if (t == 0 && cmatches == 0 && rl_filename_quoting_desired == 1)
-        rl_filename_quoting_desired = 0;
+      if (t == 0 && cmatches == 0 && rl_filename_completion_desired == 1)
+        rl_filename_completion_desired = 0;
       tmatches = completions_to_stringlist (cmatches);
       ret = strlist_append (ret, tmatches);
       strvec_dispose (cmatches);
index 031b800cf03d36529a62975b2dd026c2d69c7a41..afa579c900723b5c87eb315657a29c62a3e05f24 100644 (file)
@@ -1,2 +1,2 @@
 # Set of available languages.
-en@quot en@boldquot af bg ca cs da de eo es et fi fr ga gl hu id ja lt nl pl pt_BR ro ru sk sl sv tr uk vi zh_CN zh_TW
+en@quot en@boldquot af bg ca cs da de eo es et fi fr ga gl hu id it ja lt nl pl pt_BR ro ru sk sl sv tr uk vi zh_CN zh_TW
diff --git a/po/LINGUAS~ b/po/LINGUAS~
new file mode 100644 (file)
index 0000000..031b800
--- /dev/null
@@ -0,0 +1,2 @@
+# Set of available languages.
+en@quot en@boldquot af bg ca cs da de eo es et fi fr ga gl hu id ja lt nl pl pt_BR ro ru sk sl sv tr uk vi zh_CN zh_TW
diff --git a/po/it.po b/po/it.po
new file mode 100644 (file)
index 0000000..81cf39d
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,5226 @@
+# Italian translation for bash
+# Copyright (C) 2009 Free Software Foundation, Inc.
+# This file is distributed under the same license as the bash package.
+# Sergio Zanchetta <primes2h@ubuntu.com>, 2010, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: bash-4.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-01-28 22:09-0500\n"
+"PO-Revision-Date: 2011-10-14 16:33+0200\n"
+"Last-Translator: Sergio Zanchetta <primes2h@ubuntu.com>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural= (n != 1)\n"
+
+#: arrayfunc.c:50
+msgid "bad array subscript"
+msgstr "indice dell'array errato"
+
+#: arrayfunc.c:313 builtins/declare.def:487
+#, c-format
+msgid "%s: cannot convert indexed to associative array"
+msgstr "%s: impossibile convertire un array indicizzato in uno associativo"
+
+#: arrayfunc.c:480
+#, c-format
+msgid "%s: invalid associative array key"
+msgstr "%s: chiave dell'array associativo non valida"
+
+#: arrayfunc.c:482
+#, c-format
+msgid "%s: cannot assign to non-numeric index"
+msgstr "%s: impossibile assegnare a un indice non numerico"
+
+#: arrayfunc.c:518
+#, c-format
+msgid "%s: %s: must use subscript when assigning associative array"
+msgstr "%s: %s: deve essere usato un indice nell'assegnazione di un array associativo"
+
+#: bashhist.c:387
+#, c-format
+msgid "%s: cannot create: %s"
+msgstr "%s: impossibile creare: %s"
+
+#: bashline.c:3498
+msgid "bash_execute_unix_command: cannot find keymap for command"
+msgstr "bash_execute_unix_command: impossibile trovare una mappatura per il comando"
+
+#: bashline.c:3584
+#, c-format
+msgid "%s: first non-whitespace character is not `\"'"
+msgstr "%s: il primo carattere non spazio non è \"\"\""
+
+#: bashline.c:3613
+#, c-format
+msgid "no closing `%c' in %s"
+msgstr "carattere di chiusura \"%c\" non presente in %s"
+
+#: bashline.c:3647
+#, c-format
+msgid "%s: missing colon separator"
+msgstr "%s: separatore di tipo due punti mancante"
+
+#: builtins/alias.def:132
+#, c-format
+msgid "`%s': invalid alias name"
+msgstr "\"%s\": nome alias non valido"
+
+#: builtins/bind.def:120 builtins/bind.def:123
+msgid "line editing not enabled"
+msgstr "modifica delle righe non abilitata"
+
+#: builtins/bind.def:206
+#, c-format
+msgid "`%s': invalid keymap name"
+msgstr "\"%s\": nome della mappatura non valido"
+
+#: builtins/bind.def:245
+#, c-format
+msgid "%s: cannot read: %s"
+msgstr "%s: impossibile leggere: %s"
+
+#: builtins/bind.def:260
+#, c-format
+msgid "`%s': cannot unbind"
+msgstr "\"%s\": impossibile eliminare l'associazione"
+
+#: builtins/bind.def:295 builtins/bind.def:325
+#, c-format
+msgid "`%s': unknown function name"
+msgstr "\"%s\" nome della funzione sconosciuto"
+
+#: builtins/bind.def:303
+#, c-format
+msgid "%s is not bound to any keys.\n"
+msgstr "%s non è associato ad alcun tasto.\n"
+
+#: builtins/bind.def:307
+#, c-format
+msgid "%s can be invoked via "
+msgstr "%s può essere invocato tramite "
+
+#: builtins/break.def:77 builtins/break.def:117
+msgid "loop count"
+msgstr "numero di cicli"
+
+#: builtins/break.def:137
+msgid "only meaningful in a `for', `while', or `until' loop"
+msgstr "significativo solo in un ciclo \"for\", \"while\" o \"until\""
+
+#: builtins/caller.def:133
+msgid ""
+"Returns the context of the current subroutine call.\n"
+"    \n"
+"    Without EXPR, returns "
+msgstr ""
+"Restituisce il contesto della chiamata alla subroutine corrente.\n"
+"    \n"
+"    Senza ESPR, restituisce "
+
+#: builtins/cd.def:235
+msgid "HOME not set"
+msgstr "HOME non impostata"
+
+#: builtins/cd.def:247
+msgid "OLDPWD not set"
+msgstr "OLDPWD non impostata"
+
+#: builtins/common.c:101
+#, c-format
+msgid "line %d: "
+msgstr "riga %d: "
+
+#: builtins/common.c:139 error.c:261
+#, c-format
+msgid "warning: "
+msgstr "attenzione: "
+
+#: builtins/common.c:153
+#, c-format
+msgid "%s: usage: "
+msgstr "%s: uso: "
+
+#: builtins/common.c:166 test.c:832
+msgid "too many arguments"
+msgstr "troppi argomenti"
+
+#: builtins/common.c:191 shell.c:500 shell.c:782
+#, c-format
+msgid "%s: option requires an argument"
+msgstr "%s: l'opzione richiede un argomento"
+
+#: builtins/common.c:198
+#, c-format
+msgid "%s: numeric argument required"
+msgstr "%s: è necessario un argomento numerico"
+
+#: builtins/common.c:205
+#, c-format
+msgid "%s: not found"
+msgstr "%s: non trovata"
+
+#: builtins/common.c:214 shell.c:795
+#, c-format
+msgid "%s: invalid option"
+msgstr "%s: opzione non valida"
+
+#: builtins/common.c:221
+#, c-format
+msgid "%s: invalid option name"
+msgstr "%s: nome dell'opzione non valido"
+
+#: builtins/common.c:228 general.c:231 general.c:236
+#, c-format
+msgid "`%s': not a valid identifier"
+msgstr "\"%s\": non è un identificatore valido"
+
+#: builtins/common.c:238
+msgid "invalid octal number"
+msgstr "numero ottale non valido"
+
+#: builtins/common.c:240
+msgid "invalid hex number"
+msgstr "numero esadecimale non valido"
+
+#: builtins/common.c:242 expr.c:1362
+msgid "invalid number"
+msgstr "numero non valido"
+
+#: builtins/common.c:250
+#, c-format
+msgid "%s: invalid signal specification"
+msgstr "%s: specifica di segnale non valida"
+
+#: builtins/common.c:257
+#, c-format
+msgid "`%s': not a pid or valid job spec"
+msgstr "\"%s\": non è un pid o un numero di job valido"
+
+#: builtins/common.c:264 error.c:454
+#, c-format
+msgid "%s: readonly variable"
+msgstr "%s: variabile in sola lettura"
+
+#: builtins/common.c:272
+#, c-format
+msgid "%s: %s out of range"
+msgstr "%s: %s fuori dall'intervallo"
+
+#: builtins/common.c:272 builtins/common.c:274
+msgid "argument"
+msgstr "argomento"
+
+#: builtins/common.c:274
+#, c-format
+msgid "%s out of range"
+msgstr "%s fuori dall'intervallo"
+
+#: builtins/common.c:282
+#, c-format
+msgid "%s: no such job"
+msgstr "%s: job inesistente"
+
+#: builtins/common.c:290
+#, c-format
+msgid "%s: no job control"
+msgstr "%s: nessun controllo dei job"
+
+#: builtins/common.c:292
+msgid "no job control"
+msgstr "nessun controllo dei job"
+
+#: builtins/common.c:302
+#, c-format
+msgid "%s: restricted"
+msgstr "%s: limitato"
+
+#: builtins/common.c:304
+msgid "restricted"
+msgstr "limitato"
+
+#: builtins/common.c:312
+#, c-format
+msgid "%s: not a shell builtin"
+msgstr "%s: non è un comando interno di shell"
+
+#: builtins/common.c:321
+#, c-format
+msgid "write error: %s"
+msgstr "errore in scrittura: %s"
+
+#: builtins/common.c:329
+#, c-format
+msgid "error setting terminal attributes: %s"
+msgstr "errore nell'impostazione degli attributi del terminale: %s"
+
+#: builtins/common.c:331
+#, c-format
+msgid "error getting terminal attributes: %s"
+msgstr "errore nel recupero degli attributi del terminale: %s"
+
+#: builtins/common.c:563
+#, c-format
+msgid "%s: error retrieving current directory: %s: %s\n"
+msgstr "%s: errore nel recupero della directory corrente: %s: %s\n"
+
+#: builtins/common.c:629 builtins/common.c:631
+#, c-format
+msgid "%s: ambiguous job spec"
+msgstr "%s: specifica di job ambigua"
+
+#: builtins/complete.def:276
+#, c-format
+msgid "%s: invalid action name"
+msgstr "%s: nome azione non valido"
+
+#: builtins/complete.def:449 builtins/complete.def:644
+#: builtins/complete.def:853
+#, c-format
+msgid "%s: no completion specification"
+msgstr "%s: nessun completamento specificato"
+
+#: builtins/complete.def:696
+msgid "warning: -F option may not work as you expect"
+msgstr "attenzione: l'opzione -F potrebbe non funzionare come previsto"
+
+#: builtins/complete.def:698
+msgid "warning: -C option may not work as you expect"
+msgstr "attenzione: l'opzione -C potrebbe non funzionare come previsto"
+
+#: builtins/complete.def:826
+msgid "not currently executing completion function"
+msgstr "funzione di completamento attualmente non in esecuzione"
+
+#: builtins/declare.def:124
+msgid "can only be used in a function"
+msgstr "può essere usato solo in una funzione"
+
+#: builtins/declare.def:366
+msgid "cannot use `-f' to make functions"
+msgstr "impossibile usare \"-f\" per creare funzioni"
+
+#: builtins/declare.def:378 execute_cmd.c:5105
+#, c-format
+msgid "%s: readonly function"
+msgstr "%s: funzione in sola lettura"
+
+#: builtins/declare.def:474
+#, c-format
+msgid "%s: cannot destroy array variables in this way"
+msgstr "%s: impossibile eliminare variabili array in questo modo"
+
+#: builtins/declare.def:481
+#, c-format
+msgid "%s: cannot convert associative to indexed array"
+msgstr "%s: impossibile convertire un array associativo in uno indicizzato"
+
+#: builtins/enable.def:137 builtins/enable.def:145
+msgid "dynamic loading not available"
+msgstr "caricamento dinamico non disponibile"
+
+#: builtins/enable.def:312
+#, c-format
+msgid "cannot open shared object %s: %s"
+msgstr "impossibile aprire l'oggetto condiviso %s: %s"
+
+#: builtins/enable.def:335
+#, c-format
+msgid "cannot find %s in shared object %s: %s"
+msgstr "impossibile trovare %s nell'oggetto condiviso %s: %s"
+
+#: builtins/enable.def:459
+#, c-format
+msgid "%s: not dynamically loaded"
+msgstr "%s: non caricato dinamicamente"
+
+#: builtins/enable.def:474
+#, c-format
+msgid "%s: cannot delete: %s"
+msgstr "%s: impossibile eliminare: %s"
+
+#: builtins/evalfile.c:135 builtins/hash.def:171 execute_cmd.c:4961
+#: shell.c:1457
+#, c-format
+msgid "%s: is a directory"
+msgstr "%s: è una directory"
+
+#: builtins/evalfile.c:140
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: non è un file regolare"
+
+#: builtins/evalfile.c:148
+#, c-format
+msgid "%s: file is too large"
+msgstr "%s: file troppo grande"
+
+#: builtins/evalfile.c:182 builtins/evalfile.c:200 execute_cmd.c:5032
+#: shell.c:1467
+#, c-format
+msgid "%s: cannot execute binary file"
+msgstr "%s: impossibile eseguire il file binario"
+
+#: builtins/exec.def:154 builtins/exec.def:156 builtins/exec.def:228
+#, c-format
+msgid "%s: cannot execute: %s"
+msgstr "%s: impossibile eseguire: %s"
+
+#: builtins/exit.def:65
+#, c-format
+msgid "logout\n"
+msgstr "logout\n"
+
+#: builtins/exit.def:88
+msgid "not login shell: use `exit'"
+msgstr "non è una shell di login: utilizzare \"exit\""
+
+#: builtins/exit.def:120
+#, c-format
+msgid "There are stopped jobs.\n"
+msgstr "Sono presenti job interrotti.\n"
+
+#: builtins/exit.def:122
+#, c-format
+msgid "There are running jobs.\n"
+msgstr "Ci sono job in esecuzione.\n"
+
+#: builtins/fc.def:262
+msgid "no command found"
+msgstr "nessun comando trovato"
+
+#: builtins/fc.def:312 builtins/fc.def:359
+msgid "history specification"
+msgstr "specifica della cronologia"
+
+#: builtins/fc.def:380
+#, c-format
+msgid "%s: cannot open temp file: %s"
+msgstr "%s: impossibile aprire il file temp: %s"
+
+#: builtins/fg_bg.def:149 builtins/jobs.def:282
+msgid "current"
+msgstr "attuale"
+
+#: builtins/fg_bg.def:158
+#, c-format
+msgid "job %d started without job control"
+msgstr "job %d avviato senza controllo dei job"
+
+#: builtins/getopt.c:110
+#, c-format
+msgid "%s: illegal option -- %c\n"
+msgstr "%s: opzione illecita -- %c\n"
+
+#: builtins/getopt.c:111
+#, c-format
+msgid "%s: option requires an argument -- %c\n"
+msgstr "%s: l'opzione richiede un argomento -- %c\n"
+
+#: builtins/hash.def:92
+msgid "hashing disabled"
+msgstr "hashing disabilitato"
+
+#: builtins/hash.def:138
+#, c-format
+msgid "%s: hash table empty\n"
+msgstr "%s tabella di hash vuota\n"
+
+#: builtins/hash.def:245
+#, c-format
+msgid "hits\tcommand\n"
+msgstr "rich.\tcomando\n"
+
+#: builtins/help.def:130
+#, c-format
+msgid "Shell commands matching keyword `"
+msgid_plural "Shell commands matching keywords `"
+msgstr[0] "Comandi di shell corrispondenti alla parola chiave \""
+msgstr[1] "Comandi di shell corrispondenti alle parole chiave \""
+
+#: builtins/help.def:168
+#, c-format
+msgid "no help topics match `%s'.  Try `help help' or `man -k %s' or `info %s'."
+msgstr "nessun argomento della guida corrisponde a \"%s\". Provare \"help help\" o \"man -k %s\" o \"info %s\"."
+
+#: builtins/help.def:185
+#, c-format
+msgid "%s: cannot open: %s"
+msgstr "%s: impossibile aprire: %s"
+
+#: builtins/help.def:337
+#, c-format
+msgid ""
+"These shell commands are defined internally.  Type `help' to see this list.\n"
+"Type `help name' to find out more about the function `name'.\n"
+"Use `info bash' to find out more about the shell in general.\n"
+"Use `man -k' or `info' to find out more about commands not in this list.\n"
+"\n"
+"A star (*) next to a name means that the command is disabled.\n"
+"\n"
+msgstr ""
+"Questi comandi della shell sono definiti internamente. Digitare \"help\" per consultare questa lista.\n"
+"Digitare \"help nome\" per saperne di più sulla funzione \"nome\".\n"
+"Usare \"info bash\" per saperne di più sulla shell in generale.\n"
+"Usare \"man -k\" o \"info\" per saperne di più su comandi non presenti nella lista.\n"
+"\n"
+"Un asterisco (*) vicino a un nome significa che il comando è disabilitato.\n"
+"\n"
+
+#: builtins/history.def:154
+msgid "cannot use more than one of -anrw"
+msgstr "impossibile usare più di uno tra -anrw"
+
+#: builtins/history.def:186
+msgid "history position"
+msgstr "posizione nella cronologia"
+
+#: builtins/history.def:365
+#, c-format
+msgid "%s: history expansion failed"
+msgstr "%s: espansione della cronologia non riuscita"
+
+#: builtins/inlib.def:71
+#, c-format
+msgid "%s: inlib failed"
+msgstr "%s: inlib non riuscito"
+
+#: builtins/jobs.def:109
+msgid "no other options allowed with `-x'"
+msgstr "nessuna altra opzione permessa con \"-x\""
+
+#: builtins/kill.def:198
+#, c-format
+msgid "%s: arguments must be process or job IDs"
+msgstr "%s: gli argomenti devono essere ID di processo o di job"
+
+#: builtins/kill.def:261
+msgid "Unknown error"
+msgstr "Errore sconosciuto"
+
+#: builtins/let.def:95 builtins/let.def:120 expr.c:552 expr.c:567
+msgid "expression expected"
+msgstr "attesa espressione"
+
+#: builtins/mapfile.def:172
+#, c-format
+msgid "%s: not an indexed array"
+msgstr "%s: non è un array indicizzato"
+
+#: builtins/mapfile.def:256 builtins/read.def:279
+#, c-format
+msgid "%s: invalid file descriptor specification"
+msgstr "%s: specifica di descrittore di file non valida"
+
+#: builtins/mapfile.def:264 builtins/read.def:286
+#, c-format
+msgid "%d: invalid file descriptor: %s"
+msgstr "%d: descrittore di file non valido: %s"
+
+#: builtins/mapfile.def:273 builtins/mapfile.def:311
+#, c-format
+msgid "%s: invalid line count"
+msgstr "%s: numero di righe non valido"
+
+#: builtins/mapfile.def:284
+#, c-format
+msgid "%s: invalid array origin"
+msgstr "%s: origine dell'array non valida"
+
+#: builtins/mapfile.def:301
+#, c-format
+msgid "%s: invalid callback quantum"
+msgstr "%s: quantum di callback non valido"
+
+#: builtins/mapfile.def:333
+msgid "empty array variable name"
+msgstr "nome della variabile array vuoto"
+
+#: builtins/mapfile.def:354
+msgid "array variable support required"
+msgstr "necessario il supporto alla variabile array"
+
+#: builtins/printf.def:394
+#, c-format
+msgid "`%s': missing format character"
+msgstr "\"%s\": manca il carattere di formato"
+
+#: builtins/printf.def:448
+#, c-format
+msgid "`%c': invalid time format specification"
+msgstr "\"%c\": specifica di formato dell'orario non valida"
+
+#: builtins/printf.def:635
+#, c-format
+msgid "`%c': invalid format character"
+msgstr "\"%c\": carattere di formato non valido"
+
+#: builtins/printf.def:662
+#, c-format
+msgid "warning: %s: %s"
+msgstr "attenzione: %s: %s"
+
+#: builtins/printf.def:840
+msgid "missing hex digit for \\x"
+msgstr "cifra esadecimale mancante in \\x"
+
+#: builtins/printf.def:855
+#, c-format
+msgid "missing unicode digit for \\%c"
+msgstr "cifra unicode mancante in \\%c"
+
+#: builtins/pushd.def:195
+msgid "no other directory"
+msgstr "nessun'altra directory"
+
+#: builtins/pushd.def:462
+msgid "<no current directory>"
+msgstr "<nessuna directory corrente>"
+
+#: builtins/pushd.def:506
+msgid "directory stack empty"
+msgstr "stack delle directory vuoto"
+
+#: builtins/pushd.def:508
+msgid "directory stack index"
+msgstr "indice dello stack delle directory"
+
+#: builtins/pushd.def:683
+msgid ""
+"Display the list of currently remembered directories.  Directories\n"
+"    find their way onto the list with the `pushd' command; you can get\n"
+"    back up through the list with the `popd' command.\n"
+"    \n"
+"    Options:\n"
+"      -c\tclear the directory stack by deleting all of the elements\n"
+"      -l\tdo not print tilde-prefixed versions of directories relative\n"
+"    \tto your home directory\n"
+"      -p\tprint the directory stack with one entry per line\n"
+"      -v\tprint the directory stack with one entry per line prefixed\n"
+"    \twith its position in the stack\n"
+"    \n"
+"    Arguments:\n"
+"      +N\tDisplays the Nth entry counting from the left of the list shown by\n"
+"    \tdirs when invoked without options, starting with zero.\n"
+"    \n"
+"      -N\tDisplays the Nth entry counting from the right of the list shown by\n"
+"\tdirs when invoked without options, starting with zero."
+msgstr ""
+"Visualizza l'elenco delle directory attualmente in memoria. Le directory\n"
+"    vengono inserite nell'elenco con il comando \"pushd\"; è possibile\n"
+"    andare a ritroso nell'elenco con il comando \"popd\".\n"
+"    \n"
+"    Opzioni:\n"
+"      -c\tPulisce lo stack delle directory eliminandone tutti gli elementi\n"
+"      -l\tNon stampa la tilde come prefisso per le directory relative alla\n"
+"    \tpropria directory home\n"
+"      -p\tStampa lo stack delle directory una voce per riga\n"
+"      -v\tStampa lo stack delle directory una voce per riga usando la\n"
+"    \tposizione nello stack stesso come prefisso\n"
+"    \n"
+"    Argomenti:\n"
+"      +N\tVisualizza l'N-sima voce contando a partire da sinistra dell'elenco\n"
+"    \tmostrato da dirs quando invocato senza opzioni, iniziando da zero.\n"
+"    \n"
+"      -N\tVisualizza l'N-sima voce contando a partire da destra dell'elenco\n"
+"\tmostrato da dirs quando invocato senza opzioni, iniziando da zero."
+
+#: builtins/pushd.def:705
+msgid ""
+"Adds a directory to the top of the directory stack, or rotates\n"
+"    the stack, making the new top of the stack the current working\n"
+"    directory.  With no arguments, exchanges the top two directories.\n"
+"    \n"
+"    Options:\n"
+"      -n\tSuppresses the normal change of directory when adding\n"
+"    \tdirectories to the stack, so only the stack is manipulated.\n"
+"    \n"
+"    Arguments:\n"
+"      +N\tRotates the stack so that the Nth directory (counting\n"
+"    \tfrom the left of the list shown by `dirs', starting with\n"
+"    \tzero) is at the top.\n"
+"    \n"
+"      -N\tRotates the stack so that the Nth directory (counting\n"
+"    \tfrom the right of the list shown by `dirs', starting with\n"
+"    \tzero) is at the top.\n"
+"    \n"
+"      dir\tAdds DIR to the directory stack at the top, making it the\n"
+"    \tnew current working directory.\n"
+"    \n"
+"    The `dirs' builtin displays the directory stack."
+msgstr ""
+"Aggiunge una directory in cima allo stack delle directory o ruota lo\n"
+"    stack stesso, mettendo come primo elemento l'attuale directory\n"
+"    di lavoro. Senza argomenti scambia le prime due directory in cima.\n"
+"    \n"
+"    Opzioni:\n"
+"      -n\tEvita il normale cambio di directory quando vengono aggiunte\n"
+"    \tdirectory allo stack, così da manipolare solo lo stack stesso.\n"
+"    \n"
+"    Argomenti:\n"
+"      +N\tRuota lo stack in modo che l'N-sima directory (contando\n"
+"    \ta partire da sinistra dell'elenco mostrato da \"dirs\", iniziando da\n"
+"    \tzero) sia in cima.\n"
+"    \n"
+"      -N\tRuota lo stack in modo che l'N-sima directory (contando\n"
+"    \ta partire da destra dell'elenco mostrato da \"dirs\", iniziando da\n"
+"    \tzero) sia in cima.\n"
+"    \n"
+"      dir\tAggiunge DIR in cima allo stack delle directory, facendone la\n"
+"    \tdirectory di lavoro corrente.\n"
+"    \n"
+"    Il comando interno \"dirs\" visualizza lo stack delle directory."
+
+#: builtins/pushd.def:730
+msgid ""
+"Removes entries from the directory stack.  With no arguments, removes\n"
+"    the top directory from the stack, and changes to the new top directory.\n"
+"    \n"
+"    Options:\n"
+"      -n\tSuppresses the normal change of directory when removing\n"
+"    \tdirectories from the stack, so only the stack is manipulated.\n"
+"    \n"
+"    Arguments:\n"
+"      +N\tRemoves the Nth entry counting from the left of the list\n"
+"    \tshown by `dirs', starting with zero.  For example: `popd +0'\n"
+"    \tremoves the first directory, `popd +1' the second.\n"
+"    \n"
+"      -N\tRemoves the Nth entry counting from the right of the list\n"
+"    \tshown by `dirs', starting with zero.  For example: `popd -0'\n"
+"    \tremoves the last directory, `popd -1' the next to last.\n"
+"    \n"
+"    The `dirs' builtin displays the directory stack."
+msgstr ""
+"Rimuove voci dallo stack delle directory. Senza argomenti, rimuove\n"
+"    la directory in cima allo stack e passa alla nuova prima directory.\n"
+"    \n"
+"    Opzioni:\n"
+"      -n\tEvita il normale cambio di directory quando vengono rimosse\n"
+"    \tdirectory dallo stack, così da manipolare solo lo stack stesso.\n"
+"    \n"
+"    Argomenti:\n"
+"      +N\tRimuove l'N-sima voce contando a partire da sinistra dell'elenco\n"
+"    \tmostrato da \"dirs\", iniziando da zero. Per esempio: \"popd +0\"\n"
+"    \trimuove la prima directory, \"popd +1\" la seconda.\n"
+"    \n"
+"      -N\tRimuove l'N-sima voce contando a partire da destra dell'elenco\n"
+"    \tmostrato da \"dirs\", iniziando da zero. Per esempio: \"popd -0\"\n"
+"    \trimuove l'ultima directory, \"popd -1\" la penultima.\n"
+"    \n"
+"    Il comando interno \"dirs\" visualizza lo stack delle directory."
+
+#: builtins/read.def:252
+#, c-format
+msgid "%s: invalid timeout specification"
+msgstr "%s: specifica di timeout non valida"
+
+#: builtins/read.def:588
+#, c-format
+msgid "read error: %d: %s"
+msgstr "errore in lettura: %d: %s"
+
+#: builtins/return.def:73
+msgid "can only `return' from a function or sourced script"
+msgstr "è possibile eseguire \"return\" solo da una funzione o da uno script chiamato"
+
+#: builtins/set.def:771
+msgid "cannot simultaneously unset a function and a variable"
+msgstr "impossibile azzerare contemporaneamente una funzione e una variabile"
+
+#: builtins/set.def:808
+#, c-format
+msgid "%s: cannot unset"
+msgstr "%s: impossibile azzerare"
+
+#: builtins/set.def:815
+#, c-format
+msgid "%s: cannot unset: readonly %s"
+msgstr "%s: impossibile azzerare: %s in sola lettura"
+
+#: builtins/set.def:826
+#, c-format
+msgid "%s: not an array variable"
+msgstr "%s: non è una variabile array"
+
+#: builtins/setattr.def:186
+#, c-format
+msgid "%s: not a function"
+msgstr "%s: non è una funzione"
+
+#: builtins/shift.def:71 builtins/shift.def:77
+msgid "shift count"
+msgstr "numero di scorrimenti"
+
+#: builtins/shopt.def:264
+msgid "cannot set and unset shell options simultaneously"
+msgstr "impossibile impostare e azzerare opzioni di shell contemporaneamente"
+
+#: builtins/shopt.def:329
+#, c-format
+msgid "%s: invalid shell option name"
+msgstr "%s: nome dell'opzione di shell non valido"
+
+#: builtins/source.def:130
+msgid "filename argument required"
+msgstr "necessario un nome file come argomento"
+
+#: builtins/source.def:155
+#, c-format
+msgid "%s: file not found"
+msgstr "%s: file non trovato"
+
+#: builtins/suspend.def:101
+msgid "cannot suspend"
+msgstr "impossibile sospendere"
+
+#: builtins/suspend.def:111
+msgid "cannot suspend a login shell"
+msgstr "impossibile sospendere una shell di login"
+
+#: builtins/type.def:234
+#, c-format
+msgid "%s is aliased to `%s'\n"
+msgstr "%s ha \"%s\" come alias\n"
+
+#: builtins/type.def:255
+#, c-format
+msgid "%s is a shell keyword\n"
+msgstr "%s è una parola chiave di shell\n"
+
+#: builtins/type.def:274
+#, c-format
+msgid "%s is a function\n"
+msgstr "%s è una funzione\n"
+
+#: builtins/type.def:296
+#, c-format
+msgid "%s is a shell builtin\n"
+msgstr "%s è un comando interno di shell\n"
+
+#: builtins/type.def:317 builtins/type.def:391
+#, c-format
+msgid "%s is %s\n"
+msgstr "%s è %s\n"
+
+#: builtins/type.def:337
+#, c-format
+msgid "%s is hashed (%s)\n"
+msgstr "hash effettuato su %s (%s)\n"
+
+#: builtins/ulimit.def:376
+#, c-format
+msgid "%s: invalid limit argument"
+msgstr "%s: argomento di limite non valido"
+
+#: builtins/ulimit.def:402
+#, c-format
+msgid "`%c': bad command"
+msgstr "\"%c\": comando errato"
+
+#: builtins/ulimit.def:431
+#, c-format
+msgid "%s: cannot get limit: %s"
+msgstr "%s: impossibile recuperare il limite: %s"
+
+#: builtins/ulimit.def:457
+msgid "limit"
+msgstr "limite"
+
+#: builtins/ulimit.def:469 builtins/ulimit.def:769
+#, c-format
+msgid "%s: cannot modify limit: %s"
+msgstr "%s: impossibile modificare il limite: %s"
+
+#: builtins/umask.def:118
+msgid "octal number"
+msgstr "numero ottale"
+
+#: builtins/umask.def:231
+#, c-format
+msgid "`%c': invalid symbolic mode operator"
+msgstr "\"%c\": operatore di modo simbolico non valido"
+
+#: builtins/umask.def:286
+#, c-format
+msgid "`%c': invalid symbolic mode character"
+msgstr "\"%c\": carattere di modo simbolico non valido"
+
+#: error.c:90 error.c:321 error.c:323 error.c:325
+msgid " line "
+msgstr " riga "
+
+#: error.c:165
+#, c-format
+msgid "last command: %s\n"
+msgstr "ultimo comando: %s\n"
+
+#: error.c:173
+#, c-format
+msgid "Aborting..."
+msgstr "Interruzione..."
+
+#: error.c:406
+msgid "unknown command error"
+msgstr "errore di comando sconosciuto"
+
+#: error.c:407
+msgid "bad command type"
+msgstr "tipo di comando errato"
+
+#: error.c:408
+msgid "bad connector"
+msgstr "connettore errato"
+
+#: error.c:409
+msgid "bad jump"
+msgstr "salto errato"
+
+#: error.c:447
+#, c-format
+msgid "%s: unbound variable"
+msgstr "%s: variabile non assegnata"
+
+#: eval.c:181
+#, c-format
+msgid "\atimed out waiting for input: auto-logout\n"
+msgstr "\atempo di attesa scaduto per l'input: auto-logout\n"
+
+#: execute_cmd.c:504
+#, c-format
+msgid "cannot redirect standard input from /dev/null: %s"
+msgstr "impossibile redirigere lo standard input da /dev/null: %s"
+
+#: execute_cmd.c:1168
+#, c-format
+msgid "TIMEFORMAT: `%c': invalid format character"
+msgstr "TIMEFORMAT: \"%c\": carattere di formato non valido"
+
+#: execute_cmd.c:2121
+msgid "pipe error"
+msgstr "errore della pipe"
+
+#: execute_cmd.c:4640
+#, c-format
+msgid "%s: restricted: cannot specify `/' in command names"
+msgstr "%s: limitato: impossibile specificare \"/\" nei nomi dei comandi"
+
+#: execute_cmd.c:4735
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: comando non trovato"
+
+#: execute_cmd.c:4959
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: execute_cmd.c:4995
+#, c-format
+msgid "%s: %s: bad interpreter"
+msgstr "%s: %s: interprete errato"
+
+#: execute_cmd.c:5144
+#, c-format
+msgid "cannot duplicate fd %d to fd %d"
+msgstr "impossibile duplicare fd %d su fd %d"
+
+#: expr.c:256
+msgid "expression recursion level exceeded"
+msgstr "superato il livello di ricorsione dell'espressione"
+
+#: expr.c:280
+msgid "recursion stack underflow"
+msgstr "underflow dello stack di ricorsione"
+
+#: expr.c:422
+msgid "syntax error in expression"
+msgstr "errore di sintassi nell'espressione"
+
+#: expr.c:463
+msgid "attempted assignment to non-variable"
+msgstr "tentata un'assegnazione a una non variabile"
+
+#: expr.c:486 expr.c:491 expr.c:807
+msgid "division by 0"
+msgstr "divisione per 0"
+
+#: expr.c:517
+msgid "bug: bad expassign token"
+msgstr "bug: token di expassign errato"
+
+#: expr.c:564
+msgid "`:' expected for conditional expression"
+msgstr "atteso \":\" per l'espressione condizionale"
+
+#: expr.c:832
+msgid "exponent less than 0"
+msgstr "esponente minore di 0"
+
+#: expr.c:887
+msgid "identifier expected after pre-increment or pre-decrement"
+msgstr "atteso identificatore dopo un pre-incremento o un pre-decremento"
+
+#: expr.c:910
+msgid "missing `)'"
+msgstr "\")\" mancante"
+
+#: expr.c:959 expr.c:1282
+msgid "syntax error: operand expected"
+msgstr "errore di sintassi: atteso un operando"
+
+#: expr.c:1284
+msgid "syntax error: invalid arithmetic operator"
+msgstr "errore di sintassi: operatore aritmetico non valido"
+
+#: expr.c:1308
+#, c-format
+msgid "%s%s%s: %s (error token is \"%s\")"
+msgstr "%s%s%s: %s (il token dell'errore è \"%s\")"
+
+#: expr.c:1366
+msgid "invalid arithmetic base"
+msgstr "base aritmetica non valida"
+
+#: expr.c:1386
+msgid "value too great for base"
+msgstr "valore troppo grande per la base"
+
+#: expr.c:1435
+#, c-format
+msgid "%s: expression error\n"
+msgstr "%s: errore di espressione\n"
+
+#: general.c:61
+msgid "getcwd: cannot access parent directories"
+msgstr "getcwd: impossibile accedere alle directory padre"
+
+#: input.c:94 subst.c:5082
+#, c-format
+msgid "cannot reset nodelay mode for fd %d"
+msgstr "impossibile reimpostare il modo nodelay per fd %d"
+
+#: input.c:260
+#, c-format
+msgid "cannot allocate new file descriptor for bash input from fd %d"
+msgstr "impossibile allocare un nuovo descrittore di file per l'input della bash da fd %d"
+
+#: input.c:268
+#, c-format
+msgid "save_bash_input: buffer already exists for new fd %d"
+msgstr "save_bash_input: buffer già esistente per il nuovo fd %d"
+
+#: jobs.c:468
+msgid "start_pipeline: pgrp pipe"
+msgstr "start_pipeline: pipe pgrp"
+
+#: jobs.c:889
+#, c-format
+msgid "forked pid %d appears in running job %d"
+msgstr "il pid %d del fork appare nel job in esecuzione %d"
+
+#: jobs.c:1007
+#, c-format
+msgid "deleting stopped job %d with process group %ld"
+msgstr "eliminazione del job %d interrotto con il gruppo di processi %ld"
+
+#: jobs.c:1112
+#, c-format
+msgid "add_process: process %5ld (%s) in the_pipeline"
+msgstr "add_process: processo %5ld (%s) in the_pipeline"
+
+#: jobs.c:1115
+#, c-format
+msgid "add_process: pid %5ld (%s) marked as still alive"
+msgstr "add_process: pid %5ld (%s) segnato come ancora in vita"
+
+#: jobs.c:1430
+#, c-format
+msgid "describe_pid: %ld: no such pid"
+msgstr "describe_pid: %ld: pid inesistente"
+
+#: jobs.c:1445
+#, c-format
+msgid "Signal %d"
+msgstr "Segnale %d"
+
+#: jobs.c:1459 jobs.c:1484
+msgid "Done"
+msgstr "Completato"
+
+#: jobs.c:1464 siglist.c:123
+msgid "Stopped"
+msgstr "Fermato"
+
+#: jobs.c:1468
+#, c-format
+msgid "Stopped(%s)"
+msgstr "Fermato(%s)"
+
+#: jobs.c:1472
+msgid "Running"
+msgstr "In esecuzione"
+
+#: jobs.c:1486
+#, c-format
+msgid "Done(%d)"
+msgstr "Eseguito(%d)"
+
+#: jobs.c:1488
+#, c-format
+msgid "Exit %d"
+msgstr "Uscita %d"
+
+#: jobs.c:1491
+msgid "Unknown status"
+msgstr "Stato sconosciuto"
+
+#: jobs.c:1578
+#, c-format
+msgid "(core dumped) "
+msgstr "(core dump creato) "
+
+#: jobs.c:1597
+#, c-format
+msgid "  (wd: %s)"
+msgstr "  (dir: %s)"
+
+#: jobs.c:1805
+#, c-format
+msgid "child setpgid (%ld to %ld)"
+msgstr "setpgid del figlio (%ld a %ld)"
+
+#: jobs.c:2133 nojobs.c:585
+#, c-format
+msgid "wait: pid %ld is not a child of this shell"
+msgstr "wait: il pid %ld non è un figlio di questa shell"
+
+#: jobs.c:2360
+#, c-format
+msgid "wait_for: No record of process %ld"
+msgstr "wait_for: nessun record del processo %ld"
+
+#: jobs.c:2637
+#, c-format
+msgid "wait_for_job: job %d is stopped"
+msgstr "wait_for_job: il job %d è fermo"
+
+#: jobs.c:2859
+#, c-format
+msgid "%s: job has terminated"
+msgstr "%s: il job è terminato"
+
+#: jobs.c:2868
+#, c-format
+msgid "%s: job %d already in background"
+msgstr "%s: il job %d è già in background"
+
+#: jobs.c:3089
+msgid "waitchld: turning on WNOHANG to avoid indefinite block"
+msgstr "waitchld: attivato WNOHANG per evitare blocchi indefiniti"
+
+#: jobs.c:3538
+#, c-format
+msgid "%s: line %d: "
+msgstr "%s: riga %d: "
+
+#: jobs.c:3552 nojobs.c:814
+#, c-format
+msgid " (core dumped)"
+msgstr " (core dump creato)"
+
+#: jobs.c:3564 jobs.c:3577
+#, c-format
+msgid "(wd now: %s)\n"
+msgstr "(dir ora: %s)\n"
+
+#: jobs.c:3609
+msgid "initialize_job_control: getpgrp failed"
+msgstr "initialize_job_control: getpgrp non riuscita"
+
+#: jobs.c:3669
+msgid "initialize_job_control: line discipline"
+msgstr "initialize_job_control: disciplina di linea"
+
+#: jobs.c:3679
+msgid "initialize_job_control: setpgid"
+msgstr "initialize_job_control: setpgid"
+
+#: jobs.c:3707
+#, c-format
+msgid "cannot set terminal process group (%d)"
+msgstr "impossibile impostare il gruppo di processi del terminale (%d)"
+
+#: jobs.c:3712
+msgid "no job control in this shell"
+msgstr "nessun controllo dei job in questa shell"
+
+#: lib/malloc/malloc.c:296
+#, c-format
+msgid "malloc: failed assertion: %s\n"
+msgstr "malloc: asserzione non riuscita: %s\n"
+
+#: lib/malloc/malloc.c:312
+#, c-format
+msgid ""
+"\r\n"
+"malloc: %s:%d: assertion botched\r\n"
+msgstr ""
+"\r\n"
+"malloc: %s:%d: asserzione non riuscita\r\n"
+
+#: lib/malloc/malloc.c:313
+msgid "unknown"
+msgstr "sconosciuto"
+
+#: lib/malloc/malloc.c:797
+msgid "malloc: block on free list clobbered"
+msgstr "malloc: blocco eliminato nell'elenco dei disponibili"
+
+#: lib/malloc/malloc.c:874
+msgid "free: called with already freed block argument"
+msgstr "free: chiamata con un argomento di blocco già liberato"
+
+#: lib/malloc/malloc.c:877
+msgid "free: called with unallocated block argument"
+msgstr "free: chiamata con un argomento di blocco non allocato"
+
+#: lib/malloc/malloc.c:896
+msgid "free: underflow detected; mh_nbytes out of range"
+msgstr "free: riscontrato un underflow; mh_nbytes fuori intervallo"
+
+#: lib/malloc/malloc.c:902
+msgid "free: start and end chunk sizes differ"
+msgstr "free: dimensioni diverse dei blocchi di inizio e di fine"
+
+#: lib/malloc/malloc.c:1001
+msgid "realloc: called with unallocated block argument"
+msgstr "realloc: chiamata con un argomento di blocco non allocato"
+
+#: lib/malloc/malloc.c:1016
+msgid "realloc: underflow detected; mh_nbytes out of range"
+msgstr "realloc: riscontrato un underflow; mh_nbytes fuori intervallo"
+
+#: lib/malloc/malloc.c:1022
+msgid "realloc: start and end chunk sizes differ"
+msgstr "realloc: dimensioni diverse dei blocchi di inizio e di fine"
+
+#: lib/malloc/table.c:177
+#, c-format
+msgid "register_alloc: alloc table is full with FIND_ALLOC?\n"
+msgstr "register_alloc: forse la tavola di allocazione è piena con FIND_ALLOC\n"
+
+#: lib/malloc/table.c:184
+#, c-format
+msgid "register_alloc: %p already in table as allocated?\n"
+msgstr "register_alloc: forse %p è già come allocato nella tabella\n"
+
+#: lib/malloc/table.c:220
+#, c-format
+msgid "register_free: %p already in table as free?\n"
+msgstr "register_alloc: forse %p è già come libero nella tabella\n"
+
+#: lib/sh/fmtulong.c:101
+msgid "invalid base"
+msgstr "base non valida"
+
+#: lib/sh/netopen.c:168
+#, c-format
+msgid "%s: host unknown"
+msgstr "%s: host sconosciuto"
+
+#: lib/sh/netopen.c:175
+#, c-format
+msgid "%s: invalid service"
+msgstr "%s: servizio non valido"
+
+#: lib/sh/netopen.c:306
+#, c-format
+msgid "%s: bad network path specification"
+msgstr "%s: specifica del percorso di rete errata"
+
+#: lib/sh/netopen.c:346
+msgid "network operations not supported"
+msgstr "operazione di rete non supportata"
+
+#: locale.c:192
+#, c-format
+msgid "setlocale: LC_ALL: cannot change locale (%s)"
+msgstr "setlocale: LC_ALL: impossibile cambiare la localizzazione (%s)"
+
+#: locale.c:194
+#, c-format
+msgid "setlocale: LC_ALL: cannot change locale (%s): %s"
+msgstr "setlocale: LC_ALL: impossibile cambiare la localizzazione (%s): %s"
+
+#: locale.c:247
+#, c-format
+msgid "setlocale: %s: cannot change locale (%s)"
+msgstr "setlocale: %s: impossibile cambiare la localizzazione (%s)"
+
+#: locale.c:249
+#, c-format
+msgid "setlocale: %s: cannot change locale (%s): %s"
+msgstr "setlocale: %s: impossibile cambiare la localizzazione (%s): %s"
+
+#: mailcheck.c:433
+msgid "You have mail in $_"
+msgstr "È presente della posta in $_"
+
+#: mailcheck.c:458
+msgid "You have new mail in $_"
+msgstr "È presente della nuova posta in $_"
+
+#: mailcheck.c:474
+#, c-format
+msgid "The mail in %s has been read\n"
+msgstr "La posta in %s è stata letta\n"
+
+#: make_cmd.c:323
+msgid "syntax error: arithmetic expression required"
+msgstr "errore di sintassi: richiesta espressione aritmetica"
+
+#: make_cmd.c:325
+msgid "syntax error: `;' unexpected"
+msgstr "errore di sintassi: \";\" non atteso"
+
+#: make_cmd.c:326
+#, c-format
+msgid "syntax error: `((%s))'"
+msgstr "errore di sintassi: \"((%s))\""
+
+#: make_cmd.c:575
+#, c-format
+msgid "make_here_document: bad instruction type %d"
+msgstr "make_here_document: tipo di istruzione errata %d"
+
+#: make_cmd.c:659
+#, c-format
+msgid "here-document at line %d delimited by end-of-file (wanted `%s')"
+msgstr "here-document alla riga %d è delimitato da un EOF (era richiesto \"%s\")"
+
+#: make_cmd.c:756
+#, c-format
+msgid "make_redirection: redirection instruction `%d' out of range"
+msgstr "make_redirection: istruzione di reindirizzamento \"%d\" fuori dell'intervallo"
+
+#: parse.y:3173 parse.y:3444
+#, c-format
+msgid "unexpected EOF while looking for matching `%c'"
+msgstr "EOF non atteso durante la ricerca di \"%c\""
+
+#: parse.y:4025
+msgid "unexpected EOF while looking for `]]'"
+msgstr "EOF non atteso durante la ricerca di \"]]\""
+
+#: parse.y:4030
+#, c-format
+msgid "syntax error in conditional expression: unexpected token `%s'"
+msgstr "errore di sintassi nell'espressione condizionale: token non atteso \"%s\""
+
+#: parse.y:4034
+msgid "syntax error in conditional expression"
+msgstr "errore di sintassi nell'espressione condizionale"
+
+#: parse.y:4112
+#, c-format
+msgid "unexpected token `%s', expected `)'"
+msgstr "token non atteso \"%s\", era atteso \")\""
+
+#: parse.y:4116
+msgid "expected `)'"
+msgstr "atteso \")\""
+
+#: parse.y:4144
+#, c-format
+msgid "unexpected argument `%s' to conditional unary operator"
+msgstr "argomento non atteso \"%s\" per l'operatore unario condizionale"
+
+#: parse.y:4148
+msgid "unexpected argument to conditional unary operator"
+msgstr "argomento non atteso per l'operatore unario condizionale"
+
+#: parse.y:4194
+#, c-format
+msgid "unexpected token `%s', conditional binary operator expected"
+msgstr "token non atteso \"%s\", era atteso un operatore binario condizionale"
+
+#: parse.y:4198
+msgid "conditional binary operator expected"
+msgstr "atteso operatore binario condizionale"
+
+#: parse.y:4220
+#, c-format
+msgid "unexpected argument `%s' to conditional binary operator"
+msgstr "argomento non atteso \"%s\" per l'operatore binario condizionale"
+
+#: parse.y:4224
+msgid "unexpected argument to conditional binary operator"
+msgstr "argomento non atteso per l'operatore binario condizionale"
+
+#: parse.y:4235
+#, c-format
+msgid "unexpected token `%c' in conditional command"
+msgstr "token non atteso \"%c\" nel comando condizionale"
+
+#: parse.y:4238
+#, c-format
+msgid "unexpected token `%s' in conditional command"
+msgstr "token non atteso \"%s\" nel comando condizionale"
+
+#: parse.y:4242
+#, c-format
+msgid "unexpected token %d in conditional command"
+msgstr "token non atteso %d nel comando condizionale"
+
+#: parse.y:5566
+#, c-format
+msgid "syntax error near unexpected token `%s'"
+msgstr "errore di sintassi vicino al token non atteso \"%s\""
+
+#: parse.y:5584
+#, c-format
+msgid "syntax error near `%s'"
+msgstr "errore di sintassi vicino a \"%s\""
+
+#: parse.y:5594
+msgid "syntax error: unexpected end of file"
+msgstr "errore di sintassi: EOF non atteso"
+
+#: parse.y:5594
+msgid "syntax error"
+msgstr "errore di sintassi"
+
+#: parse.y:5656
+#, c-format
+msgid "Use \"%s\" to leave the shell.\n"
+msgstr "Usare \"%s\" per uscire dalla shell.\n"
+
+#: parse.y:5818
+msgid "unexpected EOF while looking for matching `)'"
+msgstr "EOF non atteso durante la ricerca di \")\""
+
+#: pcomplete.c:1030
+#, c-format
+msgid "completion: function `%s' not found"
+msgstr "completion: funzione \"%s\" non trovata"
+
+#: pcomplib.c:182
+#, c-format
+msgid "progcomp_insert: %s: NULL COMPSPEC"
+msgstr "progcomp_insert: %s: COMPSPEC NULL"
+
+#: print_cmd.c:296
+#, c-format
+msgid "print_command: bad connector `%d'"
+msgstr "print_command: connettore errato \"%d\""
+
+#: print_cmd.c:368
+#, c-format
+msgid "xtrace_set: %d: invalid file descriptor"
+msgstr "xtrace_set: %d: descrittore di file non valido"
+
+#: print_cmd.c:373
+msgid "xtrace_set: NULL file pointer"
+msgstr "xtrace_set: puntatore a file NULL"
+
+#: print_cmd.c:377
+#, c-format
+msgid "xtrace fd (%d) != fileno xtrace fp (%d)"
+msgstr "xtrace fd (%d) != numfile xtrace fp (%d)"
+
+#: print_cmd.c:1478
+#, c-format
+msgid "cprintf: `%c': invalid format character"
+msgstr "cprintf: \"%c\": carattere di formato non valido"
+
+#: redir.c:122
+msgid "file descriptor out of range"
+msgstr "descrittore di file fuori dell'intervallo"
+
+#: redir.c:178
+#, c-format
+msgid "%s: ambiguous redirect"
+msgstr "%s: redirezione ambigua"
+
+#: redir.c:182
+#, c-format
+msgid "%s: cannot overwrite existing file"
+msgstr "%s: impossibile sovrascrivere il file esistente"
+
+#: redir.c:187
+#, c-format
+msgid "%s: restricted: cannot redirect output"
+msgstr "%s: limitato: impossibile redirigere l'output"
+
+#: redir.c:192
+#, c-format
+msgid "cannot create temp file for here-document: %s"
+msgstr "impossibile creare un file temporaneo per here-document: %s"
+
+#: redir.c:196
+#, c-format
+msgid "%s: cannot assign fd to variable"
+msgstr "%s: impossibile assegnare fd a una variabile"
+
+#: redir.c:548
+msgid "/dev/(tcp|udp)/host/port not supported without networking"
+msgstr "/dev/(tcp|udp)/host/port non supportata senza rete"
+
+#: redir.c:818 redir.c:930 redir.c:993 redir.c:1136
+msgid "redirection error: cannot duplicate fd"
+msgstr "errore di reindirizzamento: impossibile duplicare fd"
+
+#: shell.c:333
+msgid "could not find /tmp, please create!"
+msgstr "impossibile trovare /tmp, è necessario crearla"
+
+#: shell.c:337
+msgid "/tmp must be a valid directory name"
+msgstr "/tmp deve essere un nome di directory valido"
+
+#: shell.c:884
+#, c-format
+msgid "%c%c: invalid option"
+msgstr "%c%c: opzione non valida"
+
+#: shell.c:1652
+msgid "I have no name!"
+msgstr "Manca il nome"
+
+#: shell.c:1795
+#, c-format
+msgid "GNU bash, version %s-(%s)\n"
+msgstr "GNU bash, versione %s-(%s)\n"
+
+#: shell.c:1796
+#, c-format
+msgid ""
+"Usage:\t%s [GNU long option] [option] ...\n"
+"\t%s [GNU long option] [option] script-file ...\n"
+msgstr ""
+"Uso:\t%s [opzione lunga GNU] [opzione] ...\n"
+"\t%s [opzione lunga GNU] [opzione] file-script ...\n"
+
+#: shell.c:1798
+msgid "GNU long options:\n"
+msgstr "Opzioni lunghe GNU:\n"
+
+#: shell.c:1802
+msgid "Shell options:\n"
+msgstr "Opzioni di shell:\n"
+
+#: shell.c:1803
+msgid "\t-irsD or -c command or -O shopt_option\t\t(invocation only)\n"
+msgstr "\t-irsD o -c comando o -O opzione_shopt\t\t(solo invocazione)\n"
+
+#: shell.c:1818
+#, c-format
+msgid "\t-%s or -o option\n"
+msgstr "\topzione -%s oppure -o\n"
+
+#: shell.c:1824
+#, c-format
+msgid "Type `%s -c \"help set\"' for more information about shell options.\n"
+msgstr "Digitare «%s -c \"help set\"» per ulteriori informazioni sulle opzioni di shell.\n"
+
+#: shell.c:1825
+#, c-format
+msgid "Type `%s -c help' for more information about shell builtin commands.\n"
+msgstr "Digitare \"%s -c help\" per ulteriori informazioni sui comandi interni di shell.\n"
+
+#: shell.c:1826
+#, c-format
+msgid "Use the `bashbug' command to report bugs.\n"
+msgstr "Usare il comando \"bashbug\" per segnalare i bug.\n"
+
+#: sig.c:638
+#, c-format
+msgid "sigprocmask: %d: invalid operation"
+msgstr "sigprocmask: %d: operazione non valida"
+
+#: siglist.c:48
+msgid "Bogus signal"
+msgstr "Segnale inesistente"
+
+#: siglist.c:51
+msgid "Hangup"
+msgstr "Chiusura"
+
+#: siglist.c:55
+msgid "Interrupt"
+msgstr "Interruzione"
+
+#: siglist.c:59
+msgid "Quit"
+msgstr "Uscita (con core dump)"
+
+#: siglist.c:63
+msgid "Illegal instruction"
+msgstr "Istruzione non consentita"
+
+#: siglist.c:67
+msgid "BPT trace/trap"
+msgstr "Rilevato trace/breakpoint"
+
+#: siglist.c:75
+msgid "ABORT instruction"
+msgstr "Istruzione ABORT"
+
+#: siglist.c:79
+msgid "EMT instruction"
+msgstr "Istruzione EMT"
+
+#: siglist.c:83
+msgid "Floating point exception"
+msgstr "Eccezione in virgola mobile"
+
+#: siglist.c:87
+msgid "Killed"
+msgstr "Ucciso"
+
+#: siglist.c:91
+msgid "Bus error"
+msgstr "Errore di bus"
+
+#: siglist.c:95
+msgid "Segmentation fault"
+msgstr "Errore di segmentazione"
+
+#: siglist.c:99
+msgid "Bad system call"
+msgstr "Chiamata di sistema errata"
+
+#: siglist.c:103
+msgid "Broken pipe"
+msgstr "Pipe interrotta"
+
+#: siglist.c:107
+msgid "Alarm clock"
+msgstr "Sveglia"
+
+#: siglist.c:111
+msgid "Terminated"
+msgstr "Terminato"
+
+#: siglist.c:115
+msgid "Urgent IO condition"
+msgstr "Condizione di I/O urgente"
+
+#: siglist.c:119
+msgid "Stopped (signal)"
+msgstr "Fermato (segnale)"
+
+#: siglist.c:127
+msgid "Continue"
+msgstr "Continuato"
+
+#: siglist.c:135
+msgid "Child death or stop"
+msgstr "Processo figlio concluso o fermato"
+
+#: siglist.c:139
+msgid "Stopped (tty input)"
+msgstr "Fermato (input da terminale)"
+
+#: siglist.c:143
+msgid "Stopped (tty output)"
+msgstr "Fermato (output da terminale)"
+
+#: siglist.c:147
+msgid "I/O ready"
+msgstr "I/O pronto"
+
+#: siglist.c:151
+msgid "CPU limit"
+msgstr "Limite di CPU"
+
+#: siglist.c:155
+msgid "File limit"
+msgstr "Limite di file"
+
+#: siglist.c:159
+msgid "Alarm (virtual)"
+msgstr "Timer (virtuale)"
+
+#: siglist.c:163
+msgid "Alarm (profile)"
+msgstr "Timer (profilo)"
+
+#: siglist.c:167
+msgid "Window changed"
+msgstr "Finestra modificata"
+
+#: siglist.c:171
+msgid "Record lock"
+msgstr "Blocco del record"
+
+#: siglist.c:175
+msgid "User signal 1"
+msgstr "Segnale 1 dell'utente"
+
+#: siglist.c:179
+msgid "User signal 2"
+msgstr "Segnale 2 dell'utente"
+
+#: siglist.c:183
+msgid "HFT input data pending"
+msgstr "Dati di input HTF in sospeso"
+
+#: siglist.c:187
+msgid "power failure imminent"
+msgstr "mancanza di alimentazione imminente"
+
+#: siglist.c:191
+msgid "system crash imminent"
+msgstr "crash di sistema imminente"
+
+#: siglist.c:195
+msgid "migrate process to another CPU"
+msgstr "processo spostato su un'altra CPU"
+
+#: siglist.c:199
+msgid "programming error"
+msgstr "errore di programmazione"
+
+#: siglist.c:203
+msgid "HFT monitor mode granted"
+msgstr "Modalità di monitoraggio HFT concessa"
+
+#: siglist.c:207
+msgid "HFT monitor mode retracted"
+msgstr "Modalità di monitoraggio HFT revocata"
+
+#: siglist.c:211
+msgid "HFT sound sequence has completed"
+msgstr "la sequenza sonora HFT è stata completata"
+
+#: siglist.c:215
+msgid "Information request"
+msgstr "Richiesta di informazioni"
+
+#: siglist.c:223
+msgid "Unknown Signal #"
+msgstr "Numero di segnale sconosciuto"
+
+#: siglist.c:225
+#, c-format
+msgid "Unknown Signal #%d"
+msgstr "Segnale sconosciuto n° %d"
+
+#: subst.c:1333 subst.c:1502
+#, c-format
+msgid "bad substitution: no closing `%s' in %s"
+msgstr "sostituzione errata: nessuna chiusura di \"%s\" in %s"
+
+#: subst.c:2795
+#, c-format
+msgid "%s: cannot assign list to array member"
+msgstr "%s: impossibile assegnare una lista a un membro di un array"
+
+#: subst.c:4979 subst.c:4995
+msgid "cannot make pipe for process substitution"
+msgstr "impossibile creare una pipe per la sostituzione del processo"
+
+#: subst.c:5027
+msgid "cannot make child for process substitution"
+msgstr "impossibile creare un figlio per la sostituzione del processo"
+
+#: subst.c:5072
+#, c-format
+msgid "cannot open named pipe %s for reading"
+msgstr "impossibile aprire la pipe con nome %s in lettura"
+
+#: subst.c:5074
+#, c-format
+msgid "cannot open named pipe %s for writing"
+msgstr "impossibile aprire la pipe con nome %s in scrittura"
+
+#: subst.c:5092
+#, c-format
+msgid "cannot duplicate named pipe %s as fd %d"
+msgstr "impossibile duplicare una pipe con nome %s come fd %d"
+
+#: subst.c:5284
+msgid "cannot make pipe for command substitution"
+msgstr "impossibile creare una pipe per la sostituzione del comando"
+
+#: subst.c:5322
+msgid "cannot make child for command substitution"
+msgstr "impossibile creare un figlio per la sostituzione del comando"
+
+#: subst.c:5339
+msgid "command_substitute: cannot duplicate pipe as fd 1"
+msgstr "command_substitute: impossibile duplicare la pipe come fd 1"
+
+#: subst.c:5859
+#, c-format
+msgid "%s: parameter null or not set"
+msgstr "%s: parametro nullo o non impostato"
+
+#: subst.c:6125 subst.c:6140
+#, c-format
+msgid "%s: substring expression < 0"
+msgstr "%s: expressione di sottostringa < 0"
+
+#: subst.c:7271
+#, c-format
+msgid "%s: bad substitution"
+msgstr "%s: sostituzione errata"
+
+#: subst.c:7347
+#, c-format
+msgid "$%s: cannot assign in this way"
+msgstr "$%s: impossibile assegnare in questo modo"
+
+#: subst.c:7684
+msgid "future versions of the shell will force evaluation as an arithmetic substitution"
+msgstr "le versioni future della shell forzeranno la valutazione come fosse una sostituzione aritmetica"
+
+#: subst.c:8149
+#, c-format
+msgid "bad substitution: no closing \"`\" in %s"
+msgstr "sostituzione errata: manca «\"» di chiusura in %s"
+
+#: subst.c:9036
+#, c-format
+msgid "no match: %s"
+msgstr "nessuna corrispondenza: %s"
+
+#: test.c:146
+msgid "argument expected"
+msgstr "atteso argomento"
+
+#: test.c:155
+#, c-format
+msgid "%s: integer expression expected"
+msgstr "%s: attesa espressione intera"
+
+#: test.c:263
+msgid "`)' expected"
+msgstr "atteso \")\""
+
+#: test.c:265
+#, c-format
+msgid "`)' expected, found %s"
+msgstr "atteso \")\", trovato %s"
+
+#: test.c:280 test.c:698 test.c:701
+#, c-format
+msgid "%s: unary operator expected"
+msgstr "%s: atteso operatore unario"
+
+#: test.c:449 test.c:741
+#, c-format
+msgid "%s: binary operator expected"
+msgstr "%s: atteso operatore binario"
+
+#: test.c:816
+msgid "missing `]'"
+msgstr "\"]\" mancante"
+
+#: trap.c:207
+msgid "invalid signal number"
+msgstr "numero di segnale non valido"
+
+#: trap.c:337
+#, c-format
+msgid "run_pending_traps: bad value in trap_list[%d]: %p"
+msgstr "run_pending_traps: valore errato in trap_list[%d]: %p"
+
+#: trap.c:341
+#, c-format
+msgid "run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"
+msgstr "run_pending_traps: il gestore dei segnali è SIG_DFL, viene inviato nuovamente %d (%s)"
+
+#: trap.c:393
+#, c-format
+msgid "trap_handler: bad signal %d"
+msgstr "trap_handler: segnale errato %d"
+
+#: variables.c:363
+#, c-format
+msgid "error importing function definition for `%s'"
+msgstr "errore nell'importazione della definizione di funzione per \"%s\""
+
+#: variables.c:755
+#, c-format
+msgid "shell level (%d) too high, resetting to 1"
+msgstr "livello di shell (%d) troppo alto, reimpostato a 1"
+
+#: variables.c:1932
+msgid "make_local_variable: no function context at current scope"
+msgstr "make_local_variable: nessun contesto di funzione nell'ambito corrente"
+
+#: variables.c:3182
+msgid "all_local_variables: no function context at current scope"
+msgstr "all_local_variables: nessun contesto di funzione nell'ambito corrente"
+
+#: variables.c:3427
+#, c-format
+msgid "%s has null exportstr"
+msgstr "%s ha exportstr null"
+
+#: variables.c:3432 variables.c:3441
+#, c-format
+msgid "invalid character %d in exportstr for %s"
+msgstr "carattere non valido %d in exportstr per %s"
+
+#: variables.c:3447
+#, c-format
+msgid "no `=' in exportstr for %s"
+msgstr "nessun \"=\" in exportstr per %s"
+
+#: variables.c:3891
+msgid "pop_var_context: head of shell_variables not a function context"
+msgstr "pop_var_context: la prima parte di shell_variables non è un contesto di funzione"
+
+#: variables.c:3904
+msgid "pop_var_context: no global_variables context"
+msgstr "pop_var_context: nessun contesto global_variables"
+
+#: variables.c:3978
+msgid "pop_scope: head of shell_variables not a temporary environment scope"
+msgstr "pop_scope: la prima parte di shell_variables non è un ambito temporaneo d'ambiente"
+
+#: variables.c:4786
+#, c-format
+msgid "%s: %s: cannot open as FILE"
+msgstr "%s: %s: impossibile aprire come FILE"
+
+#: variables.c:4791
+#, c-format
+msgid "%s: %s: invalid value for trace file descriptor"
+msgstr "%s: %s: valore non valido per il descrittore del file di traccia"
+
+#: version.c:46
+msgid "Copyright (C) 2011 Free Software Foundation, Inc."
+msgstr "Copyright © 2011 Free Software Foundation, Inc."
+
+#: version.c:47
+msgid "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
+msgstr "Licenza GPLv3+: GNU GPL versione 3 o successiva <http://gnu.org/licenses/gpl.html>\n"
+
+#: version.c:86 version2.c:83
+#, c-format
+msgid "GNU bash, version %s (%s)\n"
+msgstr "GNU bash, versione %s (%s)\n"
+
+#: version.c:91 version2.c:88
+#, c-format
+msgid "This is free software; you are free to change and redistribute it.\n"
+msgstr "Questo è software libero; è possibile modificarlo e ridistribuirlo.\n"
+
+#: version.c:92 version2.c:89
+#, c-format
+msgid "There is NO WARRANTY, to the extent permitted by law.\n"
+msgstr "Non c'è ALCUNA GARANZIA, nei limiti permessi dalla legge.\n"
+
+#: version2.c:86
+#, c-format
+msgid "Copyright (C) 2009 Free Software Foundation, Inc.\n"
+msgstr "Copyright © 2009 Free Software Foundation, Inc.\n"
+
+#: version2.c:87
+#, c-format
+msgid "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
+msgstr "Licenza GPLv2+: GNU GPL versione 2 o successive <http://gnu.org/licenses/gpl.html>\n"
+
+#: xmalloc.c:91
+#, c-format
+msgid "%s: cannot allocate %lu bytes (%lu bytes allocated)"
+msgstr "%s: impossibile allocare %lu byte (%lu byte allocati)"
+
+#: xmalloc.c:93
+#, c-format
+msgid "%s: cannot allocate %lu bytes"
+msgstr "%s: impossibile allocare %lu byte"
+
+#: xmalloc.c:163
+#, c-format
+msgid "%s: %s:%d: cannot allocate %lu bytes (%lu bytes allocated)"
+msgstr "%s: %s:%d: impossibile allocare %lu byte (%lu byte allocati)"
+
+#: xmalloc.c:165
+#, c-format
+msgid "%s: %s:%d: cannot allocate %lu bytes"
+msgstr "%s: %s:%d: impossibile allocare %lu byte"
+
+#: builtins.c:43
+msgid "alias [-p] [name[=value] ... ]"
+msgstr "alias [-p] [nome[=valore] ... ]"
+
+#: builtins.c:47
+msgid "unalias [-a] name [name ...]"
+msgstr "unalias [-a] nome [nome ...]"
+
+#: builtins.c:51
+msgid "bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]"
+msgstr "bind [-lpvsPVS] [-m mappatura] [-f nomefile] [-q nome] [-u nome] [-r seqtasti] [-x seqtasti:comando-shell] [seqtasti:funzione-readline o comando-readline]"
+
+#: builtins.c:54
+msgid "break [n]"
+msgstr "break [n]"
+
+#: builtins.c:56
+msgid "continue [n]"
+msgstr "continue [n]"
+
+#: builtins.c:58
+msgid "builtin [shell-builtin [arg ...]]"
+msgstr "builtin [comandoint-shell [arg ...]]"
+
+#: builtins.c:61
+msgid "caller [expr]"
+msgstr "caller [espr]"
+
+#: builtins.c:64
+msgid "cd [-L|[-P [-e]]] [dir]"
+msgstr "cd [-L|[-P [-e]]] [dir]"
+
+#: builtins.c:66
+msgid "pwd [-LP]"
+msgstr "pwd [-LP]"
+
+#: builtins.c:68
+msgid ":"
+msgstr ":"
+
+#: builtins.c:70
+msgid "true"
+msgstr "vero"
+
+#: builtins.c:72
+msgid "false"
+msgstr "falso"
+
+#: builtins.c:74
+msgid "command [-pVv] command [arg ...]"
+msgstr "command [-pVv] comando [arg ...]"
+
+#: builtins.c:76
+msgid "declare [-aAfFgilrtux] [-p] [name[=value] ...]"
+msgstr "declare [-aAfFgilrtux] [-p] [nome[=valore] ...]"
+
+#: builtins.c:78
+msgid "typeset [-aAfFgilrtux] [-p] name[=value] ..."
+msgstr "typeset [-aAfFgilrtux] [-p] nome[=valore] ..."
+
+#: builtins.c:80
+msgid "local [option] name[=value] ..."
+msgstr "local [opzione] nome[=valore] ..."
+
+#: builtins.c:83
+msgid "echo [-neE] [arg ...]"
+msgstr "echo [-neE] [arg ...]"
+
+#: builtins.c:87
+msgid "echo [-n] [arg ...]"
+msgstr "echo [-n] [arg ...]"
+
+#: builtins.c:90
+msgid "enable [-a] [-dnps] [-f filename] [name ...]"
+msgstr "enable [-a] [-dnps] [-f nome_file] [nome ...]"
+
+#: builtins.c:92
+msgid "eval [arg ...]"
+msgstr "eval [arg ...]"
+
+#: builtins.c:94
+msgid "getopts optstring name [arg]"
+msgstr "getopts stringaopz nome [arg]"
+
+#: builtins.c:96
+msgid "exec [-cl] [-a name] [command [arguments ...]] [redirection ...]"
+msgstr "exec [-cl] [-a nome] [comando [argomenti ...]] [redirezione ...]"
+
+#: builtins.c:98
+msgid "exit [n]"
+msgstr "exit [n]"
+
+#: builtins.c:100
+msgid "logout [n]"
+msgstr "logout [n]"
+
+#: builtins.c:103
+msgid "fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]"
+msgstr "fc [-e ename] [-lnr] [primo] [ultimo] oppure fc -s [pat=rep] [comando]"
+
+#: builtins.c:107
+msgid "fg [job_spec]"
+msgstr "fg [spec_job]"
+
+#: builtins.c:111
+msgid "bg [job_spec ...]"
+msgstr "bg [spec_job ...]"
+
+#: builtins.c:114
+msgid "hash [-lr] [-p pathname] [-dt] [name ...]"
+msgstr "hash [-lr] [-p nomepercorso] [-dt] [nome ...]"
+
+#: builtins.c:117
+msgid "help [-dms] [pattern ...]"
+msgstr "help [-dms] [modello ...]"
+
+#: builtins.c:121
+msgid "history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]"
+msgstr "history [-c] [-d offset] [n] oppure history -anrw [nomefile] oppure history -ps arg [arg...]"
+
+#: builtins.c:125
+msgid "jobs [-lnprs] [jobspec ...] or jobs -x command [args]"
+msgstr "jobs [-lnprs] [specjob ...] oppure jobs -x comando [argomenti]"
+
+#: builtins.c:129
+msgid "disown [-h] [-ar] [jobspec ...]"
+msgstr "disown [-h] [-ar] [specjob ...]"
+
+#: builtins.c:132
+msgid "kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]"
+msgstr "kill [-s specsegn | -n numsegn | -specsegn] pid | specjob ... oppure kill -l [specsegn]"
+
+#: builtins.c:134
+msgid "let arg [arg ...]"
+msgstr "let arg [arg ...]"
+
+#: builtins.c:136
+msgid "read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]"
+msgstr "read [-ers] [-a array] [-d delim] [-i testo] [-n ncaratt] [-N ncaratt] [-p stringa] [-t secondi] [-u fd] [nome ...]"
+
+#: builtins.c:138
+msgid "return [n]"
+msgstr "return [n]"
+
+#: builtins.c:140
+msgid "set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]"
+msgstr "set [-abefhkmnptuvxBCHP] [-o nome-opzione] [--] [arg ...]"
+
+#: builtins.c:142
+msgid "unset [-f] [-v] [name ...]"
+msgstr "unset [-f] [-v] [nome ...]"
+
+#: builtins.c:144
+msgid "export [-fn] [name[=value] ...] or export -p"
+msgstr "export [-fn] [nome[=valore] ...] oppure export -p"
+
+#: builtins.c:146
+msgid "readonly [-aAf] [name[=value] ...] or readonly -p"
+msgstr "readonly [-aAf] [nome[=valore] ...] oppure readonly -p"
+
+#: builtins.c:148
+msgid "shift [n]"
+msgstr "shift [n]"
+
+#: builtins.c:150
+msgid "source filename [arguments]"
+msgstr "source nomefile [argomenti]"
+
+#: builtins.c:152
+msgid ". filename [arguments]"
+msgstr ". nomefile [argomenti]"
+
+#: builtins.c:155
+msgid "suspend [-f]"
+msgstr "suspend [-f]"
+
+#: builtins.c:158
+msgid "test [expr]"
+msgstr "test [espr]"
+
+#: builtins.c:160
+msgid "[ arg... ]"
+msgstr "[ arg... ]"
+
+#: builtins.c:162
+msgid "times"
+msgstr "times"
+
+#: builtins.c:164
+msgid "trap [-lp] [[arg] signal_spec ...]"
+msgstr "trap [-lp] [[arg] spec_segnale ...]"
+
+#: builtins.c:166
+msgid "type [-afptP] name [name ...]"
+msgstr "type [-afptP] nome [nome ...]"
+
+#: builtins.c:169
+msgid "ulimit [-SHacdefilmnpqrstuvx] [limit]"
+msgstr "ulimit [-SHacdefilmnpqrstuvx] [limite]"
+
+#: builtins.c:172
+msgid "umask [-p] [-S] [mode]"
+msgstr "umask [-p] [-S] [modo]"
+
+#: builtins.c:175
+msgid "wait [id]"
+msgstr "wait [id]"
+
+#: builtins.c:179
+msgid "wait [pid]"
+msgstr "wait [pid]"
+
+#: builtins.c:182
+msgid "for NAME [in WORDS ... ] ; do COMMANDS; done"
+msgstr "for NOME [in PAROLE ... ] ; do COMANDI; done"
+
+#: builtins.c:184
+msgid "for (( exp1; exp2; exp3 )); do COMMANDS; done"
+msgstr "for (( espr1; espr2; espr3 )); do COMANDI; done"
+
+#: builtins.c:186
+msgid "select NAME [in WORDS ... ;] do COMMANDS; done"
+msgstr "select NOME [in PAROLE ... ;] do COMANDI; done"
+
+#: builtins.c:188
+msgid "time [-p] pipeline"
+msgstr "time [-p] pipeline"
+
+#: builtins.c:190
+msgid "case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac"
+msgstr "case PAROLA in [MODELLO [| MODELLO]...) COMANDI ;;]... esac"
+
+#: builtins.c:192
+msgid "if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi"
+msgstr "if COMANDI; then COMANDI; [ elif COMANDI; then COMANDI; ]... [ else COMANDI; ] fi"
+
+#: builtins.c:194
+msgid "while COMMANDS; do COMMANDS; done"
+msgstr "while COMANDI; do COMANDI; done"
+
+#: builtins.c:196
+msgid "until COMMANDS; do COMMANDS; done"
+msgstr "until COMANDI; do COMANDI; done"
+
+#: builtins.c:198
+msgid "coproc [NAME] command [redirections]"
+msgstr "coproc [NOME] comando [redirezioni]"
+
+#: builtins.c:200
+msgid "function name { COMMANDS ; } or name () { COMMANDS ; }"
+msgstr "function name { COMANDI ; } oppure name () { COMANDI ; }"
+
+#: builtins.c:202
+msgid "{ COMMANDS ; }"
+msgstr "{ COMANDI ; }"
+
+#: builtins.c:204
+msgid "job_spec [&]"
+msgstr "spec_job [&]"
+
+#: builtins.c:206
+msgid "(( expression ))"
+msgstr "(( espressione ))"
+
+#: builtins.c:208
+msgid "[[ expression ]]"
+msgstr "[[ espressione ]]"
+
+#: builtins.c:210
+msgid "variables - Names and meanings of some shell variables"
+msgstr "variabili - nomi e significati di alcune variabili di shell"
+
+#: builtins.c:213
+msgid "pushd [-n] [+N | -N | dir]"
+msgstr "pushd [-n] [+N | -N | dir]"
+
+#: builtins.c:217
+msgid "popd [-n] [+N | -N]"
+msgstr "popd [-n] [+N | -N]"
+
+#: builtins.c:221
+msgid "dirs [-clpv] [+N] [-N]"
+msgstr "dirs [-clpv] [+N] [-N]"
+
+#: builtins.c:224
+msgid "shopt [-pqsu] [-o] [optname ...]"
+msgstr "shopt [-pqsu] [-o] [nomeopz ...]"
+
+#: builtins.c:226
+msgid "printf [-v var] format [arguments]"
+msgstr "printf [-v var] formato [argomenti]"
+
+#: builtins.c:229
+msgid "complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]"
+msgstr "complete [-abcdefgjksuv] [-pr] [-DE] [-o opzione] [-A azione] [-G modglob] [-W elencoparole]  [-F funzione] [-C comando] [-X modfiltro] [-P prefisso] [-S suffisso] [nome ...]"
+
+#: builtins.c:233
+msgid "compgen [-abcdefgjksuv] [-o option]  [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]"
+msgstr "compgen [-abcdefgjksuv] [-o opzione]  [-A azione] [-G modglob] [-W elencoparole]  [-F funzione] [-C comando] [-X modfiltro] [-P prefisso] [-S suffisso] [parola]"
+
+#: builtins.c:237
+msgid "compopt [-o|+o option] [-DE] [name ...]"
+msgstr "compopt [-o|+o opzione] [-DE] [nome ...]"
+
+#: builtins.c:240
+msgid "mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]"
+msgstr "mapfile [-n numero] [-O origine] [-s numero] [-t] [-u fd] [-C callback] [-c quantità] [array]"
+
+#: builtins.c:242
+msgid "readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]"
+msgstr "readarray [-n numero] [-O origine] [-s numero] [-t] [-u fd] [-C callback] [-c quantità] [array]"
+
+#: builtins.c:254
+msgid ""
+"Define or display aliases.\n"
+"    \n"
+"    Without arguments, `alias' prints the list of aliases in the reusable\n"
+"    form `alias NAME=VALUE' on standard output.\n"
+"    \n"
+"    Otherwise, an alias is defined for each NAME whose VALUE is given.\n"
+"    A trailing space in VALUE causes the next word to be checked for\n"
+"    alias substitution when the alias is expanded.\n"
+"    \n"
+"    Options:\n"
+"      -p\tPrint all defined aliases in a reusable format\n"
+"    \n"
+"    Exit Status:\n"
+"    alias returns true unless a NAME is supplied for which no alias has been\n"
+"    defined."
+msgstr ""
+"Definisce o visualizza alias.\n"
+"    \n"
+"    Senza argomenti, \"alias\" stampa l'elenco degli alias nella forma\n"
+"    riusabile \"alias NOME=VALORE\" sullo standard output.\n"
+"    \n"
+"    Altrimenti, un alias è definito per ogni NOME a cui è fornito un VALORE.\n"
+"    Uno spazio finale in VALORE determina un controllo della parola successiva\n"
+"    che andrà a sostituire l'alias quando viene espanso.\n"
+"    \n"
+"    Opzioni:\n"
+"      -p\tStampa tutti gli alias definiti in un formato riusabile\n"
+"    \n"
+"    Stato di uscita:\n"
+"    alias restituisce vero a meno che non venga fornito un NOME per il quale\n"
+"    non sia stato definito alcun alias."
+
+#: builtins.c:276
+msgid ""
+"Remove each NAME from the list of defined aliases.\n"
+"    \n"
+"    Options:\n"
+"      -a\tremove all alias definitions.\n"
+"    \n"
+"    Return success unless a NAME is not an existing alias."
+msgstr ""
+"Rimuove ogni NOME dall'elenco degli alias definiti.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a\tRimuove tutte le definizioni di alias.\n"
+"    \n"
+"    Restituisce successo a meno che NOME non sia un alias esistente."
+
+#: builtins.c:289
+msgid ""
+"Set Readline key bindings and variables.\n"
+"    \n"
+"    Bind a key sequence to a Readline function or a macro, or set a\n"
+"    Readline variable.  The non-option argument syntax is equivalent to\n"
+"    that found in ~/.inputrc, but must be passed as a single argument:\n"
+"    e.g., bind '\"\\C-x\\C-r\": re-read-init-file'.\n"
+"    \n"
+"    Options:\n"
+"      -m  keymap         Use KEYMAP as the keymap for the duration of this\n"
+"                         command.  Acceptable keymap names are emacs,\n"
+"                         emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,\n"
+"                         vi-command, and vi-insert.\n"
+"      -l                 List names of functions.\n"
+"      -P                 List function names and bindings.\n"
+"      -p                 List functions and bindings in a form that can be\n"
+"                         reused as input.\n"
+"      -S                 List key sequences that invoke macros and their values\n"
+"      -s                 List key sequences that invoke macros and their values\n"
+"                         in a form that can be reused as input.\n"
+"      -V                 List variable names and values\n"
+"      -v                 List variable names and values in a form that can\n"
+"                         be reused as input.\n"
+"      -q  function-name  Query about which keys invoke the named function.\n"
+"      -u  function-name  Unbind all keys which are bound to the named function.\n"
+"      -r  keyseq         Remove the binding for KEYSEQ.\n"
+"      -f  filename       Read key bindings from FILENAME.\n"
+"      -x  keyseq:shell-command\tCause SHELL-COMMAND to be executed when\n"
+"    \t\t\t\tKEYSEQ is entered.\n"
+"    \n"
+"    Exit Status:\n"
+"    bind returns 0 unless an unrecognized option is given or an error occurs."
+msgstr ""
+"Imposta le associazioni di tasti e le variabili di Readline.\n"
+"    \n"
+"    Associa una sequenza di tasti a una funzione o a una macro Readline, oppure imposta una\n"
+"    variabile di Readline.  La sintassi di argomento senza opzione è equivalente a quella\n"
+"    trovata in ~/.inputrc, ma deve essere passata come singolo argomento:\n"
+"    es., bind '\"\\C-x\\C-r\": ri-leggi-file-init'.\n"
+"    \n"
+"    Opzioni:\n"
+"      -m  mappatura      Usa MAPPATURA come la mappatura per la durata di questo\n"
+"                         comando.  Nomi accettabili per la mappatura sono emacs,\n"
+"                         emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,\n"
+"                         vi-command e vi-insert.\n"
+"      -l                 Elenca i nomi delle funzioni.\n"
+"      -P                 Elenca i nomi delle funzioni e le associazioni.\n"
+"      -p                 Elenca le funzioni e le associazioni in una forma che\n"
+"                         possa essere riusata come input.\n"
+"      -S                 Elenca le sequenze di tasti che invocano le macro e i loro valori.\n"
+"      -s                 Elenca le sequenze di tasti che invocano le macro e i loro valori\n"
+"                         in una forma che possa essere riusata come input.\n"
+"      -V                 Elenca i nomi e i valori delle variabili.\n"
+"      -v                 Elenca i nomi e i valori delle variabili in una forma che possa\n"
+"                         essere riusata come input.\n"
+"      -q  nome-funzione  Identifica il tasto che invoca la funzione nominata.\n"
+"      -u  nome-funzione  Rimuove l'associazione tra la funzione nominata e tutti i tasti associati.\n"
+"      -r  seqtasti       Rimuove l'associazione per la SEQTASTI.\n"
+"      -f  nomefile       Legge le associazioni di tasti da NOMEFILE.\n"
+"      -x  seqtasti:comando-shell\tEsegue il COMANDO-SHELL quando viene inserita\n"
+"    \t\t\t\t\tla SEQTASTI.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    bind restituisce 0 a meno che non sia fornita una opzione non riconosciuta o si riscontri un errore."
+
+#: builtins.c:326
+msgid ""
+"Exit for, while, or until loops.\n"
+"    \n"
+"    Exit a FOR, WHILE or UNTIL loop.  If N is specified, break N enclosing\n"
+"    loops.\n"
+"    \n"
+"    Exit Status:\n"
+"    The exit status is 0 unless N is not greater than or equal to 1."
+msgstr ""
+"Esce da cicli for, while o until.\n"
+"    \n"
+"    Esce da un ciclo FOR, WHILE o UNTIL. Se è specificato N, interrompe N cicli\n"
+"    racchiusi.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Lo stato di uscita è 0 a meno che N non sia maggiore o uguale a 1."
+
+#: builtins.c:338
+msgid ""
+"Resume for, while, or until loops.\n"
+"    \n"
+"    Resumes the next iteration of the enclosing FOR, WHILE or UNTIL loop.\n"
+"    If N is specified, resumes the Nth enclosing loop.\n"
+"    \n"
+"    Exit Status:\n"
+"    The exit status is 0 unless N is not greater than or equal to 1."
+msgstr ""
+"Riprende cicli for, while o until.\n"
+"    \n"
+"    Riprende l'iterazione successiva del ciclo chiuso FOR, WHILE o UNTIL.\n"
+"    Se è specificato N, riprende l'N-simo ciclo chiuso.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Lo stato di uscita è 0 a meno che N non sia maggiore o uguale a 1."
+
+#: builtins.c:350
+msgid ""
+"Execute shell builtins.\n"
+"    \n"
+"    Execute SHELL-BUILTIN with arguments ARGs without performing command\n"
+"    lookup.  This is useful when you wish to reimplement a shell builtin\n"
+"    as a shell function, but need to execute the builtin within the function.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the exit status of SHELL-BUILTIN, or false if SHELL-BUILTIN is\n"
+"    not a shell builtin.."
+msgstr ""
+"Esegue comandi interni di shell.\n"
+"    \n"
+"    Esegue il COMINTERNO-SHELL con ARGOMENTI senza portare a termine una ricerca\n"
+"    comandi. Ciò è utile quando si desidera reimplementare un comando interno come una\n"
+"    funzione di shell, ma è necessario eseguire il comando all'interno della funzione.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato di uscita del COMINTERNO-SHELL, o falso se il COMINTERNO-SHELL\n"
+"    non è un comando interno di shell."
+
+#: builtins.c:365
+msgid ""
+"Return the context of the current subroutine call.\n"
+"    \n"
+"    Without EXPR, returns \"$line $filename\".  With EXPR, returns\n"
+"    \"$line $subroutine $filename\"; this extra information can be used to\n"
+"    provide a stack trace.\n"
+"    \n"
+"    The value of EXPR indicates how many call frames to go back before the\n"
+"    current one; the top frame is frame 0.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns 0 unless the shell is not executing a shell function or EXPR\n"
+"    is invalid."
+msgstr ""
+"Restituisce il contesto della chiamata alla subroutine corrente.\n"
+"    \n"
+"    Senza ESPR, restituisce \"$riga $nomefile\".  Con ESPR, restituisce\n"
+"    \"$riga $subroutine $nomefile\"; questa informazione aggiuntiva può essere usata\n"
+"    per fornire uno stack trace.\n"
+"    \n"
+"    Il valore dell'ESPR indica di quanti frame di chiamata tornare indietro rispetto\n"
+"    a quello attuale; in cima c'è il frame 0.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce 0 a meno che non sia in esecuzione una funzione di shell o che l'ESPR\n"
+"    non sia valida."
+
+#: builtins.c:383
+msgid ""
+"Change the shell working directory.\n"
+"    \n"
+"    Change the current directory to DIR.  The default DIR is the value of the\n"
+"    HOME shell variable.\n"
+"    \n"
+"    The variable CDPATH defines the search path for the directory containing\n"
+"    DIR.  Alternative directory names in CDPATH are separated by a colon (:).\n"
+"    A null directory name is the same as the current directory.  If DIR begins\n"
+"    with a slash (/), then CDPATH is not used.\n"
+"    \n"
+"    If the directory is not found, and the shell option `cdable_vars' is set,\n"
+"    the word is assumed to be  a variable name.  If that variable has a value,\n"
+"    its value is used for DIR.\n"
+"    \n"
+"    Options:\n"
+"        -L\tforce symbolic links to be followed\n"
+"        -P\tuse the physical directory structure without following symbolic\n"
+"    \tlinks\n"
+"        -e\tif the -P option is supplied, and the current working directory\n"
+"    \tcannot be determined successfully, exit with a non-zero status\n"
+"    \n"
+"    The default is to follow symbolic links, as if `-L' were specified.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns 0 if the directory is changed, and if $PWD is set successfully when\n"
+"    -P is used; non-zero otherwise."
+msgstr ""
+"Cambia la directory di lavoro della shell.\n"
+"    \n"
+"    Cambia la directory corrente a DIR. La DIR predefinita è il valore della variabile\n"
+"    HOME della shell.\n"
+"    \n"
+"    La variabile CDPATH definisce il percorso di ricerca per la directory che contiene\n"
+"    DIR. I nomi di directory alternative in CDPATH sono separati da un due punti (:).\n"
+"    Una nome nullo di directory corrisponde alla directory corrente.  Se DIR inizia\n"
+"    con uno slash (/), CDPATH non viene usato.\n"
+"    \n"
+"    Se la directory non viene trovata e l'opzione di shell \"cdable_vars\" è impostata,\n"
+"    si assume che la parola sia un nome di variabile. Se questa variabile ha un valore,\n"
+"    viene usato per DIR.\n"
+"    \n"
+"    Opzioni:\n"
+"        -L\tForza a seguire i collegamenti simbolici\n"
+"        -P\tUsa la struttura fisica della directory senza seguire i collegamenti\n"
+"    \tsimbolici\n"
+"        -e\tSe viene fornita l'opzione -P e non può essere determinata con successo\n"
+"    \tla directory di lavoro corrente, esce con uno stato diverso da zero\n"
+"    \n"
+"    Il valore predefinito è seguire i collegamenti simbolici, come se fosse specificato \"-L\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce 0 se viene cambiata la directory o se $PWD è impostata con successo quando\n"
+"    viene usato -P; altrimenti un valore diverso da zero."
+
+#: builtins.c:414
+msgid ""
+"Print the name of the current working directory.\n"
+"    \n"
+"    Options:\n"
+"      -L\tprint the value of $PWD if it names the current working\n"
+"    \tdirectory\n"
+"      -P\tprint the physical directory, without any symbolic links\n"
+"    \n"
+"    By default, `pwd' behaves as if `-L' were specified.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns 0 unless an invalid option is given or the current directory\n"
+"    cannot be read."
+msgstr ""
+"Stampa il nome della directory di lavoro corrente.\n"
+"    \n"
+"    Opzioni:\n"
+"      -L\tStampa il valore di $PWD se contiene il nome della directory\n"
+"    \tdi lavoro corrente\n"
+"      -P\tStampa la directory fisica senza alcun collegamento simbolico\n"
+"    \n"
+"    In maniera predefinita \"pwd\" si comporta come se fosse specificato \"-L\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce 0 a meno che non venga fornita una opzione non valida o che la\n"
+"    directory corrente non possa essere letta."
+
+#: builtins.c:431
+msgid ""
+"Null command.\n"
+"    \n"
+"    No effect; the command does nothing.\n"
+"    \n"
+"    Exit Status:\n"
+"    Always succeeds."
+msgstr ""
+"Comando nullo.\n"
+"    \n"
+"    Nessun effetto; il comando non esegue nulla.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    ha sempre successo."
+
+#: builtins.c:442
+msgid ""
+"Return a successful result.\n"
+"    \n"
+"    Exit Status:\n"
+"    Always succeeds."
+msgstr ""
+"Restituisce successo come risultato.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    ha sempre successo."
+
+#: builtins.c:451
+msgid ""
+"Return an unsuccessful result.\n"
+"    \n"
+"    Exit Status:\n"
+"    Always fails."
+msgstr ""
+"Restituisce un risultato di insuccesso.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Sempre un insuccesso."
+
+#: builtins.c:460
+msgid ""
+"Execute a simple command or display information about commands.\n"
+"    \n"
+"    Runs COMMAND with ARGS suppressing  shell function lookup, or display\n"
+"    information about the specified COMMANDs.  Can be used to invoke commands\n"
+"    on disk when a function with the same name exists.\n"
+"    \n"
+"    Options:\n"
+"      -p\tuse a default value for PATH that is guaranteed to find all of\n"
+"    \tthe standard utilities\n"
+"      -v\tprint a description of COMMAND similar to the `type' builtin\n"
+"      -V\tprint a more verbose description of each COMMAND\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns exit status of COMMAND, or failure if COMMAND is not found."
+msgstr ""
+"Esegue un comando semplice o visualizza informazioni sui comandi.\n"
+"    \n"
+"    Esegue il COMANDO con gli ARGOMENTI ignorando la ricerca delle funzioni di shell o\n"
+"    visualizza informazioni sui COMANDI specificati.  Può essere usato per invocare comandi\n"
+"    sul disco quando esiste una funzione con lo stesso nome.\n"
+"    \n"
+"    Opzioni:\n"
+"      -p\tUsa un valore predefinito per il PERCORSO che garantisce che vengano trovate tutte\n"
+"    \tle utilità standard\n"
+"      -v\tStampa una descrizione del COMANDO simile al comando interno \"type\"\n"
+"      -V\tStampa una descrizione più prolissa di ciascun COMANDO\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato di uscita del COMANDO o insuccesso se il COMANDO non viene trovato."
+
+#: builtins.c:479
+msgid ""
+"Set variable values and attributes.\n"
+"    \n"
+"    Declare variables and give them attributes.  If no NAMEs are given,\n"
+"    display the attributes and values of all variables.\n"
+"    \n"
+"    Options:\n"
+"      -f\trestrict action or display to function names and definitions\n"
+"      -F\trestrict display to function names only (plus line number and\n"
+"    \tsource file when debugging)\n"
+"      -g\tcreate global variables when used in a shell function; otherwise\n"
+"    \tignored\n"
+"      -p\tdisplay the attributes and value of each NAME\n"
+"    \n"
+"    Options which set attributes:\n"
+"      -a\tto make NAMEs indexed arrays (if supported)\n"
+"      -A\tto make NAMEs associative arrays (if supported)\n"
+"      -i\tto make NAMEs have the `integer' attribute\n"
+"      -l\tto convert NAMEs to lower case on assignment\n"
+"      -r\tto make NAMEs readonly\n"
+"      -t\tto make NAMEs have the `trace' attribute\n"
+"      -u\tto convert NAMEs to upper case on assignment\n"
+"      -x\tto make NAMEs export\n"
+"    \n"
+"    Using `+' instead of `-' turns off the given attribute.\n"
+"    \n"
+"    Variables with the integer attribute have arithmetic evaluation (see\n"
+"    the `let' command) performed when the variable is assigned a value.\n"
+"    \n"
+"    When used in a function, `declare' makes NAMEs local, as with the `local'\n"
+"    command.  The `-g' option suppresses this behavior.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is supplied or an error occurs."
+msgstr ""
+"Imposta i valori e gli attributi delle variabili.\n"
+"    \n"
+"    Dichiara le variabili e fornisce loro attributi.  Se non vengono forniti NOMI,\n"
+"    visualizza gli attributi e i valori di tutte le variabili.\n"
+"    \n"
+"    Opzioni:\n"
+"      -f\tLimita l'azione o la visualizzazione ai nomi e alle definizioni di funzione\n"
+"      -F\tLimita la visualizzazione ai soli nomi di funzione (più numero di riga e\n"
+"    \tfile sorgente durante il debug)\n"
+"      -g\tCrea variabili globali quando usato in una funzione di shell; altrimenti\n"
+"    \tè ignorato\n"
+"      -p\tVisualizza gli attributi e i valori di ciascun NOME\n"
+"    \n"
+"    Opzioni che impostano gli attributi:\n"
+"      -a\tRende i NOMI array indicizzati (se supportata)\n"
+"      -A\tRende i NOMI array associativi (se supportata)\n"
+"      -i\tFornisce ai NOMI l'attributo \"integer\"\n"
+"      -l\tConverte i NOMI in lettere minuscole in fase di assegnazione\n"
+"      -r\tImposta i NOMI in sola lettura\n"
+"      -t\tFornisce ai NOMI l'attributo \"trace\"\n"
+"      -u\tConverte i NOMI in lettere maiuscole in fase di assegnazione\n"
+"      -x\tImposta i NOMI come esportabili\n"
+"    \n"
+"    Usando \"+\" al posto di \"-\" disattiva l'attributo fornito.\n"
+"    \n"
+"    Le variabili con attributo intero vengono valutate aritmeticamente (vedere\n"
+"    il comando \"let\") quando alla variabile è assegnato un valore.\n"
+"    \n"
+"    Quando viene usato in una funzione, \"declare\" rende locali i NOMI, come con\n"
+"    il comando \"local\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o si riscontri un errore."
+
+#: builtins.c:517
+msgid ""
+"Set variable values and attributes.\n"
+"    \n"
+"    Obsolete.  See `help declare'."
+msgstr ""
+"Imposta valori e attributi di variabile.\n"
+"    \n"
+"    Obsoleto. Vedere \"help declare\"."
+
+#: builtins.c:525
+msgid ""
+"Define local variables.\n"
+"    \n"
+"    Create a local variable called NAME, and give it VALUE.  OPTION can\n"
+"    be any option accepted by `declare'.\n"
+"    \n"
+"    Local variables can only be used within a function; they are visible\n"
+"    only to the function where they are defined and its children.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is supplied, an error occurs,\n"
+"    or the shell is not executing a function."
+msgstr ""
+"Definisce variabili locali.\n"
+"    \n"
+"    Crea una variabile locale chiamata NOME fornendogli un VALORE. L'OPZIONE può\n"
+"    essere una qualsiasi opzione accettata da \"declare\".\n"
+"    \n"
+"    Le variabili locali possono essere usate solo all'interno di una funzione; sono\n"
+"    visibili solo alla funzione nella quale sono definite e ai relativi figli.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita un'opzione non valida, non si\n"
+"    riscontri un errore o la shell non stia eseguendo una funzione."
+
+#: builtins.c:542
+msgid ""
+"Write arguments to the standard output.\n"
+"    \n"
+"    Display the ARGs on the standard output followed by a newline.\n"
+"    \n"
+"    Options:\n"
+"      -n\tdo not append a newline\n"
+"      -e\tenable interpretation of the following backslash escapes\n"
+"      -E\texplicitly suppress interpretation of backslash escapes\n"
+"    \n"
+"    `echo' interprets the following backslash-escaped characters:\n"
+"      \\a\talert (bell)\n"
+"      \\b\tbackspace\n"
+"      \\c\tsuppress further output\n"
+"      \\e\tescape character\n"
+"      \\f\tform feed\n"
+"      \\n\tnew line\n"
+"      \\r\tcarriage return\n"
+"      \\t\thorizontal tab\n"
+"      \\v\tvertical tab\n"
+"      \\\\\tbackslash\n"
+"      \\0nnn\tthe character whose ASCII code is NNN (octal).  NNN can be\n"
+"    \t0 to 3 octal digits\n"
+"      \\xHH\tthe eight-bit character whose value is HH (hexadecimal).  HH\n"
+"    \tcan be one or two hex digits\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless a write error occurs."
+msgstr ""
+"Scrive argomenti sullo standard output.\n"
+"    \n"
+"    Visualizza gli ARG sullo standard output seguiti da un ritorno a capo.\n"
+"    \n"
+"    Opzioni:\n"
+"      -n\tNon accoda un carattere di ritorno a capo\n"
+"      -e\tAbilita l'interpretazione dei seguenti caratteri backslash di escape\n"
+"      -E\tDisabilita esplicitamente l'interpretazione dei caratteri backslash di escape\n"
+"    \n"
+"    \"echo\" interpreta i seguenti caratteri backslash di escape:\n"
+"      \\a\tavviso (campanello)\n"
+"      \\b\tbackspace\n"
+"      \\c\telimina ulteriore output\n"
+"      \\e\tcarattere di escape\n"
+"      \\f\tavanzamento pagina\n"
+"      \\n\tritorno a capo\n"
+"      \\r\tritorno carrello\n"
+"      \\t\ttabulazione orizzontale\n"
+"      \\v\ttabulazione verticale\n"
+"      \\\\\tbackslash\n"
+"      \\0nnn\til carattere il cui codice ASCII è NNN (ottale).  NNN può avere\n"
+"    \tda 0 a 3 cifre ottali\n"
+"      \\xHH\til carattere otto bit il cui valore è HH (esadecimale).  HH può\n"
+"    \tavere una o due cifre esadecimali\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga riscontrato un errore di scrittura."
+
+#: builtins.c:576
+msgid ""
+"Write arguments to the standard output.\n"
+"    \n"
+"    Display the ARGs on the standard output followed by a newline.\n"
+"    \n"
+"    Options:\n"
+"      -n\tdo not append a newline\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless a write error occurs."
+msgstr ""
+"Scrive argomenti sullo standard output.\n"
+"    \n"
+"    Visualizza gli ARG sullo standard output seguiti da un ritorno a capo.\n"
+"    \n"
+"    Opzioni:\n"
+"      -n\tNon accoda un ritorno a capo\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga riscontrato un errore di scrittura."
+
+#: builtins.c:591
+msgid ""
+"Enable and disable shell builtins.\n"
+"    \n"
+"    Enables and disables builtin shell commands.  Disabling allows you to\n"
+"    execute a disk command which has the same name as a shell builtin\n"
+"    without using a full pathname.\n"
+"    \n"
+"    Options:\n"
+"      -a\tprint a list of builtins showing whether or not each is enabled\n"
+"      -n\tdisable each NAME or display a list of disabled builtins\n"
+"      -p\tprint the list of builtins in a reusable format\n"
+"      -s\tprint only the names of Posix `special' builtins\n"
+"    \n"
+"    Options controlling dynamic loading:\n"
+"      -f\tLoad builtin NAME from shared object FILENAME\n"
+"      -d\tRemove a builtin loaded with -f\n"
+"    \n"
+"    Without options, each NAME is enabled.\n"
+"    \n"
+"    To use the `test' found in $PATH instead of the shell builtin\n"
+"    version, type `enable -n test'.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless NAME is not a shell builtin or an error occurs."
+msgstr ""
+"Abilita o disabilita comandi interni di shell.\n"
+"    \n"
+"    Abilita o disabilita comandi interni di shell. La disabilitazione permette di\n"
+"    eseguire un comando su disco che abbia lo stesso nome del comando interno\n"
+"    di shell senza dover usare un nome di percorso completo.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a\tStampa un elenco di comandi interni mostrando se sono abilitati o meno\n"
+"      -n\tDisabilita ogni NOME o visualizza un elenco di comandi interni disabilitati\n"
+"      -p\tStampa l'elenco dei comandi interni in un formato riusabile\n"
+"      -s\tStampa solo i nomi dei comandi interni \"speciali\" Posix\n"
+"    \n"
+"    Opzioni che controllano il caricamento dinamico:\n"
+"      -f\tCarica il comando interno NOME dall'oggetto condiviso NOMEFILE\n"
+"      -d\tRimuove un comando interno caricato con -f\n"
+"    \n"
+"    Senza opzioni viene abilitato ogni NOME.\n"
+"    \n"
+"    Per usare il comando \"test\" trovato in $PATH invece di quello interno della\n"
+"    shell, digitare \"enable -n test\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che NOME non sia un comando interno di shell o si riscontri un errore."
+
+#: builtins.c:619
+msgid ""
+"Execute arguments as a shell command.\n"
+"    \n"
+"    Combine ARGs into a single string, use the result as input to the shell,\n"
+"    and execute the resulting commands.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns exit status of command or success if command is null."
+msgstr ""
+"Esegue argomenti come un comando di shell.\n"
+"    \n"
+"    Combina gli ARGOMENTI dentro una singola stringa usando il risultato\n"
+"    come input per la shell ed esegue i comandi risultanti.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato di uscita del comando o successo se il comando è nullo."
+
+#: builtins.c:631
+msgid ""
+"Parse option arguments.\n"
+"    \n"
+"    Getopts is used by shell procedures to parse positional parameters\n"
+"    as options.\n"
+"    \n"
+"    OPTSTRING contains the option letters to be recognized; if a letter\n"
+"    is followed by a colon, the option is expected to have an argument,\n"
+"    which should be separated from it by white space.\n"
+"    \n"
+"    Each time it is invoked, getopts will place the next option in the\n"
+"    shell variable $name, initializing name if it does not exist, and\n"
+"    the index of the next argument to be processed into the shell\n"
+"    variable OPTIND.  OPTIND is initialized to 1 each time the shell or\n"
+"    a shell script is invoked.  When an option requires an argument,\n"
+"    getopts places that argument into the shell variable OPTARG.\n"
+"    \n"
+"    getopts reports errors in one of two ways.  If the first character\n"
+"    of OPTSTRING is a colon, getopts uses silent error reporting.  In\n"
+"    this mode, no error messages are printed.  If an invalid option is\n"
+"    seen, getopts places the option character found into OPTARG.  If a\n"
+"    required argument is not found, getopts places a ':' into NAME and\n"
+"    sets OPTARG to the option character found.  If getopts is not in\n"
+"    silent mode, and an invalid option is seen, getopts places '?' into\n"
+"    NAME and unsets OPTARG.  If a required argument is not found, a '?'\n"
+"    is placed in NAME, OPTARG is unset, and a diagnostic message is\n"
+"    printed.\n"
+"    \n"
+"    If the shell variable OPTERR has the value 0, getopts disables the\n"
+"    printing of error messages, even if the first character of\n"
+"    OPTSTRING is not a colon.  OPTERR has the value 1 by default.\n"
+"    \n"
+"    Getopts normally parses the positional parameters ($0 - $9), but if\n"
+"    more arguments are given, they are parsed instead.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success if an option is found; fails if the end of options is\n"
+"    encountered or an error occurs."
+msgstr ""
+"Analizza gli argomenti di opzione.\n"
+"    \n"
+"    Getopts è usato dalle procedure di shell per analizzare i parametri\n"
+"    posizionali come opzioni.\n"
+"    \n"
+"    STRINGAOPZ contiene le lettere di opzione da riconoscere; se una lettera\n"
+"    è seguita da un due punti, ci si aspetta che l'opzione abbia un argomento,\n"
+"    che dovrebbe essere separato da uno spazio.\n"
+"    \n"
+"    Ogni volta che viene evocato getopts posiziona l'opzione successiva\n"
+"    nella variabile di shell $nome inizializzando il nome, se non esiste,\n"
+"    e l'indice dell'argomento successivo da elaborare nella variabile di\n"
+"    shell OPTIND.  OPTIND è inizializzata a 1 ogni volta che viene invocata\n"
+"    la shell o uno script di shell.  Quando una opzione richiede un argomento,\n"
+"    getopts posiziona tale argomento nella variabile di shell OPTARG.\n"
+"    \n"
+"    getopts riporta gli errori in uno o due modi.  Se il primo carattere della\n"
+"    STRINGAOPZ è un due punti, riporta gli errori in silenzio.  In questa\n"
+"    modalità non vengono stampati messaggi di errore.  Se viene riscontrata una\n"
+"    opzione non valida, getopts posiziona il carattere di opzione trovato in\n"
+"    ARGOPZ.  Se un argomento richiesto non viene trovato, getopts posiziona\n"
+"    un \":\" nel NOME e imposta ARGOPZ al carattere di opzione trovato.  Se getopts\n"
+"    non è in modalità silenziosa e viene riscontrata una opzione non valida, getopts\n"
+"    posiziona \"?\" nel NOME e azzera ARGOPZ.  Se un argomento richiesto non viene\n"
+"    trovato, viene posizionato un \"?\" nel NOME, ARGOPZ viene azzerato e viene stampato\n"
+"    un messaggio diagnostico.\n"
+"    \n"
+"    Se il valore della variabile di shell ERROPZ è pari a 0, getopts disabilita\n"
+"    la stampa dei messaggi di errore anche se il primo carattere della STRINGAOPZ\n"
+"    non è un due punti.  Il valore predefinito di ERROPZ è pari a 1.\n"
+"    \n"
+"    Getopts normalmente analizza i parametri posizionali ($0 - $9), ma se\n"
+"    vengono forniti più argomenti, vengono analizzati questi ultimi.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo se viene trovata una opzione, insuccesso se viene raggiunta\n"
+"    la fine delle opzioni o viene riscontrato un errore."
+
+#: builtins.c:673
+msgid ""
+"Replace the shell with the given command.\n"
+"    \n"
+"    Execute COMMAND, replacing this shell with the specified program.\n"
+"    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,\n"
+"    any redirections take effect in the current shell.\n"
+"    \n"
+"    Options:\n"
+"      -a name\tpass NAME as the zeroth argument to COMMAND\n"
+"      -c\t\texecute COMMAND with an empty environment\n"
+"      -l\t\tplace a dash in the zeroth argument to COMMAND\n"
+"    \n"
+"    If the command cannot be executed, a non-interactive shell exits, unless\n"
+"    the shell option `execfail' is set.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless COMMAND is not found or a redirection error occurs."
+msgstr ""
+"Sostituisce la shell con il comando fornito.\n"
+"    \n"
+"    Esegue il COMANDO, sostituendo questa shell con il programma specificato.\n"
+"    Gli ARGOMENTI diventano gli argomenti per il COMANDO. Se il COMANDO non è specificato,\n"
+"    ogni redirezione avrà effetto nella shell corrente.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a nome\tPassa NOME come l'argomento zero per il COMANDO\n"
+"      -c\t\tEsegue il COMANDO con un ambiente vuoto\n"
+"      -l\t\tPosiziona un trattino nell'argomento zero per il COMANDO\n"
+"    \n"
+"    Se il comando non può essere eseguito una shell non interattiva esce, a meno che\n"
+"    non venga impostata l'opzione di shell \"execfail\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia trovato il COMANDO o si riscontri un errore di ridirezione."
+
+#: builtins.c:694
+msgid ""
+"Exit the shell.\n"
+"    \n"
+"    Exits the shell with a status of N.  If N is omitted, the exit status\n"
+"    is that of the last command executed."
+msgstr ""
+"Esce dalla shell.\n"
+"    \n"
+"    Esce dalla shell con uno stato N. Se N è omesso lo stato di uscita\n"
+"    è quello dell'ultimo comando eseguito."
+
+#: builtins.c:703
+msgid ""
+"Exit a login shell.\n"
+"    \n"
+"    Exits a login shell with exit status N.  Returns an error if not executed\n"
+"    in a login shell."
+msgstr ""
+"Esce da una shell di login.\n"
+"    \n"
+"    Esce da una shell di login con stato di uscita N. Restituisce un errore se non eseguito\n"
+"    in una shell di login."
+
+#: builtins.c:713
+msgid ""
+"Display or execute commands from the history list.\n"
+"    \n"
+"    fc is used to list or edit and re-execute commands from the history list.\n"
+"    FIRST and LAST can be numbers specifying the range, or FIRST can be a\n"
+"    string, which means the most recent command beginning with that\n"
+"    string.\n"
+"    \n"
+"    Options:\n"
+"      -e ENAME\tselect which editor to use.  Default is FCEDIT, then EDITOR,\n"
+"    \t\tthen vi\n"
+"      -l \tlist lines instead of editing\n"
+"      -n\tomit line numbers when listing\n"
+"      -r\treverse the order of the lines (newest listed first)\n"
+"    \n"
+"    With the `fc -s [pat=rep ...] [command]' format, COMMAND is\n"
+"    re-executed after the substitution OLD=NEW is performed.\n"
+"    \n"
+"    A useful alias to use with this is r='fc -s', so that typing `r cc'\n"
+"    runs the last command beginning with `cc' and typing `r' re-executes\n"
+"    the last command.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success or status of executed command; non-zero if an error occurs."
+msgstr ""
+"Visualizza o esegue comandi dall'elenco della cronologia.\n"
+"    \n"
+"    fc è usato per elencare, modificare e rieseguire comandi dall'elenco della cronologia.\n"
+"    PRIMO e ULTIMO possono essere numeri che specificano l'intervallo oppure PRIMO può\n"
+"    essere una stringa, nel qual caso significa il comando più recente che inizia con\n"
+"    quella stringa.\n"
+"    \n"
+"    Opzioni:\n"
+"      -e EDITOR\tSeleziona l'editor da usare.  Il predefinito è FCEDIT, quindi EDITOR,\n"
+"    \t\tinfine vi\n"
+"      -l \tElenca le righe invece di modificarle\n"
+"      -n\tOmette i numeri di riga nell'elencare i comandi\n"
+"      -r\tInverte l'ordine delle righe (elenca prima le più recenti)\n"
+"    \n"
+"    Con il formato \"fc -s [pat=rep ...] [comando]\", il COMANDO è\n"
+"    rieseguito dopo aver effettuato la sostituzione VECCHIO=NUOVO.\n"
+"    \n"
+"    Un alias utile da usare insieme è r=\"fc -s\", in modo che digitando \"r cc\"\n"
+"    viene eseguito l'ultimo comando che inizia con \"cc\" e digitando \"r\" riesegue\n"
+"    l'ultimo comando.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo o lo stato del comando eseguito, non zero se si riscontra un errore."
+
+#: builtins.c:743
+msgid ""
+"Move job to the foreground.\n"
+"    \n"
+"    Place the job identified by JOB_SPEC in the foreground, making it the\n"
+"    current job.  If JOB_SPEC is not present, the shell's notion of the\n"
+"    current job is used.\n"
+"    \n"
+"    Exit Status:\n"
+"    Status of command placed in foreground, or failure if an error occurs."
+msgstr ""
+"Sposta i job in primo piano.\n"
+"    \n"
+"    Mette il job identificato da SPEC_JOB in primo piano, rendendolo il\n"
+"    job corrente.  Se SPEC_JOB non è presente, viene usata la nozione di\n"
+"    job corrente della shell.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Stato del comando messo in primo piano, o insuccesso se si riscontra un errore."
+
+#: builtins.c:758
+msgid ""
+"Move jobs to the background.\n"
+"    \n"
+"    Place the jobs identified by each JOB_SPEC in the background, as if they\n"
+"    had been started with `&'.  If JOB_SPEC is not present, the shell's notion\n"
+"    of the current job is used.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless job control is not enabled or an error occurs."
+msgstr ""
+"Sposta i job sullo sfondo.\n"
+"    \n"
+"    Mette il  jobs identificato da ogni SPEC_JOB sullo sfondo, come se fossero\n"
+"    stati avviati con \"&\". Se SPEC_JOB non è presente, viene usata la nozione\n"
+"    di job corrente della shell.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che il controllo dei job non sia abilitato o si riscontri un errore."
+
+#: builtins.c:772
+msgid ""
+"Remember or display program locations.\n"
+"    \n"
+"    Determine and remember the full pathname of each command NAME.  If\n"
+"    no arguments are given, information about remembered commands is displayed.\n"
+"    \n"
+"    Options:\n"
+"      -d\t\tforget the remembered location of each NAME\n"
+"      -l\t\tdisplay in a format that may be reused as input\n"
+"      -p pathname\tuse PATHNAME is the full pathname of NAME\n"
+"      -r\t\tforget all remembered locations\n"
+"      -t\t\tprint the remembered location of each NAME, preceding\n"
+"    \t\teach location with the corresponding NAME if multiple\n"
+"    \t\tNAMEs are given\n"
+"    Arguments:\n"
+"      NAME\t\tEach NAME is searched for in $PATH and added to the list\n"
+"    \t\tof remembered commands.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless NAME is not found or an invalid option is given."
+msgstr ""
+"Ricorda o visualizza le posizioni dei programmi.\n"
+"    \n"
+"    Determina e ricorda il nome completo di percorso per ogni comando NOME. Se non\n"
+"    viene fornito alcun argomento, sono visualizzate le informazioni sui comandi memorizzati.\n"
+"    \n"
+"    Opzioni:\n"
+"      -d\t\tDimentica la posizione memorizzata di ogni NOME\n"
+"      -l\t\tVisualizza in un formato che può essere riusato come input\n"
+"      -p nomepercorso\tUsa NOMEPERCORSO come il nome completo di percorso per NOME\n"
+"      -r\t\tDimentica tutte le posizioni memorizzate\n"
+"      -t\t\tStampa la posizione memorizzata di ogni NOME, facendo\n"
+"    \t\tprecedere ciascuna posizione con il NOME corrispondente se vengono\n"
+"    \t\tforniti valori NOME multipli\n"
+"    Argomenti:\n"
+"      NOME\t\tOgni NOME è ricercato in $PATH e aggiunto all'elenco\n"
+"    \t\tdei comandi memorizzati.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia trovato NOME o sia fornita una opzione non valida."
+
+#: builtins.c:797
+msgid ""
+"Display information about builtin commands.\n"
+"    \n"
+"    Displays brief summaries of builtin commands.  If PATTERN is\n"
+"    specified, gives detailed help on all commands matching PATTERN,\n"
+"    otherwise the list of help topics is printed.\n"
+"    \n"
+"    Options:\n"
+"      -d\toutput short description for each topic\n"
+"      -m\tdisplay usage in pseudo-manpage format\n"
+"      -s\toutput only a short usage synopsis for each topic matching\n"
+"    \tPATTERN\n"
+"    \n"
+"    Arguments:\n"
+"      PATTERN\tPattern specifiying a help topic\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless PATTERN is not found or an invalid option is given."
+msgstr ""
+"Visualizza informazioni sui comandi interni.\n"
+"    \n"
+"    Visualizza un breve sommario dei comandi interni. Se viene specificato il\n"
+"    MODELLO fornisce un aiuto dettagliato su tutti i comandi corrispondenti al\n"
+"    MODELLO, altrimenti viene stampato l'elenco degli argomenti di aiuto.\n"
+"    \n"
+"    Opzioni:\n"
+"      -d\tVisualizza una breve descrizione per ciascun argomento\n"
+"      -m\tVisualizza l'uso in formato pseudo manpage\n"
+"      -s\tVisualizza solo una breve sintassi sull'uso per ciascun argomento che\n"
+"    \tcorrisponde al MODELLO\n"
+"    \n"
+"    Argomenti:\n"
+"      MODELLO\tModello che specifica un argomento di aiuto\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga trovato il MODELLO o sia fornita una opzione non valida."
+
+#: builtins.c:821
+msgid ""
+"Display or manipulate the history list.\n"
+"    \n"
+"    Display the history list with line numbers, prefixing each modified\n"
+"    entry with a `*'.  An argument of N lists only the last N entries.\n"
+"    \n"
+"    Options:\n"
+"      -c\tclear the history list by deleting all of the entries\n"
+"      -d offset\tdelete the history entry at offset OFFSET.\n"
+"    \n"
+"      -a\tappend history lines from this session to the history file\n"
+"      -n\tread all history lines not already read from the history file\n"
+"      -r\tread the history file and append the contents to the history\n"
+"    \tlist\n"
+"      -w\twrite the current history to the history file\n"
+"    \tand append them to the history list\n"
+"    \n"
+"      -p\tperform history expansion on each ARG and display the result\n"
+"    \twithout storing it in the history list\n"
+"      -s\tappend the ARGs to the history list as a single entry\n"
+"    \n"
+"    If FILENAME is given, it is used as the history file.  Otherwise,\n"
+"    if $HISTFILE has a value, that is used, else ~/.bash_history.\n"
+"    \n"
+"    If the $HISTTIMEFORMAT variable is set and not null, its value is used\n"
+"    as a format string for strftime(3) to print the time stamp associated\n"
+"    with each displayed history entry.  No time stamps are printed otherwise.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or an error occurs."
+msgstr ""
+"Visualizza o manipola l'elenco della cronologia.\n"
+"    \n"
+"    Visualizza l'elenco della cronologia con i numeri di riga, aggiungendo a ciascuna voce\n"
+"    modificata il prefisso \"*\".  Un argomento pari a N elenca solo le ultime N voci.\n"
+"    \n"
+"    Opzioni:\n"
+"      -c\t\tPulisce la cronologia eliminando tutte le voci\n"
+"      -d posizione\tElimina la voce della cronologia alla posizione OFFSET.\n"
+"    \n"
+"      -a\t\tAccoda righe al file della cronologia relative alla sessione attuale\n"
+"      -n\t\tLegge tutte le righe non ancora lette dal file della cronologia\n"
+"      -r\t\tLegge il file della cronologia e ne accoda il contenuto all'elenco della\n"
+"    \t\tcronologia\n"
+"      -w\t\tScrive la cronologia corrente nel file della cronologia\n"
+"    \t\te ne accoda le voci all'elenco della cronologia\n"
+"    \n"
+"      -p\t\tEffettua l'espansione della cronologia su ciascun ARG e visualizza il\n"
+"    \t\trisultato senza memorizzarlo nell'elenco della cronologia\n"
+"      -s\t\tAccoda gli ARG all'elenco della cronologia come una voce singola\n"
+"    \n"
+"    Se viene fornito il NOMEFILE, viene usato come file della cronologia.  Altrimenti,\n"
+"    se presente, viene usato il valore di $HISTFILE, in alternativa ~/.bash_history.\n"
+"    \n"
+"    Se la variabile $HISTTIMEFORMAT è impostata e non è nulla, il suo valore viene usato\n"
+"    come una stringa di formato per strftime(3) per stampare l'orario associato a ciascuna\n"
+"    voce di cronologia visualizzata.  Altrimenti non viene stampato alcun orario.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o si riscontri un errore."
+
+#: builtins.c:857
+msgid ""
+"Display status of jobs.\n"
+"    \n"
+"    Lists the active jobs.  JOBSPEC restricts output to that job.\n"
+"    Without options, the status of all active jobs is displayed.\n"
+"    \n"
+"    Options:\n"
+"      -l\tlists process IDs in addition to the normal information\n"
+"      -n\tlist only processes that have changed status since the last\n"
+"    \tnotification\n"
+"      -p\tlists process IDs only\n"
+"      -r\trestrict output to running jobs\n"
+"      -s\trestrict output to stopped jobs\n"
+"    \n"
+"    If -x is supplied, COMMAND is run after all job specifications that\n"
+"    appear in ARGS have been replaced with the process ID of that job's\n"
+"    process group leader.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or an error occurs.\n"
+"    If -x is used, returns the exit status of COMMAND."
+msgstr ""
+"Visualizza lo stato dei job.\n"
+"    \n"
+"    Elenca i job attivi. SPECJOB limita l'output a quei job.\n"
+"    Senza opzioni, è visualizzato lo stato di tutti i job attivi.\n"
+"    \n"
+"    Opzioni:\n"
+"      -l\tElenca gli ID dei processi in aggiunta alle normali informazioni\n"
+"      -n\tElenca solo i processi che hanno cambiato stato dall'ultima\n"
+"    \tnotifica\n"
+"      -p\tElenca solo l'ID dei processi\n"
+"      -r\tLimita l'output ai job in esecuzione\n"
+"      -s\tLimita l'output ai processi fermati\n"
+"    \n"
+"    Se viene fornito -x, il COMANDO è eseguito dopo che tutte le specifiche dei job che\n"
+"    appaiono in ARGOMENTI sono state rimpiazzate con l'ID del processo leader nel gruppo di\n"
+"    quel job.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o si riscontri un errore.\n"
+"    Se viene usato -x, restituisce lo stato di uscita del COMANDO."
+
+#: builtins.c:884
+msgid ""
+"Remove jobs from current shell.\n"
+"    \n"
+"    Removes each JOBSPEC argument from the table of active jobs.  Without\n"
+"    any JOBSPECs, the shell uses its notion of the current job.\n"
+"    \n"
+"    Options:\n"
+"      -a\tremove all jobs if JOBSPEC is not supplied\n"
+"      -h\tmark each JOBSPEC so that SIGHUP is not sent to the job if the\n"
+"    \tshell receives a SIGHUP\n"
+"      -r\tremove only running jobs\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option or JOBSPEC is given."
+msgstr ""
+"Rimuove job dalla shell corrente.\n"
+"    \n"
+"    Rimuove ciascun argomento SPECJOB dalla tabella dei job attivi.  Senza alcun\n"
+"    SPECJOB, la shell usa la sua nozione del job corrente.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a\tRimuove tutti i job se non viene fornito uno SPECJOB\n"
+"      -h\tMarca ciascun SPECJOB in modo che non venga inviato un SIGHUP al job se la\n"
+"    \tshell lo riceve\n"
+"      -r\tRimuove solo i job in esecuzione\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita una opzione non valida o uno SPECJOB."
+
+#: builtins.c:903
+msgid ""
+"Send a signal to a job.\n"
+"    \n"
+"    Send the processes identified by PID or JOBSPEC the signal named by\n"
+"    SIGSPEC or SIGNUM.  If neither SIGSPEC nor SIGNUM is present, then\n"
+"    SIGTERM is assumed.\n"
+"    \n"
+"    Options:\n"
+"      -s sig\tSIG is a signal name\n"
+"      -n sig\tSIG is a signal number\n"
+"      -l\tlist the signal names; if arguments follow `-l' they are\n"
+"    \tassumed to be signal numbers for which names should be listed\n"
+"    \n"
+"    Kill is a shell builtin for two reasons: it allows job IDs to be used\n"
+"    instead of process IDs, and allows processes to be killed if the limit\n"
+"    on processes that you can create is reached.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or an error occurs."
+msgstr ""
+"Invia un segnale a un job.\n"
+"    \n"
+"    Invia il segnale chiamato dallo SPECSEGN o dal NUMSEGN ai processi identificati\n"
+"    dal PID o dallo SPECJOB.  Se non è presente né lo SPECSEGN né il NUMSEGN, viene\n"
+"    allora considerato SIGTERM.\n"
+"    \n"
+"    Opzioni:\n"
+"      -s segn\tSEGN è il nome di un segnale\n"
+"      -n segn\tSEGN è il numero di un segnale\n"
+"      -l\tElenca i nomi dei segnali; Se ci sono argomenti dopo \"-l\"\n"
+"    \tvengono valutati come numeri di segnale di cui elencare i nomi\n"
+"    \n"
+"    Kill è un comando interno di shell per due ragioni: permette di usare gli ID\n"
+"    dei job invece degli ID dei processi e permette di uccidere quei processi che\n"
+"    abbiano raggiunto un numero limite prefissato di processi creabili.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o si riscontri un errore."
+
+#: builtins.c:926
+msgid ""
+"Evaluate arithmetic expressions.\n"
+"    \n"
+"    Evaluate each ARG as an arithmetic expression.  Evaluation is done in\n"
+"    fixed-width integers with no check for overflow, though division by 0\n"
+"    is trapped and flagged as an error.  The following list of operators is\n"
+"    grouped into levels of equal-precedence operators.  The levels are listed\n"
+"    in order of decreasing precedence.\n"
+"    \n"
+"    \tid++, id--\tvariable post-increment, post-decrement\n"
+"    \t++id, --id\tvariable pre-increment, pre-decrement\n"
+"    \t-, +\t\tunary minus, plus\n"
+"    \t!, ~\t\tlogical and bitwise negation\n"
+"    \t**\t\texponentiation\n"
+"    \t*, /, %\t\tmultiplication, division, remainder\n"
+"    \t+, -\t\taddition, subtraction\n"
+"    \t<<, >>\t\tleft and right bitwise shifts\n"
+"    \t<=, >=, <, >\tcomparison\n"
+"    \t==, !=\t\tequality, inequality\n"
+"    \t&\t\tbitwise AND\n"
+"    \t^\t\tbitwise XOR\n"
+"    \t|\t\tbitwise OR\n"
+"    \t&&\t\tlogical AND\n"
+"    \t||\t\tlogical OR\n"
+"    \texpr ? expr : expr\n"
+"    \t\t\tconditional operator\n"
+"    \t=, *=, /=, %=,\n"
+"    \t+=, -=, <<=, >>=,\n"
+"    \t&=, ^=, |=\tassignment\n"
+"    \n"
+"    Shell variables are allowed as operands.  The name of the variable\n"
+"    is replaced by its value (coerced to a fixed-width integer) within\n"
+"    an expression.  The variable need not have its integer attribute\n"
+"    turned on to be used in an expression.\n"
+"    \n"
+"    Operators are evaluated in order of precedence.  Sub-expressions in\n"
+"    parentheses are evaluated first and may override the precedence\n"
+"    rules above.\n"
+"    \n"
+"    Exit Status:\n"
+"    If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise."
+msgstr ""
+"Valuta espressioni aritmetiche.\n"
+"    \n"
+"    Valuta ciascun ARG come una espressione aritmetica.  La valutazione è effettuata con\n"
+"    interi a larghezza fissa senza alcun controllo per overflow, sebbene la divisione\n"
+"    per 0 sia bloccata e contrassegnata come un errore.  Il seguente elenco di operatori\n"
+"    è raggruppato per livelli di operatore di uguale precedenza.  I livelli sono elencati\n"
+"    in ordine di precedenza decrescente.\n"
+"    \n"
+"    \tid++, id--\tIncremento e decremento successivo di variabile\n"
+"    \t++id, --id\tIncremento e decremento precedente di variabile\n"
+"    \t-, +\t\tMeno e più unari\n"
+"    \t!, ~\t\tNegazione logica e bit a bit\n"
+"    \t**\t\tEsponenziazione\n"
+"    \t*, /, %\t\tMoltiplicazione, divisione, resto\n"
+"    \t+, -\t\tAddizione, sottrazione\n"
+"    \t<<, >>\t\tScorrimento bit a bit sinistro e destro\n"
+"    \t<=, >=, <, >\tComparazione\n"
+"    \t==, !=\t\tUguaglianza, disuguaglianza\n"
+"    \t&\t\tAND bit a bit\n"
+"    \t^\t\tXOR bit a bit\n"
+"    \t|\t\tOR bit a bit\n"
+"    \t&&\t\tAND logico\n"
+"    \t||\t\tOR logico\n"
+"    \tespr ? espr : espr\n"
+"    \t\t\tOperatore condizionale\n"
+"    \t=, *=, /=, %=,\n"
+"    \t+=, -=, <<=, >>=,\n"
+"    \t&=, ^=, |=\tAssegnazione\n"
+"    \n"
+"    Le variabili di shell sono ammesse come operandi.  Il nome della variabile è\n"
+"    sostituito dal suo valore (forzato a un intero a larghezza fissa) all'interno\n"
+"    di una espressione.  Non è necessario che la variabile abbia il proprio attributo\n"
+"    intero abilitato per essere usata in una espressione.\n"
+"    \n"
+"    Gli operatori sono valutati in ordine di precedenza.  Le sottoespressioni tra\n"
+"    parentesi sono valutate per prime e possono avere la precedenza sulle regole\n"
+"    sopradescritte.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Se l'ultimo ARG viene valutato pari a 0 restituisce 1, altrimenti restituisce 0."
+
+#: builtins.c:971
+msgid ""
+"Read a line from the standard input and split it into fields.\n"
+"    \n"
+"    Reads a single line from the standard input, or from file descriptor FD\n"
+"    if the -u option is supplied.  The line is split into fields as with word\n"
+"    splitting, and the first word is assigned to the first NAME, the second\n"
+"    word to the second NAME, and so on, with any leftover words assigned to\n"
+"    the last NAME.  Only the characters found in $IFS are recognized as word\n"
+"    delimiters.\n"
+"    \n"
+"    If no NAMEs are supplied, the line read is stored in the REPLY variable.\n"
+"    \n"
+"    Options:\n"
+"      -a array\tassign the words read to sequential indices of the array\n"
+"    \t\tvariable ARRAY, starting at zero\n"
+"      -d delim\tcontinue until the first character of DELIM is read, rather\n"
+"    \t\tthan newline\n"
+"      -e\t\tuse Readline to obtain the line in an interactive shell\n"
+"      -i text\tUse TEXT as the initial text for Readline\n"
+"      -n nchars\treturn after reading NCHARS characters rather than waiting\n"
+"    \t\tfor a newline, but honor a delimiter if fewer than NCHARS\n"
+"    \t\tcharacters are read before the delimiter\n"
+"      -N nchars\treturn only after reading exactly NCHARS characters, unless\n"
+"    \t\tEOF is encountered or read times out, ignoring any delimiter\n"
+"      -p prompt\toutput the string PROMPT without a trailing newline before\n"
+"    \t\tattempting to read\n"
+"      -r\t\tdo not allow backslashes to escape any characters\n"
+"      -s\t\tdo not echo input coming from a terminal\n"
+"      -t timeout\ttime out and return failure if a complete line of input is\n"
+"    \t\tnot read withint TIMEOUT seconds.  The value of the TMOUT\n"
+"    \t\tvariable is the default timeout.  TIMEOUT may be a\n"
+"    \t\tfractional number.  If TIMEOUT is 0, read returns success only\n"
+"    \t\tif input is available on the specified file descriptor.  The\n"
+"    \t\texit status is greater than 128 if the timeout is exceeded\n"
+"      -u fd\t\tread from file descriptor FD instead of the standard input\n"
+"    \n"
+"    Exit Status:\n"
+"    The return code is zero, unless end-of-file is encountered, read times out,\n"
+"    or an invalid file descriptor is supplied as the argument to -u."
+msgstr ""
+"Legge una riga dallo standard input e la divide in campi.\n"
+"    \n"
+"    Legge una singola riga dallo standard input o, se viene fornita l'opzione -u,\n"
+"    dal descrittore di file FD.  La riga è divisa in campi corrispondenti a\n"
+"    parole dove la prima parola è assegnata al primo NOME, la seconda parola\n"
+"    al secondo NOME e così via, con ciascuna parola rimanente assegnata al\n"
+"    corrispondente ultimo NOME.  Sono riconosciuti come delimitatori di parola\n"
+"    solo quelli presenti in $IFS.\n"
+"    \n"
+"    Se non viene fornito alcun NOME, la riga letta è memorizzata nella variabile REPLY.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a array\tAssegna le parole lette agli indici sequenziali della variabile\n"
+"    \t\tdi ARRAY, iniziando da zero\n"
+"      -d delim\tContinua fino alla lettura del primo carattere di DELIM, invece\n"
+"    \t\tdi un ritorno a capo \n"
+"      -e\t\tUsa Readline per ottenere la riga in una shell interattiva\n"
+"      -i testo\tUsa TESTO come testo iniziale per Readline\n"
+"      -n ncarat\tRitorna dopo la lettura di NCARAT caratteri invece di attendere\n"
+"    \t\tun a capo, ma rispetta un delimitatore se vengono letti meno di\n"
+"    \t\tNCARAT caratteri prima del delimitatore stesso\n"
+"      -N ncarat\tRitorna solo dopo la lettura di NCARAT caratteri esatti, a meno che non si\n"
+"    \t\triscontri un EOF o un time out di lettura, ignorando qualsiasi delimitatore\n"
+"      -p stringa\tVisualizza la stringa PROMPT senza un a capo finale prima\n"
+"    \t\tdel tentativo di lettura\n"
+"      -r\t\tNon ammette backslash per fare l'escape dei caratteri\n"
+"      -s\t\tNon fa l'echo dell'input proveniente da un terminale\n"
+"      -t secondi\tVa in timeout e restituisce insuccesso se non viene letta una\n"
+"    \t\triga di input completa entro i SECONDI forniti.  Il valore della\n"
+"    \t\tvariabile TMOUT è il timeout predefinito.  SECONDI può essere\n"
+"    \t\tuna frazione.  Se SECONDI è pari a 0, la lettura restituisce successo\n"
+"    \t\tsolo se l'input è disponibile sul descrittore di file specificato.  Lo\n"
+"    \t\tstato di uscita è maggiore di 128 se viene superato il timeout\n"
+"      -u fd\t\tLegge dal descrittore di file FD invece che dallo standard input\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Il codice restituito è zero a meno che non sia riscontrato un EOF, un timeout in lettura\n"
+"    o venga fornito un descrittore di file non valido come argomento per -u."
+
+#: builtins.c:1014
+msgid ""
+"Return from a shell function.\n"
+"    \n"
+"    Causes a function or sourced script to exit with the return value\n"
+"    specified by N.  If N is omitted, the return status is that of the\n"
+"    last command executed within the function or script.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns N, or failure if the shell is not executing a function or script."
+msgstr ""
+"Ritorna da una funzione di shell.\n"
+"    \n"
+"    Causa l'uscita da una funzione o da uno script sorgente con il valore di\n"
+"    ritorno specificato da N.  Se N è omesso, lo stato di ritorno è quello\n"
+"    dell'ultimo comando eseguito all'interno della funzione o dello script.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce N, oppure insuccesso se la shell non sta eseguendo una funzione o uno script."
+
+#: builtins.c:1027
+msgid ""
+"Set or unset values of shell options and positional parameters.\n"
+"    \n"
+"    Change the value of shell attributes and positional parameters, or\n"
+"    display the names and values of shell variables.\n"
+"    \n"
+"    Options:\n"
+"      -a  Mark variables which are modified or created for export.\n"
+"      -b  Notify of job termination immediately.\n"
+"      -e  Exit immediately if a command exits with a non-zero status.\n"
+"      -f  Disable file name generation (globbing).\n"
+"      -h  Remember the location of commands as they are looked up.\n"
+"      -k  All assignment arguments are placed in the environment for a\n"
+"          command, not just those that precede the command name.\n"
+"      -m  Job control is enabled.\n"
+"      -n  Read commands but do not execute them.\n"
+"      -o option-name\n"
+"          Set the variable corresponding to option-name:\n"
+"              allexport    same as -a\n"
+"              braceexpand  same as -B\n"
+"              emacs        use an emacs-style line editing interface\n"
+"              errexit      same as -e\n"
+"              errtrace     same as -E\n"
+"              functrace    same as -T\n"
+"              hashall      same as -h\n"
+"              histexpand   same as -H\n"
+"              history      enable command history\n"
+"              ignoreeof    the shell will not exit upon reading EOF\n"
+"              interactive-comments\n"
+"                           allow comments to appear in interactive commands\n"
+"              keyword      same as -k\n"
+"              monitor      same as -m\n"
+"              noclobber    same as -C\n"
+"              noexec       same as -n\n"
+"              noglob       same as -f\n"
+"              nolog        currently accepted but ignored\n"
+"              notify       same as -b\n"
+"              nounset      same as -u\n"
+"              onecmd       same as -t\n"
+"              physical     same as -P\n"
+"              pipefail     the return value of a pipeline is the status of\n"
+"                           the last command to exit with a non-zero status,\n"
+"                           or zero if no command exited with a non-zero status\n"
+"              posix        change the behavior of bash where the default\n"
+"                           operation differs from the Posix standard to\n"
+"                           match the standard\n"
+"              privileged   same as -p\n"
+"              verbose      same as -v\n"
+"              vi           use a vi-style line editing interface\n"
+"              xtrace       same as -x\n"
+"      -p  Turned on whenever the real and effective user ids do not match.\n"
+"          Disables processing of the $ENV file and importing of shell\n"
+"          functions.  Turning this option off causes the effective uid and\n"
+"          gid to be set to the real uid and gid.\n"
+"      -t  Exit after reading and executing one command.\n"
+"      -u  Treat unset variables as an error when substituting.\n"
+"      -v  Print shell input lines as they are read.\n"
+"      -x  Print commands and their arguments as they are executed.\n"
+"      -B  the shell will perform brace expansion\n"
+"      -C  If set, disallow existing regular files to be overwritten\n"
+"          by redirection of output.\n"
+"      -E  If set, the ERR trap is inherited by shell functions.\n"
+"      -H  Enable ! style history substitution.  This flag is on\n"
+"          by default when the shell is interactive.\n"
+"      -P  If set, do not follow symbolic links when executing commands\n"
+"          such as cd which change the current directory.\n"
+"      -T  If set, the DEBUG trap is inherited by shell functions.\n"
+"      --  Assign any remaining arguments to the positional parameters.\n"
+"          If there are no remaining arguments, the positional parameters\n"
+"          are unset.\n"
+"      -   Assign any remaining arguments to the positional parameters.\n"
+"          The -x and -v options are turned off.\n"
+"    \n"
+"    Using + rather than - causes these flags to be turned off.  The\n"
+"    flags can also be used upon invocation of the shell.  The current\n"
+"    set of flags may be found in $-.  The remaining n ARGs are positional\n"
+"    parameters and are assigned, in order, to $1, $2, .. $n.  If no\n"
+"    ARGs are given, all shell variables are printed.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given."
+msgstr ""
+"Imposta o azzera i valori delle opzioni di shell e dei parametri posizionali.\n"
+"    \n"
+"    Cambia il valore degli attributi di shell e dei parametri posizionali, o\n"
+"    visualizza i nomi e i valori delle variabili di shell.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a  Marca le variabili che sono modificate o create per l'esportazione.\n"
+"      -b  Notifica immediatamente della terminazione di un job.\n"
+"      -e  Esce immediatamente se un comando esce con uno stao diverso da zero.\n"
+"      -f  Disabilita la generazione dei nomi file (globbing).\n"
+"      -h  Ricorda la posizione dei comandi quando vengono cercati.\n"
+"      -k  Tutte le assegnazioni degli argomenti sono posizionate nell'ambiente per un\n"
+"          comando, non solo quelle che precedono il nome del comando stesso.\n"
+"      -m  Abilita il controllo dei job.\n"
+"      -n  Legge i comandi senza eseguirli.\n"
+"      -o nome-opzione\n"
+"          Imposta la variabile corrispondente al nome dell'opzione:\n"
+"              allexport    Uguale a -a\n"
+"              braceexpand  Uguale a -B\n"
+"              emacs        Usa una interfaccia di modifica righe di stile emacs\n"
+"              errexit      Uguale a -e\n"
+"              errtrace     Uguale a -E\n"
+"              functrace    Uguale a -T\n"
+"              hashall      Uguale a -h\n"
+"              histexpand   Uguale a -H\n"
+"              history      Abilita la cronologia comandi\n"
+"              ignoreeof    Non esce dalla shell dopo aver raggiunto EOF\n"
+"              interactive-comments\n"
+"                           Permette ai commenti di comparire nei comandi interattivi\n"
+"              keyword      Uguale a -k\n"
+"              monitor      Uguale a -m\n"
+"              noclobber    Uguale a -C\n"
+"              noexec       Uguale a -n\n"
+"              noglob       Uguale a -f\n"
+"              nolog        Accettato al momento ma ignorato\n"
+"              notify       Uguale a -b\n"
+"              nounset      Uguale a -u\n"
+"              onecmd       Uguale a -t\n"
+"              physical     Uguale a -P\n"
+"              pipefail     Il valore restituito da una pipeline è lo stato\n"
+"                           dell'ultimo comando che esce con uno stato diverso da zero,\n"
+"                           oppure zero se nessun comando esce con uno stato diverso da zero\n"
+"              posix        Modifica il comportamento di bash dove l'operazione\n"
+"                           predefinita è diversa dallo standard Posix per rispettare\n"
+"                           lo standard stesso\n"
+"              privileged   Uguale a -p\n"
+"              verbose      Uguale a -v\n"
+"              vi           Usa un'editor di riga stile vi\n"
+"              xtrace       Uguale a -x\n"
+"      -p  Abilitato ogni qualvolta gli id utente reali non corrispondono a quelli effettivi.\n"
+"          Disabilita l'analisi del file $ENV e l'importazione delle funzioni di\n"
+"          shell.  Disabilitare questa opzione comporta l'impostazione degli\n"
+"          uid e gid effettivi a uid e gid reali.\n"
+"      -t  Esce dopo la lettura e l'esecuzione di un comando.\n"
+"      -u  Tratta le variabili non impostate come un errore durante la sostituzione.\n"
+"      -v  Stampa le righe di input della shell mentre vengono lette.\n"
+"      -x  Stampa i comandi e i loro argomenti mentre vengono eseguiti.\n"
+"      -B  La shell effettua l'espansione delle parentesi graffe\n"
+"      -C  Se impostata, non permette la sovrascrittura dei file regolari esistenti\n"
+"          da parte della redirezione dell'output.\n"
+"      -E  Se impostata, la trap ERR è ereditata dalle funzioni di shell.\n"
+"      -H  Abilita la sostituzione per la cronologia stile !.  Questo flag è abilitato\n"
+"          in modo predefinito quando la shell è interattiva.\n"
+"      -P  Se impostata, non segue i link simbolici quando vengono eseguiti dei comandi\n"
+"          come cd, il quale cambia la directory corrente.\n"
+"      -T  Se impostata, la trap DEBUG è ereditata dalle funzioni di shell.\n"
+"      --  Assegna tutti gli argomenti rimasti ai parametri posizionali.\n"
+"          Se non sono rimasti argomenti, i parametri posizionali\n"
+"          vengono azzerati.\n"
+"      -   Assegna tutti gli argomenti rimasti ai parametri posizionali.\n"
+"          Le opzioni -x e -v sono disabilitate.\n"
+"    \n"
+"    Usando + al posto di - questi flag vengono disabilitati.  I\n"
+"    flag possono anche essere usati subito dopo l'invocazione della shell.  Il set corrente\n"
+"    dei flag può essere trovato in $-.  I restanti n ARG sono parametri\n"
+"    posizionali e vengono assegnati, in ordine, a $1, $2, .. $n.  Se non\n"
+"    vengono forniti ARG, vengono stampate tutte le variabili di shell.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita una opzione non valida."
+
+#: builtins.c:1112
+msgid ""
+"Unset values and attributes of shell variables and functions.\n"
+"    \n"
+"    For each NAME, remove the corresponding variable or function.\n"
+"    \n"
+"    Options:\n"
+"      -f\ttreat each NAME as a shell function\n"
+"      -v\ttreat each NAME as a shell variable\n"
+"    \n"
+"    Without options, unset first tries to unset a variable, and if that fails,\n"
+"    tries to unset a function.\n"
+"    \n"
+"    Some variables cannot be unset; also see `readonly'.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or a NAME is read-only."
+msgstr ""
+"Azzera i valori e gli attributi delle variabili e delle funzioni di shell.\n"
+"    \n"
+"    Per ciascun NOME, rimuove la corrispondente variabile o funzione.\n"
+"    \n"
+"    Opzioni:\n"
+"      -f\tConsidera ciascun NOME come una funzione di shell\n"
+"      -v\tConsidera ciascun NOME come una variabile di shell\n"
+"    \n"
+"    Senza opzioni, unset prova prima ad azzerare una variabile e, in caso di insuccesso,\n"
+"    prova ad azzerare una funzione.\n"
+"    \n"
+"    Alcune variabili non possono essere azzerate; vedere anche \"readonly\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o NOME sia in sola lettura."
+
+#: builtins.c:1132
+msgid ""
+"Set export attribute for shell variables.\n"
+"    \n"
+"    Marks each NAME for automatic export to the environment of subsequently\n"
+"    executed commands.  If VALUE is supplied, assign VALUE before exporting.\n"
+"    \n"
+"    Options:\n"
+"      -f\trefer to shell functions\n"
+"      -n\tremove the export property from each NAME\n"
+"      -p\tdisplay a list of all exported variables and functions\n"
+"    \n"
+"    An argument of `--' disables further option processing.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or NAME is invalid."
+msgstr ""
+"Imposta l'attributo di esportazione per le variabili di shell.\n"
+"    \n"
+"    Marca ciascun NOME per l'esportazione automatica all'ambiente dei comandi\n"
+"    eseguiti successivi.  Se è fornito un VALORE, lo assegna prima dell'esportazione.\n"
+"    \n"
+"    Opzioni:\n"
+"      -f\tRimanda alle funzioni di shell\n"
+"      -n\tRimuove la proprietà di esportazione da ciascun NOME\n"
+"      -p\tVisualizza un elenco di tutte le variabili e funzioni esportate\n"
+"    \n"
+"    L'argomento \"--\" disabilita l'elaborazione di ulteriori opzioni.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o il NOME non sia valido."
+
+#: builtins.c:1151
+msgid ""
+"Mark shell variables as unchangeable.\n"
+"    \n"
+"    Mark each NAME as read-only; the values of these NAMEs may not be\n"
+"    changed by subsequent assignment.  If VALUE is supplied, assign VALUE\n"
+"    before marking as read-only.\n"
+"    \n"
+"    Options:\n"
+"      -a\trefer to indexed array variables\n"
+"      -A\trefer to associative array variables\n"
+"      -f\trefer to shell functions\n"
+"      -p\tdisplay a list of all readonly variables and functions\n"
+"    \n"
+"    An argument of `--' disables further option processing.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or NAME is invalid."
+msgstr ""
+"Marca la variabili di shell come non modificabili.\n"
+"    \n"
+"    Marca ciascun NOME in sola lettura; i valori di questi NOMI non possono\n"
+"    essere modificati da un assegnamento successivo.  Se viene fornito il\n"
+"     VALORE, lo assegna prima di marcarlo in sola lettura.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a\tRimanda alle variabili degli array indicizzati\n"
+"      -A\tRimanda alle variabili degli array associativi\n"
+"      -f\tRimanda alle funzioni di shell\n"
+"      -p\tVisualizza un elenco di tutte le variabili e le funzioni in sola lettura\n"
+"    \n"
+"    Un argomento pari a \"--\" disabilita ulteriori analisi delle opzioni.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita una opzione non valida o NOME non sia valido."
+
+#: builtins.c:1172
+msgid ""
+"Shift positional parameters.\n"
+"    \n"
+"    Rename the positional parameters $N+1,$N+2 ... to $1,$2 ...  If N is\n"
+"    not given, it is assumed to be 1.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless N is negative or greater than $#."
+msgstr ""
+"Sposta i parametri posizionali.\n"
+"    \n"
+"    Rinomina i parametri posizionali $N+1,$N+2 ... a $1,$2 ...  Se N non\n"
+"    è fornito, viene assunto a 1.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che N non sia negativo o maggiore di $#."
+
+#: builtins.c:1184 builtins.c:1199
+msgid ""
+"Execute commands from a file in the current shell.\n"
+"    \n"
+"    Read and execute commands from FILENAME in the current shell.  The\n"
+"    entries in $PATH are used to find the directory containing FILENAME.\n"
+"    If any ARGUMENTS are supplied, they become the positional parameters\n"
+"    when FILENAME is executed.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed in FILENAME; fails if\n"
+"    FILENAME cannot be read."
+msgstr ""
+"Esegue comandi da un file nella shell corrente.\n"
+"    \n"
+"    Legge ed esegue comandi da NOMEFILE nella shell corrente. Le voci\n"
+"    in $PATH sono usate per trovare la directory contenente il NOMEFILE.\n"
+"    Se vengono forniti ARGOMENTI, essi diventano i parametri di posizione\n"
+"    quando viene eseguito NOMEFILE.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito in NOMEFILE; insuccesso se\n"
+"    il NOMEFILE non può essere letto."
+
+#: builtins.c:1215
+msgid ""
+"Suspend shell execution.\n"
+"    \n"
+"    Suspend the execution of this shell until it receives a SIGCONT signal.\n"
+"    Unless forced, login shells cannot be suspended.\n"
+"    \n"
+"    Options:\n"
+"      -f\tforce the suspend, even if the shell is a login shell\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless job control is not enabled or an error occurs."
+msgstr ""
+"Sospende l'esecuzione della shell.\n"
+"    \n"
+"    Sospende l'esecuzione di questa shell fino a che non riceve un segnale SIGCONT.\n"
+"    A meno di forzature, le shell di login non possono essere sospese.\n"
+"    \n"
+"    Opzioni:\n"
+"      -f\tForza la sospensione, anche se in presenza di una shell di login\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia abilitato il controllo job o si riscontri un errore."
+
+#: builtins.c:1231
+msgid ""
+"Evaluate conditional expression.\n"
+"    \n"
+"    Exits with a status of 0 (true) or 1 (false) depending on\n"
+"    the evaluation of EXPR.  Expressions may be unary or binary.  Unary\n"
+"    expressions are often used to examine the status of a file.  There\n"
+"    are string operators and numeric comparison operators as well.\n"
+"    \n"
+"    The behavior of test depends on the number of arguments.  Read the\n"
+"    bash manual page for the complete specification.\n"
+"    \n"
+"    File operators:\n"
+"    \n"
+"      -a FILE        True if file exists.\n"
+"      -b FILE        True if file is block special.\n"
+"      -c FILE        True if file is character special.\n"
+"      -d FILE        True if file is a directory.\n"
+"      -e FILE        True if file exists.\n"
+"      -f FILE        True if file exists and is a regular file.\n"
+"      -g FILE        True if file is set-group-id.\n"
+"      -h FILE        True if file is a symbolic link.\n"
+"      -L FILE        True if file is a symbolic link.\n"
+"      -k FILE        True if file has its `sticky' bit set.\n"
+"      -p FILE        True if file is a named pipe.\n"
+"      -r FILE        True if file is readable by you.\n"
+"      -s FILE        True if file exists and is not empty.\n"
+"      -S FILE        True if file is a socket.\n"
+"      -t FD          True if FD is opened on a terminal.\n"
+"      -u FILE        True if the file is set-user-id.\n"
+"      -w FILE        True if the file is writable by you.\n"
+"      -x FILE        True if the file is executable by you.\n"
+"      -O FILE        True if the file is effectively owned by you.\n"
+"      -G FILE        True if the file is effectively owned by your group.\n"
+"      -N FILE        True if the file has been modified since it was last read.\n"
+"    \n"
+"      FILE1 -nt FILE2  True if file1 is newer than file2 (according to\n"
+"                       modification date).\n"
+"    \n"
+"      FILE1 -ot FILE2  True if file1 is older than file2.\n"
+"    \n"
+"      FILE1 -ef FILE2  True if file1 is a hard link to file2.\n"
+"    \n"
+"    String operators:\n"
+"    \n"
+"      -z STRING      True if string is empty.\n"
+"    \n"
+"      -n STRING\n"
+"         STRING      True if string is not empty.\n"
+"    \n"
+"      STRING1 = STRING2\n"
+"                     True if the strings are equal.\n"
+"      STRING1 != STRING2\n"
+"                     True if the strings are not equal.\n"
+"      STRING1 < STRING2\n"
+"                     True if STRING1 sorts before STRING2 lexicographically.\n"
+"      STRING1 > STRING2\n"
+"                     True if STRING1 sorts after STRING2 lexicographically.\n"
+"    \n"
+"    Other operators:\n"
+"    \n"
+"      -o OPTION      True if the shell option OPTION is enabled.\n"
+"      -v VAR\t True if the shell variable VAR is set\n"
+"      ! EXPR         True if expr is false.\n"
+"      EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.\n"
+"      EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.\n"
+"    \n"
+"      arg1 OP arg2   Arithmetic tests.  OP is one of -eq, -ne,\n"
+"                     -lt, -le, -gt, or -ge.\n"
+"    \n"
+"    Arithmetic binary operators return true if ARG1 is equal, not-equal,\n"
+"    less-than, less-than-or-equal, greater-than, or greater-than-or-equal\n"
+"    than ARG2.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success if EXPR evaluates to true; fails if EXPR evaluates to\n"
+"    false or an invalid argument is given."
+msgstr ""
+"Analizza espressioni condizionali.\n"
+"    \n"
+"    Esce con stato 0 (vero) o 1 (falso) in base all'analisi\n"
+"    dell'ESPR.  Le espressioni possono essere unarie o binarie.  Le\n"
+"    espressioni unarie sono spesso usate per esaminare lo stato di un file.\n"
+"    Esistono anche operatori di stringa e di comparazione numerica.\n"
+"    \n"
+"    Il comportamento del test dipende dal numero degli argomenti.  Leggere\n"
+"    la pagina di manuale di bash per le specifiche complete.\n"
+"    \n"
+"    Operatori su file:\n"
+"    \n"
+"      -a FILE        Vero se il file esiste.\n"
+"      -b FILE        Vero se è un file speciale a blocchi.\n"
+"      -c FILE        Vero se è un file speciale a caratteri.\n"
+"      -d FILE        Vero se il file è una directory.\n"
+"      -e FILE        Vero se il file esiste.\n"
+"      -f FILE        Vero se il file esiste ed è un file regolare.\n"
+"      -g FILE        Vero se il file è un set-group-id.\n"
+"      -h FILE        Vero se il file è un link simbolico.\n"
+"      -L FILE        Vero se il file è un link simbolico.\n"
+"      -k FILE        Vero se il file ha il suo bit \"sticky\" impostato.\n"
+"      -p FILE        Vero se il file è una pipe con nome.\n"
+"      -r FILE        Vero se il file è leggibile dall' utente corrente.\n"
+"      -s FILE        Vero se il file esiste e non è vuoto.\n"
+"      -S FILE        Vero se il file è un socket.\n"
+"      -t FD          Vero se il descrittore di file è aperto su un terminale.\n"
+"      -u FILE        Vero se il file è un set-user-id.\n"
+"      -w FILE        Vero se il file è scrivibile dall'utente corrente.\n"
+"      -x FILE        Vero se il file è eseguibile dall'utente corrente.\n"
+"      -O FILE        Vero se l'utente corrente è il reale proprietario del file.\n"
+"      -G FILE        Vero se il gruppo dell'utente corrente è il reale proprietario del file.\n"
+"      -N FILE        Vero se il file è stato modificato dall'ultima volta che è stato letto.\n"
+"    \n"
+"      FILE1 -nt FILE2  Vero se il file1 è più recente del file2 (in accordo con la\n"
+"                       data di modifica).\n"
+"    \n"
+"      FILE1 -ot FILE2  Vero se il file1 è più vecchio del file2.\n"
+"    \n"
+"      FILE1 -ef FILE2  Vero se il file1 è un link hardware al file2.\n"
+"    \n"
+"    Operatori di stringa:\n"
+"    \n"
+"      -z STRINGA     Vero se la stringa e vuota.\n"
+"    \n"
+"      -n STRINGA\n"
+"         STRINGA     Vero se la stringa non è vuota.\n"
+"    \n"
+"      STRINGA1 = STRINGA2\n"
+"                     Vero se le stringhe sono uguali.\n"
+"      STRINGA1 != STRINGA2\n"
+"                     Vero se le stringhe non sono uguali.\n"
+"      STRINGA1 < STRINGA2\n"
+"                     Vero se la STRINGA1 viene ordinata lessicograficamente prima della STRINGA2.\n"
+"      STRINGA1 > STRINGA2\n"
+"                     Vero se la STRINGA1 viene ordinata lessicograficamente dopo la STRINGA2.\n"
+"    \n"
+"    Altri operatori:\n"
+"    \n"
+"      -o OPZIONE     Vero se l'OPZIONE di shell è abilitata.\n"
+"      -v VAR\t Vero se la variabile di shell VAR è impostata.\n"
+"      ! ESPR         Vero se l'ESPR è falsa.\n"
+"      ESPR1 -a ESPR2 Vero se entrambe le espressioni espr1 E espr2 sono vere.\n"
+"      ESPR1 -o ESPR2 Vero se sono vere le espressioni espr1 O espr2.\n"
+"    \n"
+"      arg1 OP arg2   Test aritmetici.  OP è uno tra -eq, -ne,\n"
+"                     -lt, -le, -gt oppure -ge.\n"
+"    \n"
+"    Gli operatori aritmetici binari restituiscono vero se ARG1 è uguale, non uguale,\n"
+"    più piccolo di, più piccolo o uguale, più grande di o più grande o uguale\n"
+"    ad ARG2.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo se l'ESPR viene valutata vera; insuccesso se l'ESPR viene valutata\n"
+"    falsa o viene fornito un argomento non valido."
+
+#: builtins.c:1311
+msgid ""
+"Evaluate conditional expression.\n"
+"    \n"
+"    This is a synonym for the \"test\" builtin, but the last argument must\n"
+"    be a literal `]', to match the opening `['."
+msgstr ""
+"Valuta l'espressione condizionale.\n"
+"    \n"
+"    Questo è un sinonimo del comando interno \"test\", ma l'ultimo argomento deve\n"
+"    essere un \"]\" letterale per corrispondere al \"[\" di apertura."
+
+#: builtins.c:1320
+msgid ""
+"Display process times.\n"
+"    \n"
+"    Prints the accumulated user and system times for the shell and all of its\n"
+"    child processes.\n"
+"    \n"
+"    Exit Status:\n"
+"    Always succeeds."
+msgstr ""
+"Visualizza le durate dei processi.\n"
+"    \n"
+"    Stampa i tempi utente e di sistema accumulati per la shell e per tutti i\n"
+"    relativi processi figli.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Sempre successo."
+
+#: builtins.c:1332
+msgid ""
+"Trap signals and other events.\n"
+"    \n"
+"    Defines and activates handlers to be run when the shell receives signals\n"
+"    or other conditions.\n"
+"    \n"
+"    ARG is a command to be read and executed when the shell receives the\n"
+"    signal(s) SIGNAL_SPEC.  If ARG is absent (and a single SIGNAL_SPEC\n"
+"    is supplied) or `-', each specified signal is reset to its original\n"
+"    value.  If ARG is the null string each SIGNAL_SPEC is ignored by the\n"
+"    shell and by the commands it invokes.\n"
+"    \n"
+"    If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell.  If\n"
+"    a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command.  If\n"
+"    a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a\n"
+"    script run by the . or source builtins finishes executing.  A SIGNAL_SPEC\n"
+"    of ERR means to execute ARG each time a command's failure would cause the\n"
+"    shell to exit when the -e option is enabled.\n"
+"    \n"
+"    If no arguments are supplied, trap prints the list of commands associated\n"
+"    with each signal.\n"
+"    \n"
+"    Options:\n"
+"      -l\tprint a list of signal names and their corresponding numbers\n"
+"      -p\tdisplay the trap commands associated with each SIGNAL_SPEC\n"
+"    \n"
+"    Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal number.\n"
+"    Signal names are case insensitive and the SIG prefix is optional.  A\n"
+"    signal may be sent to the shell with \"kill -signal $$\".\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless a SIGSPEC is invalid or an invalid option is given."
+msgstr ""
+"Esegue il trap dei segnali e di altri eventi.\n"
+"    \n"
+"    Definisce e attiva i gestori da eseguire quando la shell riceve segnali\n"
+"    o altre condizioni.\n"
+"    \n"
+"    ARG è un comando da leggere ed eseguire quando la shell riceve il o i\n"
+"    segnali SPEC_SEGNALE.  Se ARG o \"-\" non sono presenti (e viene fornito\n"
+"    un singolo SPEC_SEGNALE), ciascun segnale specificato è riportato\n"
+"    al suo valore originario.  Se ARG è pari a null, ogni SPEC_SEGNALE è\n"
+"    ignorato dalla shell e dai comandi che invoca.\n"
+"    \n"
+"    Se uno SPEC_SEGNALE è EXIT (0) ARG viene eseguito all'uscita dalla shell.  Se\n"
+"    lo SPEC_SEGNALE è DEBUG, ARG viene eseguito prima di ogni comando semplice.  Se\n"
+"    uno SPEC_SEGNALE è RETURN, ARG viene eseguito al termine di ogni esecuzione\n"
+"    di una funzione di shell o di uno script avviato dai comandi interni . o sorgenti.\n"
+"    Un SPEC_SEGNALE di ERR significa eseguire ARG ogni volta che un errore di comando\n"
+"    causi l'uscita della shell quando è abilitata l'opzione -e.\n"
+"    \n"
+"    Se non vengono forniti argomenti, trap stampa l'elenco di comandi associati\n"
+"    a ciascun segnale.\n"
+"    \n"
+"    Ozioni:\n"
+"      -l\tStampa un elenco di nomi di segnale e i loro corrispondenti numeri\n"
+"      -p\tVisualizza i comandi trap associati a ciascun SPEC_SEGNALE\n"
+"    \n"
+"    Ciascun SPEC_SEGNALE è un nome di segnale in <signal.h> oppure un numero di segnale.\n"
+"    I nomi di segnale sono case insensitive e il prefisso SIG è opzionale.  Per\n"
+"    inviare un segnale alla shell usare \"kill -signal $$\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che SPEC_SEGNALE non sia valido o si fornisca una opzione non valida."
+
+#: builtins.c:1368
+msgid ""
+"Display information about command type.\n"
+"    \n"
+"    For each NAME, indicate how it would be interpreted if used as a\n"
+"    command name.\n"
+"    \n"
+"    Options:\n"
+"      -a\tdisplay all locations containing an executable named NAME;\n"
+"    \tincludes aliases, builtins, and functions, if and only if\n"
+"    \tthe `-p' option is not also used\n"
+"      -f\tsuppress shell function lookup\n"
+"      -P\tforce a PATH search for each NAME, even if it is an alias,\n"
+"    \tbuiltin, or function, and returns the name of the disk file\n"
+"    \tthat would be executed\n"
+"      -p\treturns either the name of the disk file that would be executed,\n"
+"    \tor nothing if `type -t NAME' would not return `file'.\n"
+"      -t\toutput a single word which is one of `alias', `keyword',\n"
+"    \t`function', `builtin', `file' or `', if NAME is an alias, shell\n"
+"    \treserved word, shell function, shell builtin, disk file, or not\n"
+"    \tfound, respectively\n"
+"    \n"
+"    Arguments:\n"
+"      NAME\tCommand name to be interpreted.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success if all of the NAMEs are found; fails if any are not found."
+msgstr ""
+"Visualizza informazioni sul tipo di comando.\n"
+"    \n"
+"    Per ciascun NOME, indica come sarebbe interpretato se fosse usato come\n"
+"    un nome di comando.\n"
+"    \n"
+"    Opzioni:\n"
+"      -a\tVisualizza tutte le posizioni contenenti un eseguibile chiamato NOME,\n"
+"    \tincludendo alias, comandi interni e funzioni se e solo se\n"
+"    \tnon viene usata anche l'opzione \"-p\"\n"
+"      -f\tNon esegue la ricerca delle funzioni di shell\n"
+"      -P\tForza una ricerca del PERCORSO per ciascun NOME anche se è un alias,\n"
+"    \tun comando interno o una funzione, e restituisce il nome del file su disco\n"
+"    \tche sarebbe eseguito\n"
+"      -p\tRestituisce o il nome del file su disco che sarebbe eseguito,\n"
+"    \toppure niente se \"type -t NOME\" non restituisce \"file\".\n"
+"      -t\tVisualizza una singola parola che è una tra \"alias\", \"keyword\",\n"
+"    \t\"function\", \"builtin\", \"file\" or \"\", se il NOME è rispettivamente un alias,\n"
+"    \tuna parola riservata di shell, una funzione di shell, un comando interno di shell,\n"
+"    \tun file su disco o non trovato\n"
+"    \n"
+"    Argomenti:\n"
+"      NOME\tIl nome del comando da interpretare.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo se tutti i NOMI vengono trovati; insuccesso in caso contrario."
+
+#: builtins.c:1399
+msgid ""
+"Modify shell resource limits.\n"
+"    \n"
+"    Provides control over the resources available to the shell and processes\n"
+"    it creates, on systems that allow such control.\n"
+"    \n"
+"    Options:\n"
+"      -S\tuse the `soft' resource limit\n"
+"      -H\tuse the `hard' resource limit\n"
+"      -a\tall current limits are reported\n"
+"      -b\tthe socket buffer size\n"
+"      -c\tthe maximum size of core files created\n"
+"      -d\tthe maximum size of a process's data segment\n"
+"      -e\tthe maximum scheduling priority (`nice')\n"
+"      -f\tthe maximum size of files written by the shell and its children\n"
+"      -i\tthe maximum number of pending signals\n"
+"      -l\tthe maximum size a process may lock into memory\n"
+"      -m\tthe maximum resident set size\n"
+"      -n\tthe maximum number of open file descriptors\n"
+"      -p\tthe pipe buffer size\n"
+"      -q\tthe maximum number of bytes in POSIX message queues\n"
+"      -r\tthe maximum real-time scheduling priority\n"
+"      -s\tthe maximum stack size\n"
+"      -t\tthe maximum amount of cpu time in seconds\n"
+"      -u\tthe maximum number of user processes\n"
+"      -v\tthe size of virtual memory\n"
+"      -x\tthe maximum number of file locks\n"
+"    \n"
+"    If LIMIT is given, it is the new value of the specified resource; the\n"
+"    special LIMIT values `soft', `hard', and `unlimited' stand for the\n"
+"    current soft limit, the current hard limit, and no limit, respectively.\n"
+"    Otherwise, the current value of the specified resource is printed.  If\n"
+"    no option is given, then -f is assumed.\n"
+"    \n"
+"    Values are in 1024-byte increments, except for -t, which is in seconds,\n"
+"    -p, which is in increments of 512 bytes, and -u, which is an unscaled\n"
+"    number of processes.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is supplied or an error occurs."
+msgstr ""
+"Modifica i limiti delle risorse di shell.\n"
+"    \n"
+"    Fornisce il controllo sulle risorse disponibili per la shell e per i processi\n"
+"    che crea, sui sistemi che permettono tale controllo.\n"
+"    \n"
+"    Opzioni:\n"
+"      -S\tUsa il limite di risorse \"leggero\"\n"
+"      -H\tUsa il limite di risorse \"pesante\"\n"
+"      -a\tRiporta tutti i limiti correnti\n"
+"      -b\tLa dimensione del buffer del socket\n"
+"      -c\tLa dimensione massima dei file di core creati\n"
+"      -d\tLa dimensione massima di un segmento di dati di processo\n"
+"      -e\tLa priorità massima di scheduling (\"nice\")\n"
+"      -f\tLa dimensione massima dei file scritti dalla shell e dai suoi figli\n"
+"      -i\tIl numero massimo di segnali pendenti\n"
+"      -l\tLa dimensione massima di memoria che un processo può impegnare\n"
+"      -m\tIl numero massimo di set residenti\n"
+"      -n\tIl numero massimo di descrittori di file aperti\n"
+"      -p\tLa dimensione del buffer della pipe\n"
+"      -q\tIl numero massimo di byte nelle code messaggi POSIX\n"
+"      -r\tLa priorità massima di scheduling in tempo reale\n"
+"      -s\tLa dimensione massima dello stack\n"
+"      -t\tLa quantità massima di tempo CPU in secondi\n"
+"      -u\tIl numero massimo di processi utente\n"
+"      -v\tLa dimensione della memoria virtuale\n"
+"      -x\tIl numero massimo di lock dei file\n"
+"    \n"
+"    Se viene fornito un LIMITE, sarà il nuovo valore della risorsa specificata;\n"
+"    I valori LIMITE speciali \"soft\", \"hard\" e \"unlimited\" corrispondono\n"
+"    rispettivamente agli attuali limiti leggero, pesante e senza limite.\n"
+"    Altrimenti viene stampato il valore attuale della risorsa specificata.  Se\n"
+"    non viene fornita alcuna opzione, viene assunta -f.\n"
+"    \n"
+"    I valori sono ad incrementi di 1024-byte, ad eccezione di -t che è in secondi,\n"
+"    -p che è ad incrementi di 512 byte e -u che è un numero di processi non\n"
+"    scalato.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita una opzione non valida o venga riscontrato un errore."
+
+#: builtins.c:1444
+msgid ""
+"Display or set file mode mask.\n"
+"    \n"
+"    Sets the user file-creation mask to MODE.  If MODE is omitted, prints\n"
+"    the current value of the mask.\n"
+"    \n"
+"    If MODE begins with a digit, it is interpreted as an octal number;\n"
+"    otherwise it is a symbolic mode string like that accepted by chmod(1).\n"
+"    \n"
+"    Options:\n"
+"      -p\tif MODE is omitted, output in a form that may be reused as input\n"
+"      -S\tmakes the output symbolic; otherwise an octal number is output\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless MODE is invalid or an invalid option is given."
+msgstr ""
+"Visualizza o imposta la maschera del modo file.\n"
+"    \n"
+"    Imposta la maschera di creazione file dell'utente su MODO.  Se MODO viene omesso, stampa\n"
+"    il valore corrente della maschera.\n"
+"    \n"
+"    Se MODO inizia con una cifra, è interpretato con un numero ottale;\n"
+"    altrimenti come una stringa di modo simbolico come quella accettata da chmod(1).\n"
+"    \n"
+"    Opzioni:\n"
+"      -p\tSe MODO viene omesso, mostra in una forma che possa essere riusata come input\n"
+"      -S\tRende simbolico l'output; altrimenti viene mostrato un numero ottale\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che MODO non sia valido o venga fornita una opzione non valida."
+
+#: builtins.c:1464
+msgid ""
+"Wait for job completion and return exit status.\n"
+"    \n"
+"    Waits for the process identified by ID, which may be a process ID or a\n"
+"    job specification, and reports its termination status.  If ID is not\n"
+"    given, waits for all currently active child processes, and the return\n"
+"    status is zero.  If ID is a a job specification, waits for all processes\n"
+"    in the job's pipeline.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of ID; fails if ID is invalid or an invalid option is\n"
+"    given."
+msgstr ""
+"Attende il completamento del job restituendo lo stato di uscita.\n"
+"    \n"
+"    Attende il processo identificato dall'ID, che può essere un ID di processo o\n"
+"    una specifica di job, riportando il suo stato di termine.  Se non è\n"
+"    fornito un ID, attende tutti i processi figlio correntemente attivi, restituendo\n"
+"    zero come stato.  Se l'ID è una specifica di job, attende tutti i processi\n"
+"    presenti nella pipeline del job.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ID; insuccesso se l'ID non è valido o viene fornita una\n"
+"    opzione non valida."
+
+#: builtins.c:1482
+msgid ""
+"Wait for process completion and return exit status.\n"
+"    \n"
+"    Waits for the specified process and reports its termination status.  If\n"
+"    PID is not given, all currently active child processes are waited for,\n"
+"    and the return code is zero.  PID must be a process ID.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of ID; fails if ID is invalid or an invalid option is\n"
+"    given."
+msgstr ""
+"Attende il completamento del processo e restituisce lo stato di uscita.\n"
+"    \n"
+"    Attende per il processo specificato e riporta il suo stato di terminazione.  Se non\n"
+"    viene fornito il PID, l'attesa comprende tutti i processi figlio correntemente attivi\n"
+"    e il codice restituito è zero.  Il PID deve essere un ID di processo.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ID; insuccesso se l'ID non è valido o viene fornita una opzione non\n"
+"    valida."
+
+#: builtins.c:1497
+msgid ""
+"Execute commands for each member in a list.\n"
+"    \n"
+"    The `for' loop executes a sequence of commands for each member in a\n"
+"    list of items.  If `in WORDS ...;' is not present, then `in \"$@\"' is\n"
+"    assumed.  For each element in WORDS, NAME is set to that element, and\n"
+"    the COMMANDS are executed.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Esegue comandi per ciascun membro di un elenco.\n"
+"    \n"
+"    Il ciclo \"for\" esegue una sequenza di comandi per ciascun membro di un\n"
+"    elenco di voci.  Se \"in PAROLE ...;\" non è presente, allora viene assunto\n"
+"    \"in \"$@\"\".  Per ciascun elemento in PAROLE, NOME è impostato a quell'elemento e\n"
+"    i COMANDI vengono eseguiti.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito."
+
+#: builtins.c:1511
+msgid ""
+"Arithmetic for loop.\n"
+"    \n"
+"    Equivalent to\n"
+"    \t(( EXP1 ))\n"
+"    \twhile (( EXP2 )); do\n"
+"    \t\tCOMMANDS\n"
+"    \t\t(( EXP3 ))\n"
+"    \tdone\n"
+"    EXP1, EXP2, and EXP3 are arithmetic expressions.  If any expression is\n"
+"    omitted, it behaves as if it evaluates to 1.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Ciclo \"for\" aritmetico.\n"
+"    \n"
+"    Equivalente a\n"
+"    \t(( ESPR1 ))\n"
+"    \twhile (( ESPR2 )); do\n"
+"    \t\tCOMANDI\n"
+"    \t\t(( ESPR3 ))\n"
+"    \tdone\n"
+"    ESPR1, ESPR2 e ESPR3 sono espressioni aritmetiche.  Se viene omessa qualche\n"
+"    espressione, si comporta come se valesse 1.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito."
+
+#: builtins.c:1529
+msgid ""
+"Select words from a list and execute commands.\n"
+"    \n"
+"    The WORDS are expanded, generating a list of words.  The\n"
+"    set of expanded words is printed on the standard error, each\n"
+"    preceded by a number.  If `in WORDS' is not present, `in \"$@\"'\n"
+"    is assumed.  The PS3 prompt is then displayed and a line read\n"
+"    from the standard input.  If the line consists of the number\n"
+"    corresponding to one of the displayed words, then NAME is set\n"
+"    to that word.  If the line is empty, WORDS and the prompt are\n"
+"    redisplayed.  If EOF is read, the command completes.  Any other\n"
+"    value read causes NAME to be set to null.  The line read is saved\n"
+"    in the variable REPLY.  COMMANDS are executed after each selection\n"
+"    until a break command is executed.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Seleziona le parole da un elenco ed esegue i comandi.\n"
+"    \n"
+"    Le PAROLE vengono estese, generando un elenco di parole.  L'insieme\n"
+"    di parole estese viene stampato sullo standard error, ognuna delle\n"
+"    quali preceduta da un numero.  Se non è presente \"in PAROLE\", viene\n"
+"    assunto `in \"$@\".  Viene poi visualizzato il prompt PS3 e viene letta\n"
+"    una riga dallo standard input.  Se la riga è composta dal numero che\n"
+"    corrisponde a una delle parole visualizzate, NOME è impostato a quella\n"
+"    parola.  Se la riga è vuota, Le PAROLE e il prompt vengono rivisualizzati.\n"
+"    Se viene letto EOF, il comando termina.  Se vengono letti altri valori\n"
+"    NOME viene impostato a null.  La riga letta viene salvata nella variabile\n"
+"    REPLY.  I COMANDI vengono eseguiti dopo ogni selezione finché non viene\n"
+"    eseguito un comando di interruzione.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato di uscita dell'ultimo comando eseguito."
+
+#: builtins.c:1550
+msgid ""
+"Report time consumed by pipeline's execution.\n"
+"    \n"
+"    Execute PIPELINE and print a summary of the real time, user CPU time,\n"
+"    and system CPU time spent executing PIPELINE when it terminates.\n"
+"    \n"
+"    Options:\n"
+"      -p\tprint the timing summary in the portable Posix format\n"
+"    \n"
+"    The value of the TIMEFORMAT variable is used as the output format.\n"
+"    \n"
+"    Exit Status:\n"
+"    The return status is the return status of PIPELINE."
+msgstr ""
+"Riporta il tempo speso nell'esecuzione della pipeline.\n"
+"    \n"
+"    Esegue la PIPELINE e stampa, quando termina, un sommario del tempo reale, tempo utente della CPU\n"
+"    e tempo di sistema della CPU dedicato all'esecuzione della PIPELINE.\n"
+"    \n"
+"    Opzioni:\n"
+"      -p\tStampa il riepilogo dei tempi nel formato portabile Posix format\n"
+"    \n"
+"    Il valore della variabile TIMEFORMAT è usato come formato di output.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Viene restituito lo stato della PIPELINE."
+
+#: builtins.c:1567
+msgid ""
+"Execute commands based on pattern matching.\n"
+"    \n"
+"    Selectively execute COMMANDS based upon WORD matching PATTERN.  The\n"
+"    `|' is used to separate multiple patterns.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Esegue comandi basati sulla corrispondenza di modello.\n"
+"    \n"
+"    Esegue in modo selettivo COMANDI basati sulla PAROLA corrispondente al MODELLO.  Il\n"
+"    carattere \"|\" è usato per separare modelli multipli.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito."
+
+#: builtins.c:1579
+msgid ""
+"Execute commands based on conditional.\n"
+"    \n"
+"    The `if COMMANDS' list is executed.  If its exit status is zero, then the\n"
+"    `then COMMANDS' list is executed.  Otherwise, each `elif COMMANDS' list is\n"
+"    executed in turn, and if its exit status is zero, the corresponding\n"
+"    `then COMMANDS' list is executed and the if command completes.  Otherwise,\n"
+"    the `else COMMANDS' list is executed, if present.  The exit status of the\n"
+"    entire construct is the exit status of the last command executed, or zero\n"
+"    if no condition tested true.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Esegue comandi basati su condizioni.\n"
+"    \n"
+"    Viene eseguito l'elenco degli \"if COMANDI\".  Se lo stato di uscita è zero\n"
+"    viene eseguito l'elenco \"then COMANDI\", altrimenti viene eseguito l'elenco\n"
+"    degli \"elif COMANDI\" e, se il loro stato è zero, viene eseguito l'elenco dei\n"
+"    \"then COMANDI\" corrispondente e viene completato l'\"if COMANDO\".  Altrimenti,\n"
+"    viene eseguito l'elenco \"else COMANDI\", se presente.  Lo stato di uscita\n"
+"    dell'intero costrutto corrisponde a quello dell'ultimo comando eseguito, o\n"
+"    zero se nessuna condizione provata è vera.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito."
+
+#: builtins.c:1596
+msgid ""
+"Execute commands as long as a test succeeds.\n"
+"    \n"
+"    Expand and execute COMMANDS as long as the final command in the\n"
+"    `while' COMMANDS has an exit status of zero.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Esegue i comandi finché un test ha successo.\n"
+"    \n"
+"    Espande ed esegue i COMANDI fino a quando il comando finale nei\n"
+"    COMANDI \"while\" ha uno stato di uscita pari a zero.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito."
+
+#: builtins.c:1608
+msgid ""
+"Execute commands as long as a test does not succeed.\n"
+"    \n"
+"    Expand and execute COMMANDS as long as the final command in the\n"
+"    `until' COMMANDS has an exit status which is not zero.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Esegue i comandi finché un test non ha successo.\n"
+"    \n"
+"    Espande ed esegue i COMANDI fino a quando il comando finale nei\n"
+"    COMANDI \"until\" ha uno stato di uscita diverso da zero.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito."
+
+#: builtins.c:1620
+msgid ""
+"Create a coprocess named NAME.\n"
+"    \n"
+"    Execute COMMAND asynchronously, with the standard output and standard\n"
+"    input of the command connected via a pipe to file descriptors assigned\n"
+"    to indices 0 and 1 of an array variable NAME in the executing shell.\n"
+"    The default NAME is \"COPROC\".\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the exit status of COMMAND."
+msgstr ""
+"Crea un coprocesso chiamato NOME.\n"
+"    \n"
+"    Esegue il COMANDO in modo asincrono, con lo standard output e lo standard\n"
+"    input del comando connessi attraverso una pipe ai descrittori di file assegnati\n"
+"    agli indici 0 e 1 di una variabile di array NOME nella shell in esecuzione.\n"
+"    Il NOME predefinito è \"COPROC\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato di uscita del COMANDO."
+
+#: builtins.c:1634
+msgid ""
+"Define shell function.\n"
+"    \n"
+"    Create a shell function named NAME.  When invoked as a simple command,\n"
+"    NAME runs COMMANDs in the calling shell's context.  When NAME is invoked,\n"
+"    the arguments are passed to the function as $1...$n, and the function's\n"
+"    name is in $FUNCNAME.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless NAME is readonly."
+msgstr ""
+"Definisce una funzione di shell.\n"
+"    \n"
+"    Crea una funzione di shell chiamata NOME.  Quando invocato come un semplice comando,\n"
+"    NOME esegue i COMANDI nel contesto delle chiamate di shell.  Quando viene invocato NOME,\n"
+"    gli argomenti sono passati alla funzione come $1...$n e il nome della funzione si trova\n"
+"    in $FUNCNAME.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che il NOME non sia in sola lettura."
+
+#: builtins.c:1648
+msgid ""
+"Group commands as a unit.\n"
+"    \n"
+"    Run a set of commands in a group.  This is one way to redirect an\n"
+"    entire set of commands.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the last command executed."
+msgstr ""
+"Raggruppa i comandi come un'unità.\n"
+"    \n"
+"    Esegue un set di comandi in un gruppo.  Questo è un modo per reindirizzare un\n"
+"    intero set di comandi.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato dell'ultimo comando eseguito."
+
+#: builtins.c:1660
+msgid ""
+"Resume job in foreground.\n"
+"    \n"
+"    Equivalent to the JOB_SPEC argument to the `fg' command.  Resume a\n"
+"    stopped or background job.  JOB_SPEC can specify either a job name\n"
+"    or a job number.  Following JOB_SPEC with a `&' places the job in\n"
+"    the background, as if the job specification had been supplied as an\n"
+"    argument to `bg'.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns the status of the resumed job."
+msgstr ""
+"Ripristina un job in primo piano.\n"
+"    \n"
+"    Equivale all'argomento SPEC_JOB per il comando \"fg\".  Ripristina\n"
+"    un job fermato o sullo sfondo.  SPEC_JOB può specificare un nome\n"
+"    job o un numero di job.  SPEC_JOB seguito da \"&\" mette il job\n"
+"    sullo sfondo, come se la specifica del job fosse stata fornita\n"
+"    come argomento per \"bg\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce lo stato del job ripristinato."
+
+#: builtins.c:1675
+msgid ""
+"Evaluate arithmetic expression.\n"
+"    \n"
+"    The EXPRESSION is evaluated according to the rules for arithmetic\n"
+"    evaluation.  Equivalent to \"let EXPRESSION\".\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise."
+msgstr ""
+"Valuta espressioni aritmetiche.\n"
+"    \n"
+"    L'ESPRESSIONE è valutata seguendo le regole di valutazione\n"
+"    aritmetica. Equivalente a \"let ESPRESSIONE\".\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce 1 se ESPRESSIONE è valutata 0, altrimenti restituisce 0."
+
+#: builtins.c:1687
+msgid ""
+"Execute conditional command.\n"
+"    \n"
+"    Returns a status of 0 or 1 depending on the evaluation of the conditional\n"
+"    expression EXPRESSION.  Expressions are composed of the same primaries used\n"
+"    by the `test' builtin, and may be combined using the following operators:\n"
+"    \n"
+"      ( EXPRESSION )\tReturns the value of EXPRESSION\n"
+"      ! EXPRESSION\t\tTrue if EXPRESSION is false; else false\n"
+"      EXPR1 && EXPR2\tTrue if both EXPR1 and EXPR2 are true; else false\n"
+"      EXPR1 || EXPR2\tTrue if either EXPR1 or EXPR2 is true; else false\n"
+"    \n"
+"    When the `==' and `!=' operators are used, the string to the right of\n"
+"    the operator is used as a pattern and pattern matching is performed.\n"
+"    When the `=~' operator is used, the string to the right of the operator\n"
+"    is matched as a regular expression.\n"
+"    \n"
+"    The && and || operators do not evaluate EXPR2 if EXPR1 is sufficient to\n"
+"    determine the expression's value.\n"
+"    \n"
+"    Exit Status:\n"
+"    0 or 1 depending on value of EXPRESSION."
+msgstr ""
+"Esegue comandi condizionali.\n"
+"    \n"
+"    Resituisce uno stato di 0 o 1 a seconda della valutazione dell'espressione\n"
+"    condizionale ESPRESSIONE.  Le espressioni sono composte dalle stesse basilari usate\n"
+"    dal comando interno \"test\", e possono essere combinate usando i seguenti operatori:\n"
+"    \n"
+"      ( ESPRESSIONE )\tRestituisce il valore dell'ESPRESSIONE\n"
+"      ! ESPRESSIONE\t\tVero se l'ESPRESSIONE è falsa; falso in caso contrario\n"
+"      ESPR1 && ESPR2\tVero se sia ESPR1 che ESPR2 sono vere; falso in caso contrario\n"
+"      ESPR1 || ESPR2\tVero se una tra ESPR1 ed ESPR2 è vera; falso in caso contrario\n"
+"    \n"
+"    Quando vengono usati gli operatori \"==\" e \"!=\", la stringa a destra dell'operatore\n"
+"    è usata come un modello e ne viene effettuata la corrispondenza.\n"
+"    Quando viene usato l'operatore \"=~\", la stringa a destra dell'operatore è valutata\n"
+"    corrispondente a un'espressione regolare.\n"
+"    \n"
+"    Gli operatori && e || non valutano ESPR2 se ESPR1 è sufficiente a\n"
+"    determinare il valore dell'espressione.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    0 o 1 a seconda del valore dell'ESPRESSIONE."
+
+#: builtins.c:1713
+msgid ""
+"Common shell variable names and usage.\n"
+"    \n"
+"    BASH_VERSION\tVersion information for this Bash.\n"
+"    CDPATH\tA colon-separated list of directories to search\n"
+"    \t\tfor directories given as arguments to `cd'.\n"
+"    GLOBIGNORE\tA colon-separated list of patterns describing filenames to\n"
+"    \t\tbe ignored by pathname expansion.\n"
+"    HISTFILE\tThe name of the file where your command history is stored.\n"
+"    HISTFILESIZE\tThe maximum number of lines this file can contain.\n"
+"    HISTSIZE\tThe maximum number of history lines that a running\n"
+"    \t\tshell can access.\n"
+"    HOME\tThe complete pathname to your login directory.\n"
+"    HOSTNAME\tThe name of the current host.\n"
+"    HOSTTYPE\tThe type of CPU this version of Bash is running under.\n"
+"    IGNOREEOF\tControls the action of the shell on receipt of an EOF\n"
+"    \t\tcharacter as the sole input.  If set, then the value\n"
+"    \t\tof it is the number of EOF characters that can be seen\n"
+"    \t\tin a row on an empty line before the shell will exit\n"
+"    \t\t(default 10).  When unset, EOF signifies the end of input.\n"
+"    MACHTYPE\tA string describing the current system Bash is running on.\n"
+"    MAILCHECK\tHow often, in seconds, Bash checks for new mail.\n"
+"    MAILPATH\tA colon-separated list of filenames which Bash checks\n"
+"    \t\tfor new mail.\n"
+"    OSTYPE\tThe version of Unix this version of Bash is running on.\n"
+"    PATH\tA colon-separated list of directories to search when\n"
+"    \t\tlooking for commands.\n"
+"    PROMPT_COMMAND\tA command to be executed before the printing of each\n"
+"    \t\tprimary prompt.\n"
+"    PS1\t\tThe primary prompt string.\n"
+"    PS2\t\tThe secondary prompt string.\n"
+"    PWD\t\tThe full pathname of the current directory.\n"
+"    SHELLOPTS\tA colon-separated list of enabled shell options.\n"
+"    TERM\tThe name of the current terminal type.\n"
+"    TIMEFORMAT\tThe output format for timing statistics displayed by the\n"
+"    \t\t`time' reserved word.\n"
+"    auto_resume\tNon-null means a command word appearing on a line by\n"
+"    \t\titself is first looked for in the list of currently\n"
+"    \t\tstopped jobs.  If found there, that job is foregrounded.\n"
+"    \t\tA value of `exact' means that the command word must\n"
+"    \t\texactly match a command in the list of stopped jobs.  A\n"
+"    \t\tvalue of `substring' means that the command word must\n"
+"    \t\tmatch a substring of the job.  Any other value means that\n"
+"    \t\tthe command must be a prefix of a stopped job.\n"
+"    histchars\tCharacters controlling history expansion and quick\n"
+"    \t\tsubstitution.  The first character is the history\n"
+"    \t\tsubstitution character, usually `!'.  The second is\n"
+"    \t\tthe `quick substitution' character, usually `^'.  The\n"
+"    \t\tthird is the `history comment' character, usually `#'.\n"
+"    HISTIGNORE\tA colon-separated list of patterns used to decide which\n"
+"    \t\tcommands should be saved on the history list.\n"
+msgstr ""
+"Nomi e usi comuni delle variabili di shell.\n"
+"    \n"
+"    BASH_VERSION\tInformazioni sulla versione di Bash.\n"
+"    CDPATH\tUn elenco di directory da cercare separate da un due punti\n"
+"    \tfornite come argomenti per \"cd\".\n"
+"    GLOBIGNORE\tUn elenco di modelli separato da un due punti che descrivono i nomi\n"
+"    \t\tdi file che devono essere ignorati dall'espansione di percorso.\n"
+"    HISTFILE\tIl nome del file in cui è memorizzata la cronologia dei comandi.\n"
+"    HISTFILESIZE\tIl numero massimo di righe che può contenere questo file.\n"
+"    HISTSIZE\tIl numero massimo di righe di cronologia a cui può accedere\n"
+"    \t\tuna shell in esecuzione.\n"
+"    HOME\tIl nome completo del percorso della propria directory di login.\n"
+"    HOSTNAME\tIl nome dell'host corrente.\n"
+"    HOSTTYPE\tIl tipo di cpu sulla quale è in esecuzione questa versione di bash.\n"
+"    IGNOREEOF\tControlla il comportamento della shell quando riceve un carattere EOF\n"
+"    \t\tcome unico input.  Se impostato, il suo valore corrisponde al numero\n"
+"    \t\tdi caratteri EOF che si possono trovare in una fila in una riga vuota\n"
+"    \t\tprima che la shell esca (predefinito 10).  Quando viene azzerato, EOF\n"
+"    \t\tindica la fine dell'input.\n"
+"    MACHTYPE\tUna stringa che descrive l'attuale sistema dove è in esecuzione bash.\n"
+"    MAILCHECK\tQuanto spesso, in secondi, Bash controlla la presenza di nuova posta.\n"
+"    MAILPATH\tUn elenco di nomi di file separati da un due punti usati da Bash per\n"
+"    \t\tcontrollare la presenza di nuova posta.\n"
+"    OSTYPE\tLa versione di Unix sulla quale è in esecuzione questa versione di bash.\n"
+"    PATH\tUn elenco di directory, separato da un due punti, da analizzare quando\n"
+"    \t\tsi cercano i comandi.\n"
+"    PROMPT_COMMAND\tUn comando da eseguire prima della stampa di ciascun prompt\n"
+"    \t\tprimario.\n"
+"    PS1\t\tLa stringa del prompt primario.\n"
+"    PS2\t\tLa stringa del prompt secondario.\n"
+"    PWD\t\tIl nome completo del percorso della directory corrente.\n"
+"    SHELLOPTS\tUn elenco di opzioni di shell abilitate, separate da un due punti.\n"
+"    TERM\tIl nome del tipo di terminale corrente.\n"
+"    TIMEFORMAT\tIl formato di output per le statistiche temporali visualizzato dalla\n"
+"    \t\tparola riservata \"time\".\n"
+"    auto_resume\tNon null significa che una parola di un comando che compare da\n"
+"    \t\taol in una riga viene prima cercata nell'elenco dei job correnti\n"
+"    \t\tfermati.  Se trovato, questo job viene messo in primo piano.\n"
+"    \t\tUn valore pari a \"exact\" significa che la parola del comando deve\n"
+"    \t\tcorrispondere esattamente a un comando nell'elenco dei job fermati.  Un\n"
+"    \t\tvalore pari a \"substring\" significa che la parola del comando deve\n"
+"    \t\tcorrispondere a una sottostringa del job.  Qualsiasi altro valore significa\n"
+"    \t\tche il comando deve essere un prefisso di un lavoro fermato.\n"
+"    histchars\tCaratteri che controllano l'espansione della cronologia e la sostituzione\n"
+"    \t\trapida.  Il primo carattere è quello di sostituzione della cronologia,\n"
+"    \t\tsolitamente \"!\".  Il secondo è il carattere di \"sostituzione rapida\",\n"
+"    \t\tsolitamente \"^\".  Il terzo è il carattere di \"commento della cronologia\",\n"
+"    \t\tsolitamente \"#\".\n"
+"    HISTIGNORE\tUn elenco di modelli separato da un due punti usato per decidere quale\n"
+"    \t\tcomando dovrebbe essere salvato nell'elenco della cronologia.\n"
+
+#: builtins.c:1770
+msgid ""
+"Add directories to stack.\n"
+"    \n"
+"    Adds a directory to the top of the directory stack, or rotates\n"
+"    the stack, making the new top of the stack the current working\n"
+"    directory.  With no arguments, exchanges the top two directories.\n"
+"    \n"
+"    Options:\n"
+"      -n\tSuppresses the normal change of directory when adding\n"
+"    \tdirectories to the stack, so only the stack is manipulated.\n"
+"    \n"
+"    Arguments:\n"
+"      +N\tRotates the stack so that the Nth directory (counting\n"
+"    \tfrom the left of the list shown by `dirs', starting with\n"
+"    \tzero) is at the top.\n"
+"    \n"
+"      -N\tRotates the stack so that the Nth directory (counting\n"
+"    \tfrom the right of the list shown by `dirs', starting with\n"
+"    \tzero) is at the top.\n"
+"    \n"
+"      dir\tAdds DIR to the directory stack at the top, making it the\n"
+"    \tnew current working directory.\n"
+"    \n"
+"    The `dirs' builtin displays the directory stack.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid argument is supplied or the directory\n"
+"    change fails."
+msgstr ""
+"Aggiunge directory allo stack.\n"
+"    \n"
+"    Aggiunge una directory in cima allo stack delle directory o ruota lo\n"
+"    stack stesso, mettendo come primo elemento la directory di lavoro\n"
+"    corrente. Senza argomenti scambia le prime due directory in cima.\n"
+"    \n"
+"    Opzioni:\n"
+"      -n\tEvita il normale cambio di directory quando vengono aggiunte\n"
+"    \tdirectory allo stack, così da manipolare solo lo stack stesso.\n"
+"    \n"
+"    Argomenti:\n"
+"      +N\tRuota lo stack in modo che l'N-sima directory (contando\n"
+"    \ta partire da sinistra dell'elenco mostrato da \"dirs\", iniziando da\n"
+"    \tzero) sia in cima.\n"
+"    \n"
+"      -N\tRuota lo stack in modo che l'N-sima directory (contando\n"
+"    \ta partire da destra dell'elenco mostrato da \"dirs\", iniziando da\n"
+"    \tzero) sia in cima.\n"
+"    \n"
+"      dir\tAggiunge DIR in cima allo stack delle directory, facendone la\n"
+"    \tdirectory di lavoro corrente.\n"
+"    \n"
+"    Il comando interno \"dirs\" mostra lo stack delle directory.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornito un argomento valido o non abbia\n"
+"    successo il cambio di directory."
+
+#: builtins.c:1804
+msgid ""
+"Remove directories from stack.\n"
+"    \n"
+"    Removes entries from the directory stack.  With no arguments, removes\n"
+"    the top directory from the stack, and changes to the new top directory.\n"
+"    \n"
+"    Options:\n"
+"      -n\tSuppresses the normal change of directory when removing\n"
+"    \tdirectories from the stack, so only the stack is manipulated.\n"
+"    \n"
+"    Arguments:\n"
+"      +N\tRemoves the Nth entry counting from the left of the list\n"
+"    \tshown by `dirs', starting with zero.  For example: `popd +0'\n"
+"    \tremoves the first directory, `popd +1' the second.\n"
+"    \n"
+"      -N\tRemoves the Nth entry counting from the right of the list\n"
+"    \tshown by `dirs', starting with zero.  For example: `popd -0'\n"
+"    \tremoves the last directory, `popd -1' the next to last.\n"
+"    \n"
+"    The `dirs' builtin displays the directory stack.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid argument is supplied or the directory\n"
+"    change fails."
+msgstr ""
+"Rimuove directory dallo stack.\n"
+"    \n"
+"    Rimuove voci dallo stack delle directory. Senza argomenti, rimuove\n"
+"     la directory in cima allo stack e cambia alla nuova prima directory.\n"
+"    \n"
+"    Opzioni:\n"
+"      -n\tEvita il normale cambio di directory quando vengono rimosse\n"
+"    \tdirectory dallo stack, così da manipolare solo lo stack stesso.\n"
+"    \n"
+"    Argomenti:\n"
+"      +N\tRimuove l'N-sima voce contando a partire da sinistra dell'elenco\n"
+"    \tmostrato da \"dirs\", iniziando da zero. Per esempio: \"popd +0\"\n"
+"    \trimuove la prima directory, \"popd +1\" la seconda.\n"
+"    \n"
+"      -N\tRimuove l'N-sima voce contando a partire da destra dell'elenco\n"
+"    \tmostrato da \"dirs\", iniziando da zero. Per esempio: \"popd -0\"\n"
+"    \trimuove l'ultima directory, \"popd -1\" la penultima.\n"
+"    \n"
+"    Il comando interno \"dirs\" mostra lo stack delle directory.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornito un argomento non valido o non\n"
+"    abbia successo il cambio di directory."
+
+#: builtins.c:1834
+msgid ""
+"Display directory stack.\n"
+"    \n"
+"    Display the list of currently remembered directories.  Directories\n"
+"    find their way onto the list with the `pushd' command; you can get\n"
+"    back up through the list with the `popd' command.\n"
+"    \n"
+"    Options:\n"
+"      -c\tclear the directory stack by deleting all of the elements\n"
+"      -l\tdo not print tilde-prefixed versions of directories relative\n"
+"    \tto your home directory\n"
+"      -p\tprint the directory stack with one entry per line\n"
+"      -v\tprint the directory stack with one entry per line prefixed\n"
+"    \twith its position in the stack\n"
+"    \n"
+"    Arguments:\n"
+"      +N\tDisplays the Nth entry counting from the left of the list shown by\n"
+"    \tdirs when invoked without options, starting with zero.\n"
+"    \n"
+"      -N\tDisplays the Nth entry counting from the right of the list shown by\n"
+"    \tdirs when invoked without options, starting with zero.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is supplied or an error occurs."
+msgstr ""
+"Visualizza lo stack delle directory.\n"
+"    \n"
+"    Visualizza l'elenco delle directory ricordate attualmente. Le directory\n"
+"    vengono inserite nell'elenco con il comando \"pushd\"; è possibile\n"
+"    andare a ritroso nell'elenco con il comando \"popd\".\n"
+"    \n"
+"    Opzioni:\n"
+"      -c\tPulisce lo stack delle directory eliminandone tutti gli elementi\n"
+"      -l\tNon stampa le directory con prefisso tilde relative alla propria\n"
+"    \tdirectory home\n"
+"      -p\tStampa lo stack delle directory una voce per riga\n"
+"      -v\tStampa lo stack delle directory una voce per riga usando come\n"
+"    \tprefisso la posizione nello stack\n"
+"    \n"
+"    Argomenti:\n"
+"      +N\tMostra l'N-sima voce contando a partire da sinistra dell'elenco\n"
+"    \tmostrato da dirs quando invocato senza opzioni, iniziando da zero.\n"
+"    \n"
+"      -N\tMostra l'N-sima voce contando a partire da destro dell'elenco\n"
+"    \tmostrato da dirs quando invocato senza opzioni, iniziando da zero.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita un'opzione non valida o si riscontri un errore."
+
+#: builtins.c:1863
+msgid ""
+"Set and unset shell options.\n"
+"    \n"
+"    Change the setting of each shell option OPTNAME.  Without any option\n"
+"    arguments, list all shell options with an indication of whether or not each\n"
+"    is set.\n"
+"    \n"
+"    Options:\n"
+"      -o\trestrict OPTNAMEs to those defined for use with `set -o'\n"
+"      -p\tprint each shell option with an indication of its status\n"
+"      -q\tsuppress output\n"
+"      -s\tenable (set) each OPTNAME\n"
+"      -u\tdisable (unset) each OPTNAME\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success if OPTNAME is enabled; fails if an invalid option is\n"
+"    given or OPTNAME is disabled."
+msgstr ""
+"Imposta le opzioni della shell.\n"
+"    \n"
+"    Cambia le impostazioni di ciascuna opzione di shell NOMEOPZ.  Senza argomenti\n"
+"    per le opzioni, elenca tutte le opzioni di shell indicando se sono o non sono\n"
+"    impostate.\n"
+"    \n"
+"    Opzioni:\n"
+"      -o\tLimita i NOMEOPZ a quelli definiti per essere usati con \"set -o\"\n"
+"      -p\tStampa ogni opzione di shell indicando il relativo stato\n"
+"      -q\tNon stampa l'output\n"
+"      -s\tAbilita (imposta) ciascun NOMEOPZ\n"
+"      -u\tDisabilita (elimina) ciascun NOMEOPZ\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo se NOMEOPZ è abilitato; insuccesso se viene fornita\n"
+"    una opzione non valida o NOMEOPZ è disabilitato."
+
+#: builtins.c:1884
+msgid ""
+"Formats and prints ARGUMENTS under control of the FORMAT.\n"
+"    \n"
+"    Options:\n"
+"      -v var\tassign the output to shell variable VAR rather than\n"
+"    \t\tdisplay it on the standard output\n"
+"    \n"
+"    FORMAT is a character string which contains three types of objects: plain\n"
+"    characters, which are simply copied to standard output; character escape\n"
+"    sequences, which are converted and copied to the standard output; and\n"
+"    format specifications, each of which causes printing of the next successive\n"
+"    argument.\n"
+"    \n"
+"    In addition to the standard format specifications described in printf(1)\n"
+"    and printf(3), printf interprets:\n"
+"    \n"
+"      %b\texpand backslash escape sequences in the corresponding argument\n"
+"      %q\tquote the argument in a way that can be reused as shell input\n"
+"      %(fmt)T output the date-time string resulting from using FMT as a format\n"
+"            string for strftime(3)\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or a write or assignment\n"
+"    error occurs."
+msgstr ""
+"Formatta e stampa gli ARGOMENTI come indicato dal FORMATO.\n"
+"    \n"
+"    Opzioni:\n"
+"      -v var\tAssegna l'output alla variabile di shell VAR invece\n"
+"    \t\tdi visualizzarlo sullo standard output\n"
+"    \n"
+"    FORMATO è una stringa di caratteri che contiene tre tipi di oggetto: caratteri\n"
+"    semplici, che sono semplicemente copiati sullo standard output; sequenze di escape\n"
+"    dei caratteri, che sono convertite e copiate sullo standard output;\n"
+"    specifiche di formato, ognuna delle quali provoca la stampa del successivo argomento\n"
+"    consecutivo.\n"
+"    \n"
+"    In aggiunta alle specifiche di formato standard descritte in printf(1)\n"
+"    e printf(3), printf interpreta:\n"
+"    \n"
+"      %b\tEspande le sequenze di escape di backslash nell'argomento corrispondente\n"
+"      %q\tQuota l'argomento in modo che possa essere riusato come input per la shell\n"
+"      %(fmt)T Visualizza la stringa della data/ora risultante dall'uso di FMT come stringa\n"
+"            di formato per strftime(3)\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita una opzione non valida o si riscontri\n"
+"    un errore di scrittura o assegnazione."
+
+#: builtins.c:1913
+msgid ""
+"Specify how arguments are to be completed by Readline.\n"
+"    \n"
+"    For each NAME, specify how arguments are to be completed.  If no options\n"
+"    are supplied, existing completion specifications are printed in a way that\n"
+"    allows them to be reused as input.\n"
+"    \n"
+"    Options:\n"
+"      -p\tprint existing completion specifications in a reusable format\n"
+"      -r\tremove a completion specification for each NAME, or, if no\n"
+"    \tNAMEs are supplied, all completion specifications\n"
+"      -D\tapply the completions and actions as the default for commands\n"
+"    \twithout any specific completion defined\n"
+"      -E\tapply the completions and actions to \"empty\" commands --\n"
+"    \tcompletion attempted on a blank line\n"
+"    \n"
+"    When completion is attempted, the actions are applied in the order the\n"
+"    uppercase-letter options are listed above.  The -D option takes\n"
+"    precedence over -E.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is supplied or an error occurs."
+msgstr ""
+"Specifica come gli argomenti debbano essere completati da Readline.\n"
+"    \n"
+"    Per ciascun NOME, specifica come gli argomenti debbano essere completati.  Se non\n"
+"    vengono fornite opzioni, le specifiche di completamento esistenti sono stampate in modo\n"
+"    che possano essere riusate come input.\n"
+"    \n"
+"    Opzioni:\n"
+"      -p\tStampa le specifiche di completamento esistenti in un formato riusabile\n"
+"      -r\tRimuove una specifica di completamento per ciascun NOME, oppure tutte\n"
+"    \tse non viene fornito alcun NOME\n"
+"      -D\tApplica i completamenti e le azioni come predefiniti per i comandi\n"
+"    \tsenza alcun completamento definito specifico\n"
+"      -E\tApplica i completamenti e le azioni ai comandi \"vuoti\" --\n"
+"    \tcompletamenti tentati su una riga vuota\n"
+"    \n"
+"    Quando viene tentato un completamento, le azioni sono applicate nell'ordine\n"
+"    in cui sono sopra elencate le opzioni a lettera maiuscola.\n"
+"    L'opzione -D ha precedenza su -E.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o si riscontri un errore."
+
+#: builtins.c:1941
+msgid ""
+"Display possible completions depending on the options.\n"
+"    \n"
+"    Intended to be used from within a shell function generating possible\n"
+"    completions.  If the optional WORD argument is supplied, matches against\n"
+"    WORD are generated.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is supplied or an error occurs."
+msgstr ""
+"Visualizza i possibili completamenti a seconda delle opzioni.\n"
+"    \n"
+"    È pensata per essere usata all'interno di una funzione di shell per generare\n"
+"    dei possibili completamenti.  Se viene fornito l'argomento opzionale PAROLA,\n"
+"    vengono generate le corrispondenze relative a PAROLA.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non sia fornita una opzione non valida o si riscontri un errore."
+
+#: builtins.c:1956
+msgid ""
+"Modify or display completion options.\n"
+"    \n"
+"    Modify the completion options for each NAME, or, if no NAMEs are supplied,\n"
+"    the completion currently being executed.  If no OPTIONs are given, print\n"
+"    the completion options for each NAME or the current completion specification.\n"
+"    \n"
+"    Options:\n"
+"    \t-o option\tSet completion option OPTION for each NAME\n"
+"    \t-D\t\tChange options for the \"default\" command completion\n"
+"    \t-E\t\tChange options for the \"empty\" command completion\n"
+"    \n"
+"    Using `+o' instead of `-o' turns off the specified option.\n"
+"    \n"
+"    Arguments:\n"
+"    \n"
+"    Each NAME refers to a command for which a completion specification must\n"
+"    have previously been defined using the `complete' builtin.  If no NAMEs\n"
+"    are supplied, compopt must be called by a function currently generating\n"
+"    completions, and the options for that currently-executing completion\n"
+"    generator are modified.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is supplied or NAME does not\n"
+"    have a completion specification defined."
+msgstr ""
+"Modifica o visualizza le opzioni di completamento.\n"
+"    \n"
+"    Modifica le opzioni di completamento per ciascun NOME, oppure, se non viene fornito alcun NOME,\n"
+"    il completamento attualmente in esecuzione.  Con nessuna OPZIONE fornita, stampa\n"
+"    le opzioni di completamento per ciascun NOME o le specifiche di completamento correnti.\n"
+"    \n"
+"    Opzioni:\n"
+"    \t-o opzione\tImposta l'OPZIONE di completamento per ciascun NOME\n"
+"    \t-D\t\tCambia le opzioni per il completamento di comando \"predefinito\"\n"
+"    \t-E\t\tCambia le opzioni per il completamento di comando \"vuoto\"\n"
+"    \n"
+"    Usando \"+o\" al posto di \"-o\" disabilita l'opzione specificata.\n"
+"    \n"
+"    Argomenti:\n"
+"    \n"
+"    Ciascun NOME si riferisce a un comando per il quale deve essere stata precedentemente\n"
+"    definita una specifica di completamento con il comando interno \"complete\".  Se non viene fornito\n"
+"    alcun NOME, compopt deve essere richiamato da una funzione che generi attualmente\n"
+"    completamenti, e le opzioni per questo generatore di completamenti attualmente\n"
+"    in esecuzione sono modificate\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita una opzione non valida o NOME non\n"
+"    abbia una specifica di completamento definita."
+
+#: builtins.c:1986
+msgid ""
+"Read lines from the standard input into an indexed array variable.\n"
+"    \n"
+"    Read lines from the standard input into the indexed array variable ARRAY, or\n"
+"    from file descriptor FD if the -u option is supplied.  The variable MAPFILE\n"
+"    is the default ARRAY.\n"
+"    \n"
+"    Options:\n"
+"      -n count\tCopy at most COUNT lines.  If COUNT is 0, all lines are copied.\n"
+"      -O origin\tBegin assigning to ARRAY at index ORIGIN.  The default index is 0.\n"
+"      -s count \tDiscard the first COUNT lines read.\n"
+"      -t\t\tRemove a trailing newline from each line read.\n"
+"      -u fd\t\tRead lines from file descriptor FD instead of the standard input.\n"
+"      -C callback\tEvaluate CALLBACK each time QUANTUM lines are read.\n"
+"      -c quantum\tSpecify the number of lines read between each call to CALLBACK.\n"
+"    \n"
+"    Arguments:\n"
+"      ARRAY\t\tArray variable name to use for file data.\n"
+"    \n"
+"    If -C is supplied without -c, the default quantum is 5000.  When\n"
+"    CALLBACK is evaluated, it is supplied the index of the next array\n"
+"    element to be assigned and the line to be assigned to that element\n"
+"    as additional arguments.\n"
+"    \n"
+"    If not supplied with an explicit origin, mapfile will clear ARRAY before\n"
+"    assigning to it.\n"
+"    \n"
+"    Exit Status:\n"
+"    Returns success unless an invalid option is given or ARRAY is readonly or\n"
+"    not an indexed array."
+msgstr ""
+"Legge righe dallo standard input in una variabile di array indicizzato.\n"
+"    \n"
+"    Legge righe dallo standard input nella variabile di ARRAY indicizzato, oppure\n"
+"    dal descrittore di file FD se viene fornita l'opzione -u.  La variabile MAPFILE\n"
+"    è l'ARRAY predefinito.\n"
+"    \n"
+"    Opzioni:\n"
+"      -n numero\t\tCopia al massimo un NUMERO di righe.  Se NUMERO è 0, vengono copiate tutte.\n"
+"      -O origine\tInizia assegnando all'ARRAY all'indice ORIGINE.  L'indice predefinito è 0.\n"
+"      -s numero \tScarta le prime NUMERO righe lette.\n"
+"      -t\t\tRimuove un ritorno a capo finale da ciascuna riga letta.\n"
+"      -u fd\t\tLegge le righe da un descrittore di file FD invece che dallo standard input.\n"
+"      -C callback\tEsamina CALLBACK ogni volta che vengono lette un numero QUANTO di righe.\n"
+"      -c quantità\tSpecifica il numero di righe lette tra ciascuna chiamata a CALLBACK.\n"
+"    \n"
+"    Argomenti:\n"
+"      ARRAY\t\tNome della variabile di array da usare per i dati dei file.\n"
+"    \n"
+"    Se viene fornito -C senza -c, il quanto predefinito è 5000.  Quando\n"
+"    viene analizzata CALLBACK, viene fornito l'indice dell'elemento di\n"
+"    array successivo da assegnare e la riga da attribuire a quell'elemento\n"
+"    come argomenti aggiuntivi.\n"
+"    \n"
+"    Se non viene fornito con una origine esplicita, il file di mappa azzererà l'ARRAY\n"
+"    prima della relativa assegnazione.\n"
+"    \n"
+"    Stato di uscita:\n"
+"    Restituisce successo a meno che non venga fornita una opzione non valida, ARRAY sia\n"
+"    in sola lettura oppure non indicizzato."
+
+#: builtins.c:2020
+msgid ""
+"Read lines from a file into an array variable.\n"
+"    \n"
+"    A synonym for `mapfile'."
+msgstr ""
+"Legge le righe da un file in una variabile di array.\n"
+"    \n"
+"    Sinonimo per \"mapfile\"."
index 7c3f39064cc6b10aff317dfd2686ddfa6b0917f0..6788ea82de4720f7e3ae1b83e9e2547cce8e6938 100644 (file)
--- a/po/nl.po
+++ b/po/nl.po
@@ -1,4 +1,4 @@
-# Dutch translations GNU for bash.
+# Dutch translations for GNU bash.
 # Copyright (C) 2011 Free Software Foundation, Inc.
 # This file is distributed under the same license as the bash package.
 #
@@ -24,7 +24,7 @@ msgstr ""
 "Project-Id-Version: bash-4.2\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2011-01-28 22:09-0500\n"
-"PO-Revision-Date: 2011-02-17 21:14+0100\n"
+"PO-Revision-Date: 2011-10-01 21:14+0100\n"
 "Last-Translator: Benno Schulenberg <benno@vertaalt.nl>\n"
 "Language-Team: Dutch <vertaling@vrijschrift.org>\n"
 "Language: nl\n"
@@ -686,8 +686,8 @@ msgstr ""
 "           de lijst getoond door 'dirs', beginned bij nul) bovenaan komt.\n"
 "      -N   Roteert de stapel zodat de N-de map (tellend vanaf rechts, van\n"
 "           de lijst getoond door 'dirs', beginned bij nul) bovenaan komt.\n"
-"      MAP  Voegt deze map toe aan de top van de mappenstapel, het de nieuwe\n"
-"           werkmap makend.\n"
+"      MAP  Voegt deze map toe aan de top van de mappenstapel, en maakt het\n"
+"           de nieuwe werkmap.\n"
 "\n"
 "    De opdracht 'dirs' toont de huidige mappenstapel."
 
@@ -2015,13 +2015,15 @@ msgstr "pwd [-LP]"
 msgid ":"
 msgstr ":"
 
+# Dit is een commandonaam.
 #: builtins.c:70
 msgid "true"
-msgstr "waar"
+msgstr "true"
 
+# Dit is een commandonaam.
 #: builtins.c:72
 msgid "false"
-msgstr "onwaar"
+msgstr "false"
 
 #: builtins.c:74
 msgid "command [-pVv] command [arg ...]"
@@ -2073,9 +2075,7 @@ msgstr "logout [N]"
 
 #: builtins.c:103
 msgid "fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]"
-msgstr ""
-"fc [-e EDITORNAAM] [-lnr] [EERSTE] [LAATSTE]\n"
-"of: fc -s [PATROON=VERVANGING] [OPDRACHT]"
+msgstr "fc [-e EDITORNAAM] [-lnr] [EERSTE] [LAATSTE]  of: fc -s [PATROON=VERVANGING] [OPDRACHT]"
 
 #: builtins.c:107
 msgid "fg [job_spec]"
@@ -2095,14 +2095,11 @@ msgstr "help [-dms] [PATROON...]"
 
 #: builtins.c:121
 msgid "history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]"
-msgstr ""
-"history [-c] [-d POSITIE] [N]\n"
-"     of: history -anrw [BESTANDSNAAM]\n"
-"     of: history -ps ARGUMENT..."
+msgstr "history [-c] [-d POSITIE] [N]  of: history -anrw [BESTANDSNAAM]  of: history -ps ARGUMENT..."
 
 #: builtins.c:125
 msgid "jobs [-lnprs] [jobspec ...] or jobs -x command [args]"
-msgstr "jobs [-lnprs] [TAAKAANDUIDING...]   of   jobs -x OPDRACHT [ARGUMENT...]"
+msgstr "jobs [-lnprs] [TAAKAANDUIDING...]  of: jobs -x OPDRACHT [ARGUMENT...]"
 
 #: builtins.c:129
 msgid "disown [-h] [-ar] [jobspec ...]"
@@ -2121,9 +2118,9 @@ msgstr "let ARGUMENT..."
 #: builtins.c:136
 msgid "read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]"
 msgstr ""
-"read [-ers] [-a ARRAY] [-d SCHEIDINGSTEKEN] [-i TEKST]\n"
-"           [-n AANTAL_TEKENS] [-N AANTAL_TEKENS] [-p PROMPT]\n"
-"           [-t TIJDSLIMIET] [-u BESTANDSDESCRIPTOR] [NAAM...]"
+"read [-ers] [-a ARRAY] [-d SCHEIDINGSTEKEN] [-i TEKST] [-p PROMPT]\n"
+"           [-n AANTAL_TEKENS] [-N AANTAL_TEKENS] [-t TIJDSLIMIET]\n"
+"           [-u BESTANDSDESCRIPTOR]  [NAAM...]"
 
 #: builtins.c:138
 msgid "return [n]"
@@ -2167,7 +2164,7 @@ msgstr "test [EXPRESSIE]"
 
 #: builtins.c:160
 msgid "[ arg... ]"
-msgstr "[ ARGUMENT... ]"
+msgstr "[ EXPRESSIE... ]"
 
 #: builtins.c:162
 msgid "times"
@@ -2219,10 +2216,7 @@ msgstr "case WOORD in [PATROON [| PATROON]...) OPDRACHTEN ;;]... esac"
 
 #: builtins.c:192
 msgid "if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi"
-msgstr ""
-"if OPDRACHTEN; then OPDRACHTEN;\n"
-"  [ elif OPDRACHTEN; then OPDRACHTEN; ]...\n"
-"  [ else OPDRACHTEN; ] fi"
+msgstr "if OPDRACHTEN; then OPDRACHTEN; [elif OPDRACHTEN; then OPDRACHTEN;]... [else OPDRACHTEN;] fi"
 
 #: builtins.c:194
 msgid "while COMMANDS; do COMMANDS; done"
@@ -2283,16 +2277,16 @@ msgstr "printf [-v VARIABELE] OPMAAK [ARGUMENTEN]"
 #: builtins.c:229
 msgid "complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]"
 msgstr ""
-"complete [-abcdefgjksuv] [-pr] [-DE] [-o OPTIE] [-A ACTIE]\n"
-"                   [-C OPDRACHT] [-F FUNCTIE] [-G PATROON] [-P PREFIX]\n"
-"                   [-S SUFFIX] [-W WOORDENLIJST] [-X FILTERPATROON]  [NAAM...]"
+"complete [-abcdefgjksuv] [-pr] [-DE] [-o OPTIE] [-A ACTIE] [-C OPDRACHT]\n"
+"                   [-F FUNCTIE] [-G PATROON] [-P PREFIX] [-S SUFFIX]\n"
+"                   [-W WOORDENLIJST] [-X FILTERPATROON]  [NAAM...]"
 
 #: builtins.c:233
 msgid "compgen [-abcdefgjksuv] [-o option]  [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]"
 msgstr ""
-"compgen [-abcdefgjksuv] [-o OPTIE] [-A ACTIE] [-C OPDRACHT]\n"
-"                 [-F FUNCTIE] [-G PATROON] [-P PREFIX] [-S SUFFIX]\n"
-"                 [-W WOORDENLIJST] [-X FILTERPATROON]  [WOORD]"
+"compgen [-abcdefgjksuv] [-o OPTIE] [-A ACTIE] [-C OPDRACHT] [-F FUNCTIE]\n"
+"                  [-G PATROON] [-P PREFIX] [-S SUFFIX]\n"
+"                  [-W WOORDENLIJST] [-X FILTERPATROON]  [WOORD]"
 
 #: builtins.c:237
 msgid "compopt [-o|+o option] [-DE] [name ...]"
@@ -4637,7 +4631,7 @@ msgid ""
 "    Exit Status:\n"
 "    0 or 1 depending on value of EXPRESSION."
 msgstr ""
-"Een voorwaardelijke opdracht uitveoren.\n"
+"Een voorwaardelijke opdracht uitvoeren.\n"
 "\n"
 "    Evalueert de gegeven conditionele expressie; afhankelijk van het resultaat\n"
 "    is de afsluitwaarde 0 (\"waar\") of 1 (\"onwaar\").  De expressies bestaan uit\n"
@@ -5144,7 +5138,7 @@ msgid ""
 msgstr ""
 "Regels inlezen in een geïndexeerde array-variabele.\n"
 "\n"
-"    Leest regels van standaardinvoer in in the array-variabele ARRAY.\n"
+"    Leest regels van standaardinvoer in in de array-variabele ARRAY.\n"
 "    De variabele MAPFILE wordt gebruikt als geen ARRAY gegeven is.\n"
 "\n"
 "    Opties:\n"
index d4823edf5b9501acf00afb2a14ce4e4f3554c248..3ceccc6645903f953ca0ebbc8c393d486cda2330 100644 (file)
@@ -419,7 +419,7 @@ indirection_level_string ()
   register int i, j;
   char *ps4;
   char ps4_firstc[MB_LEN_MAX+1];
-  int ps4_firstc_len, ps4_len, ineed;
+  int ps4_firstc_len, ps4_len, ineed, old;
 
   ps4 = get_string_value ("PS4");
   if (indirection_string == 0)
@@ -429,9 +429,10 @@ indirection_level_string ()
   if (ps4 == 0 || *ps4 == '\0')
     return (indirection_string);
 
-  change_flag ('x', FLAG_OFF);
+  old = change_flag ('x', FLAG_OFF);
   ps4 = decode_prompt_string (ps4);
-  change_flag ('x', FLAG_ON);
+  if (old == FLAG_ON)
+    change_flag ('x', FLAG_ON);
 
   if (ps4 == 0 || *ps4 == '\0')
     return (indirection_string);
index dbb566d18f9a956ff261c7211066bb2c829a8006..056892d4106077d9df3db37289fb05c03606d4a2 100644 (file)
@@ -130,8 +130,10 @@ value = new1 new2 new3
 ./array.tests: line 239: narray: unbound variable
 ./array1.sub: line 1: syntax error near unexpected token `('
 ./array1.sub: line 1: `printf "%s\n" -a a=(a 'b  c')'
-./array2.sub: line 1: syntax error near unexpected token `('
-./array2.sub: line 1: `declare -a ''=(a 'b c')'
+./array2.sub: line 1: declare: `[]=asdf': not a valid identifier
+./array2.sub: line 2: a[]: bad array subscript
+./array2.sub: line 4: syntax error near unexpected token `('
+./array2.sub: line 4: `declare -a ''=(a 'b c')'
 9
 9
 
index 0e6417d7a0514aad11140d42efb480f363ea63e8..44bb7c5b76a711f1fe3f4b21ab40a04fe1770b8a 100644 (file)
@@ -1 +1,4 @@
+declare -r []=asdf
+declare -r a[]=asdf
+
 declare -a ''=(a 'b c')
index f816c63b734b0f76f5cc004c47c1d90016064979..12b944b1443026fdc3dfc633fbab6950660642c5 100644 (file)
@@ -139,3 +139,4 @@ bix ()
     echo foo 2>&1 | cat
 }
 foo
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
index 37759b5aa4abf81472b5435f33e41ef2f3e2a42a..c2e48663fb079e678b16d6816b8e0763c05a9b38 100644 (file)
@@ -187,3 +187,5 @@ exec 2>&9
 exec 9>&-
 
 ${THIS_SH} ./redir9.sub
+
+${THIS_SH} ./redir10.sub
diff --git a/tests/redir10.sub b/tests/redir10.sub
new file mode 100644 (file)
index 0000000..27c48e8
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Out of file descriptors, because it forgets to close redirection.  Only
+# happens in a shell function.  Problem through bash-4.2.
+
+ulimit -n 128
+
+bug()
+{
+c=`ulimit -n`
+let c+=100
+while let c--
+do
+       while read -ru3 x
+       do
+               echo -n :
+       done 3< <(echo x)
+
+done
+}
+
+bug
+echo
+
+exit 0
index 7bb850fabdf2a5bb553256cbc6760078f9fc80fb..85f7bb4f2061343bc0789a9489310d1c6362fc4f 100644 (file)
@@ -1,6 +1,6 @@
 /* variables.c -- Functions for hacking shell variables. */
 
-/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -310,7 +310,7 @@ initialize_shell_variables (env, privmode)
      int privmode;
 {
   char *name, *string, *temp_string;
-  int c, char_index, string_index, string_length;
+  int c, char_index, string_index, string_length, ro;
   SHELL_VAR *temp_var;
 
   create_variable_tables ();
@@ -386,6 +386,14 @@ initialize_shell_variables (env, privmode)
       else
 #endif
        {
+         ro = 0;
+         if (posixly_correct && STREQ (name, "SHELLOPTS"))
+           {
+             temp_var = find_variable ("SHELLOPTS");
+             ro = temp_var && readonly_p (temp_var);
+             if (temp_var)
+               VUNSETATTR (temp_var, att_readonly);
+           }
          temp_var = bind_variable (name, string, 0);
          if (temp_var)
            {
@@ -393,6 +401,8 @@ initialize_shell_variables (env, privmode)
                VSETATTR (temp_var, (att_exported | att_imported));
              else
                VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
+             if (ro)
+               VSETATTR (temp_var, att_readonly);
              array_needs_making = 1;
            }
        }
diff --git a/variables.c~ b/variables.c~
new file mode 100644 (file)
index 0000000..98d7516
--- /dev/null
@@ -0,0 +1,4822 @@
+/* variables.c -- Functions for hacking shell variables. */
+
+/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "bashtypes.h"
+#include "posixstat.h"
+#include "posixtime.h"
+
+#if defined (__QNX__)
+#  if defined (__QNXNTO__)
+#    include <sys/netmgr.h>
+#  else
+#    include <sys/vc.h>
+#  endif /* !__QNXNTO__ */
+#endif /* __QNX__ */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include "chartypes.h"
+#if defined (HAVE_PWD_H)
+#  include <pwd.h>
+#endif
+#include "bashansi.h"
+#include "bashintl.h"
+
+#define NEED_XTRACE_SET_DECL
+
+#include "shell.h"
+#include "flags.h"
+#include "execute_cmd.h"
+#include "findcmd.h"
+#include "mailcheck.h"
+#include "input.h"
+#include "hashcmd.h"
+#include "pathexp.h"
+#include "alias.h"
+
+#include "builtins/getopt.h"
+#include "builtins/common.h"
+
+#if defined (READLINE)
+#  include "bashline.h"
+#  include <readline/readline.h>
+#else
+#  include <tilde/tilde.h>
+#endif
+
+#if defined (HISTORY)
+#  include "bashhist.h"
+#  include <readline/history.h>
+#endif /* HISTORY */
+
+#if defined (PROGRAMMABLE_COMPLETION)
+#  include "pcomplete.h"
+#endif
+
+#define TEMPENV_HASH_BUCKETS   4       /* must be power of two */
+
+#define ifsname(s)     ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
+
+extern char **environ;
+
+/* Variables used here and defined in other files. */
+extern int posixly_correct;
+extern int line_number, line_number_base;
+extern int subshell_environment, indirection_level, subshell_level;
+extern int build_version, patch_level;
+extern int expanding_redir;
+extern char *dist_version, *release_status;
+extern char *shell_name;
+extern char *primary_prompt, *secondary_prompt;
+extern char *current_host_name;
+extern sh_builtin_func_t *this_shell_builtin;
+extern SHELL_VAR *this_shell_function;
+extern char *the_printed_command_except_trap;
+extern char *this_command_name;
+extern char *command_execution_string;
+extern time_t shell_start_time;
+extern int assigning_in_environment;
+extern int executing_builtin;
+extern int funcnest_max;
+
+#if defined (READLINE)
+extern int no_line_editing;
+extern int perform_hostname_completion;
+#endif
+
+/* The list of shell variables that the user has created at the global
+   scope, or that came from the environment. */
+VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
+
+/* The current list of shell variables, including function scopes */
+VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
+
+/* The list of shell functions that the user has created, or that came from
+   the environment. */
+HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
+
+#if defined (DEBUGGER)
+/* The table of shell function definitions that the user defined or that
+   came from the environment. */
+HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
+#endif
+
+/* The current variable context.  This is really a count of how deep into
+   executing functions we are. */
+int variable_context = 0;
+
+/* The set of shell assignments which are made only in the environment
+   for a single command. */
+HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
+
+/* Set to non-zero if an assignment error occurs while putting variables
+   into the temporary environment. */
+int tempenv_assign_error;
+
+/* Some funky variables which are known about specially.  Here is where
+   "$*", "$1", and all the cruft is kept. */
+char *dollar_vars[10];
+WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
+
+/* The value of $$. */
+pid_t dollar_dollar_pid;
+
+/* Non-zero means that we have to remake EXPORT_ENV. */
+int array_needs_making = 1;
+
+/* The number of times BASH has been executed.  This is set
+   by initialize_variables (). */
+int shell_level = 0;
+
+/* An array which is passed to commands as their environment.  It is
+   manufactured from the union of the initial environment and the
+   shell variables that are marked for export. */
+char **export_env = (char **)NULL;
+static int export_env_index;
+static int export_env_size;
+
+#if defined (READLINE)
+static int winsize_assignment;         /* currently assigning to LINES or COLUMNS */
+#endif
+
+/* Some forward declarations. */
+static void create_variable_tables __P((void));
+
+static void set_machine_vars __P((void));
+static void set_home_var __P((void));
+static void set_shell_var __P((void));
+static char *get_bash_name __P((void));
+static void initialize_shell_level __P((void));
+static void uidset __P((void));
+#if defined (ARRAY_VARS)
+static void make_vers_array __P((void));
+#endif
+
+static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
+#if defined (ARRAY_VARS)
+static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t, char *));
+#endif
+static SHELL_VAR *get_self __P((SHELL_VAR *));
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
+static SHELL_VAR *init_dynamic_assoc_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
+#endif
+
+static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_seconds __P((SHELL_VAR *));
+static SHELL_VAR *init_seconds_var __P((void));
+
+static int brand __P((void));
+static void sbrand __P((unsigned long));               /* set bash random number generator. */
+static void seedrand __P((void));                      /* seed generator randomly */
+static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_random __P((SHELL_VAR *));
+
+static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_lineno __P((SHELL_VAR *));
+
+static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_subshell __P((SHELL_VAR *));
+
+static SHELL_VAR *get_bashpid __P((SHELL_VAR *));
+
+#if defined (HISTORY)
+static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
+#endif
+
+#if defined (READLINE)
+static SHELL_VAR *get_comp_wordbreaks __P((SHELL_VAR *));
+static SHELL_VAR *assign_comp_wordbreaks __P((SHELL_VAR *, char *, arrayind_t, char *));
+#endif
+
+#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t, char *));
+static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
+#endif
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *get_groupset __P((SHELL_VAR *));
+
+static SHELL_VAR *build_hashcmd __P((SHELL_VAR *));
+static SHELL_VAR *get_hashcmd __P((SHELL_VAR *));
+static SHELL_VAR *assign_hashcmd __P((SHELL_VAR *,  char *, arrayind_t, char *));
+#  if defined (ALIAS)
+static SHELL_VAR *build_aliasvar __P((SHELL_VAR *));
+static SHELL_VAR *get_aliasvar __P((SHELL_VAR *));
+static SHELL_VAR *assign_aliasvar __P((SHELL_VAR *,  char *, arrayind_t, char *));
+#  endif
+#endif
+
+static SHELL_VAR *get_funcname __P((SHELL_VAR *));
+static SHELL_VAR *init_funcname_var __P((void));
+
+static void initialize_dynamic_variables __P((void));
+
+static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
+static SHELL_VAR *new_shell_variable __P((const char *));
+static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
+static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
+
+static void dispose_variable_value __P((SHELL_VAR *));
+static void free_variable_hash_data __P((PTR_T));
+
+static VARLIST *vlist_alloc __P((int));
+static VARLIST *vlist_realloc __P((VARLIST *, int));
+static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
+
+static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
+
+static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
+
+static SHELL_VAR **vapply __P((sh_var_map_func_t *));
+static SHELL_VAR **fapply __P((sh_var_map_func_t *));
+
+static int visible_var __P((SHELL_VAR *));
+static int visible_and_exported __P((SHELL_VAR *));
+static int export_environment_candidate __P((SHELL_VAR *));
+static int local_and_exported __P((SHELL_VAR *));
+static int variable_in_context __P((SHELL_VAR *));
+#if defined (ARRAY_VARS)
+static int visible_array_vars __P((SHELL_VAR *));
+#endif
+
+static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
+static void push_temp_var __P((PTR_T));
+static void propagate_temp_var __P((PTR_T));
+static void dispose_temporary_env __P((sh_free_func_t *));     
+
+static inline char *mk_env_string __P((const char *, const char *));
+static char **make_env_array_from_var_list __P((SHELL_VAR **));
+static char **make_var_export_array __P((VAR_CONTEXT *));
+static char **make_func_export_array __P((void));
+static void add_temp_array_to_env __P((char **, int, int));
+
+static int n_shell_variables __P((void));
+static int set_context __P((SHELL_VAR *));
+
+static void push_func_var __P((PTR_T));
+static void push_exported_var __P((PTR_T));
+
+static inline int find_special_var __P((const char *));
+
+static void
+create_variable_tables ()
+{
+  if (shell_variables == 0)
+    {
+      shell_variables = global_variables = new_var_context ((char *)NULL, 0);
+      shell_variables->scope = 0;
+      shell_variables->table = hash_create (0);
+    }
+
+  if (shell_functions == 0)
+    shell_functions = hash_create (0);
+
+#if defined (DEBUGGER)
+  if (shell_function_defs == 0)
+    shell_function_defs = hash_create (0);
+#endif
+}
+
+/* Initialize the shell variables from the current environment.
+   If PRIVMODE is nonzero, don't import functions from ENV or
+   parse $SHELLOPTS. */
+void
+initialize_shell_variables (env, privmode)
+     char **env;
+     int privmode;
+{
+  char *name, *string, *temp_string;
+  int c, char_index, string_index, string_length, ro;
+  SHELL_VAR *temp_var;
+
+  create_variable_tables ();
+
+  for (string_index = 0; string = env[string_index++]; )
+    {
+      char_index = 0;
+      name = string;
+      while ((c = *string++) && c != '=')
+       ;
+      if (string[-1] == '=')
+       char_index = string - name - 1;
+
+      /* If there are weird things in the environment, like `=xxx' or a
+        string without an `=', just skip them. */
+      if (char_index == 0)
+       continue;
+
+      /* ASSERT(name[char_index] == '=') */
+      name[char_index] = '\0';
+      /* Now, name = env variable name, string = env variable value, and
+        char_index == strlen (name) */
+
+      temp_var = (SHELL_VAR *)NULL;
+
+      /* If exported function, define it now.  Don't import functions from
+        the environment in privileged mode. */
+      if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
+       {
+         string_length = strlen (string);
+         temp_string = (char *)xmalloc (3 + string_length + char_index);
+
+         strcpy (temp_string, name);
+         temp_string[char_index] = ' ';
+         strcpy (temp_string + char_index + 1, string);
+
+         parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
+
+         /* Ancient backwards compatibility.  Old versions of bash exported
+            functions like name()=() {...} */
+         if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
+           name[char_index - 2] = '\0';
+
+         if (temp_var = find_function (name))
+           {
+             VSETATTR (temp_var, (att_exported|att_imported));
+             array_needs_making = 1;
+           }
+         else
+           report_error (_("error importing function definition for `%s'"), name);
+
+         /* ( */
+         if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
+           name[char_index - 2] = '(';         /* ) */
+       }
+#if defined (ARRAY_VARS)
+#  if 0
+      /* Array variables may not yet be exported. */
+      else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
+       {
+         string_length = 1;
+         temp_string = extract_array_assignment_list (string, &string_length);
+         temp_var = assign_array_from_string (name, temp_string);
+         FREE (temp_string);
+         VSETATTR (temp_var, (att_exported | att_imported));
+         array_needs_making = 1;
+       }
+#  endif
+#endif
+#if 0
+      else if (legal_identifier (name))
+#else
+      else
+#endif
+       {
+         ro = 0;
+         if (posixly_correct && STREQ (name, "SHELLOPTS"))
+           {
+             temp_var = find_variable ("SHELLOPTS");
+             ro = temp_var && readonly_p (temp_var);
+             if (temp_var)
+               VUNSETATTR (temp_var, att_readonly);
+           }
+         temp_var = bind_variable (name, string, 0);
+         if (temp_var)
+           {
+             if (legal_identifier (name))
+               VSETATTR (temp_var, (att_exported | att_imported));
+             else
+               VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
+             if (ro)
+               VSETATTR (temp_var, att_readonly);
+             array_needs_making = 1;
+           }
+       }
+
+      name[char_index] = '=';
+      /* temp_var can be NULL if it was an exported function with a syntax
+        error (a different bug, but it still shouldn't dump core). */
+      if (temp_var && function_p (temp_var) == 0)      /* XXX not yet */
+       {
+         CACHE_IMPORTSTR (temp_var, name);
+       }
+    }
+
+  set_pwd ();
+
+  /* Set up initial value of $_ */
+  temp_var = set_if_not ("_", dollar_vars[0]);
+
+  /* Remember this pid. */
+  dollar_dollar_pid = getpid ();
+
+  /* Now make our own defaults in case the vars that we think are
+     important are missing. */
+  temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
+#if 0
+  set_auto_export (temp_var);  /* XXX */
+#endif
+
+  temp_var = set_if_not ("TERM", "dumb");
+#if 0
+  set_auto_export (temp_var);  /* XXX */
+#endif
+
+#if defined (__QNX__)
+  /* set node id -- don't import it from the environment */
+  {
+    char node_name[22];
+#  if defined (__QNXNTO__)
+    netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name));
+#  else
+    qnx_nidtostr (getnid (), node_name, sizeof (node_name));
+#  endif
+    temp_var = bind_variable ("NODE", node_name, 0);
+    set_auto_export (temp_var);
+  }
+#endif
+
+  /* set up the prompts. */
+  if (interactive_shell)
+    {
+#if defined (PROMPT_STRING_DECODE)
+      set_if_not ("PS1", primary_prompt);
+#else
+      if (current_user.uid == -1)
+       get_current_user_info ();
+      set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
+#endif
+      set_if_not ("PS2", secondary_prompt);
+    }
+  set_if_not ("PS4", "+ ");
+
+  /* Don't allow IFS to be imported from the environment. */
+  temp_var = bind_variable ("IFS", " \t\n", 0);
+  setifs (temp_var);
+
+  /* Magic machine types.  Pretty convenient. */
+  set_machine_vars ();
+
+  /* Default MAILCHECK for interactive shells.  Defer the creation of a
+     default MAILPATH until the startup files are read, because MAIL
+     names a mail file if MAILPATH is not set, and we should provide a
+     default only if neither is set. */
+  if (interactive_shell)
+    {
+      temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
+      VSETATTR (temp_var, att_integer);
+    }
+
+  /* Do some things with shell level. */
+  initialize_shell_level ();
+
+  set_ppid ();
+
+  /* Initialize the `getopts' stuff. */
+  temp_var = bind_variable ("OPTIND", "1", 0);
+  VSETATTR (temp_var, att_integer);
+  getopts_reset (0);
+  bind_variable ("OPTERR", "1", 0);
+  sh_opterr = 1;
+
+  if (login_shell == 1 && posixly_correct == 0)
+    set_home_var ();
+
+  /* Get the full pathname to THIS shell, and set the BASH variable
+     to it. */
+  name = get_bash_name ();
+  temp_var = bind_variable ("BASH", name, 0);
+  free (name);
+
+  /* Make the exported environment variable SHELL be the user's login
+     shell.  Note that the `tset' command looks at this variable
+     to determine what style of commands to output; if it ends in "csh",
+     then C-shell commands are output, else Bourne shell commands. */
+  set_shell_var ();
+
+  /* Make a variable called BASH_VERSION which contains the version info. */
+  bind_variable ("BASH_VERSION", shell_version_string (), 0);
+#if defined (ARRAY_VARS)
+  make_vers_array ();
+#endif
+
+  if (command_execution_string)
+    bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
+
+  /* Find out if we're supposed to be in Posix.2 mode via an
+     environment variable. */
+  temp_var = find_variable ("POSIXLY_CORRECT");
+  if (!temp_var)
+    temp_var = find_variable ("POSIX_PEDANTIC");
+  if (temp_var && imported_p (temp_var))
+    sv_strict_posix (temp_var->name);
+
+#if defined (HISTORY)
+  /* Set history variables to defaults, and then do whatever we would
+     do if the variable had just been set.  Do this only in the case
+     that we are remembering commands on the history list. */
+  if (remember_on_history)
+    {
+      name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
+
+      set_if_not ("HISTFILE", name);
+      free (name);
+
+#if 0
+      set_if_not ("HISTSIZE", "500");
+      sv_histsize ("HISTSIZE");
+#endif
+    }
+#endif /* HISTORY */
+
+  /* Seed the random number generator. */
+  seedrand ();
+
+  /* Handle some "special" variables that we may have inherited from a
+     parent shell. */
+  if (interactive_shell)
+    {
+      temp_var = find_variable ("IGNOREEOF");
+      if (!temp_var)
+       temp_var = find_variable ("ignoreeof");
+      if (temp_var && imported_p (temp_var))
+       sv_ignoreeof (temp_var->name);
+    }
+
+#if defined (HISTORY)
+  if (interactive_shell && remember_on_history)
+    {
+      sv_history_control ("HISTCONTROL");
+      sv_histignore ("HISTIGNORE");
+      sv_histtimefmt ("HISTTIMEFORMAT");
+    }
+#endif /* HISTORY */
+
+#if defined (READLINE) && defined (STRICT_POSIX)
+  /* POSIXLY_CORRECT will only be 1 here if the shell was compiled
+     -DSTRICT_POSIX */
+  if (interactive_shell && posixly_correct && no_line_editing == 0)
+    rl_prefer_env_winsize = 1;
+#endif /* READLINE && STRICT_POSIX */
+
+     /*
+      * 24 October 2001
+      *
+      * I'm tired of the arguing and bug reports.  Bash now leaves SSH_CLIENT
+      * and SSH2_CLIENT alone.  I'm going to rely on the shell_level check in
+      * isnetconn() to avoid running the startup files more often than wanted.
+      * That will, of course, only work if the user's login shell is bash, so
+      * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
+      * in config-top.h.
+      */
+#if 0
+  temp_var = find_variable ("SSH_CLIENT");
+  if (temp_var && imported_p (temp_var))
+    {
+      VUNSETATTR (temp_var, att_exported);
+      array_needs_making = 1;
+    }
+  temp_var = find_variable ("SSH2_CLIENT");
+  if (temp_var && imported_p (temp_var))
+    {
+      VUNSETATTR (temp_var, att_exported);
+      array_needs_making = 1;
+    }
+#endif
+
+  /* Get the user's real and effective user ids. */
+  uidset ();
+
+  temp_var = find_variable ("BASH_XTRACEFD");
+  if (temp_var && imported_p (temp_var))
+    sv_xtracefd (temp_var->name);
+
+  /* Initialize the dynamic variables, and seed their values. */
+  initialize_dynamic_variables ();
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*          Setting values for special shell variables             */
+/*                                                                 */
+/* **************************************************************** */
+
+static void
+set_machine_vars ()
+{
+  SHELL_VAR *temp_var;
+
+  temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
+  temp_var = set_if_not ("OSTYPE", OSTYPE);
+  temp_var = set_if_not ("MACHTYPE", MACHTYPE);
+
+  temp_var = set_if_not ("HOSTNAME", current_host_name);
+}
+
+/* Set $HOME to the information in the password file if we didn't get
+   it from the environment. */
+
+/* This function is not static so the tilde and readline libraries can
+   use it. */
+char *
+sh_get_home_dir ()
+{
+  if (current_user.home_dir == 0)
+    get_current_user_info ();
+  return current_user.home_dir;
+}
+
+static void
+set_home_var ()
+{
+  SHELL_VAR *temp_var;
+
+  temp_var = find_variable ("HOME");
+  if (temp_var == 0)
+    temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
+#if 0
+  VSETATTR (temp_var, att_exported);
+#endif
+}
+
+/* Set $SHELL to the user's login shell if it is not already set.  Call
+   get_current_user_info if we haven't already fetched the shell. */
+static void
+set_shell_var ()
+{
+  SHELL_VAR *temp_var;
+
+  temp_var = find_variable ("SHELL");
+  if (temp_var == 0)
+    {
+      if (current_user.shell == 0)
+       get_current_user_info ();
+      temp_var = bind_variable ("SHELL", current_user.shell, 0);
+    }
+#if 0
+  VSETATTR (temp_var, att_exported);
+#endif
+}
+
+static char *
+get_bash_name ()
+{
+  char *name;
+
+  if ((login_shell == 1) && RELPATH(shell_name))
+    {
+      if (current_user.shell == 0)
+       get_current_user_info ();
+      name = savestring (current_user.shell);
+    }
+  else if (ABSPATH(shell_name))
+    name = savestring (shell_name);
+  else if (shell_name[0] == '.' && shell_name[1] == '/')
+    {
+      /* Fast path for common case. */
+      char *cdir;
+      int len;
+
+      cdir = get_string_value ("PWD");
+      if (cdir)
+       {
+         len = strlen (cdir);
+         name = (char *)xmalloc (len + strlen (shell_name) + 1);
+         strcpy (name, cdir);
+         strcpy (name + len, shell_name + 1);
+       }
+      else
+       name = savestring (shell_name);
+    }
+  else
+    {
+      char *tname;
+      int s;
+
+      tname = find_user_command (shell_name);
+
+      if (tname == 0)
+       {
+         /* Try the current directory.  If there is not an executable
+            there, just punt and use the login shell. */
+         s = file_status (shell_name);
+         if (s & FS_EXECABLE)
+           {
+             tname = make_absolute (shell_name, get_string_value ("PWD"));
+             if (*shell_name == '.')
+               {
+                 name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+                 if (name == 0)
+                   name = tname;
+                 else
+                   free (tname);
+               }
+            else
+               name = tname;
+           }
+         else
+           {
+             if (current_user.shell == 0)
+               get_current_user_info ();
+             name = savestring (current_user.shell);
+           }
+       }
+      else
+       {
+         name = full_pathname (tname);
+         free (tname);
+       }
+    }
+
+  return (name);
+}
+
+void
+adjust_shell_level (change)
+     int change;
+{
+  char new_level[5], *old_SHLVL;
+  intmax_t old_level;
+  SHELL_VAR *temp_var;
+
+  old_SHLVL = get_string_value ("SHLVL");
+  if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
+    old_level = 0;
+
+  shell_level = old_level + change;
+  if (shell_level < 0)
+    shell_level = 0;
+  else if (shell_level > 1000)
+    {
+      internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
+      shell_level = 1;
+    }
+
+  /* We don't need the full generality of itos here. */
+  if (shell_level < 10)
+    {
+      new_level[0] = shell_level + '0';
+      new_level[1] = '\0';
+    }
+  else if (shell_level < 100)
+    {
+      new_level[0] = (shell_level / 10) + '0';
+      new_level[1] = (shell_level % 10) + '0';
+      new_level[2] = '\0';
+    }
+  else if (shell_level < 1000)
+    {
+      new_level[0] = (shell_level / 100) + '0';
+      old_level = shell_level % 100;
+      new_level[1] = (old_level / 10) + '0';
+      new_level[2] = (old_level % 10) + '0';
+      new_level[3] = '\0';
+    }
+
+  temp_var = bind_variable ("SHLVL", new_level, 0);
+  set_auto_export (temp_var);
+}
+
+static void
+initialize_shell_level ()
+{
+  adjust_shell_level (1);
+}
+
+/* If we got PWD from the environment, update our idea of the current
+   working directory.  In any case, make sure that PWD exists before
+   checking it.  It is possible for getcwd () to fail on shell startup,
+   and in that case, PWD would be undefined.  If this is an interactive
+   login shell, see if $HOME is the current working directory, and if
+   that's not the same string as $PWD, set PWD=$HOME. */
+
+void
+set_pwd ()
+{
+  SHELL_VAR *temp_var, *home_var;
+  char *temp_string, *home_string;
+
+  home_var = find_variable ("HOME");
+  home_string = home_var ? value_cell (home_var) : (char *)NULL;
+
+  temp_var = find_variable ("PWD");
+  if (temp_var && imported_p (temp_var) &&
+      (temp_string = value_cell (temp_var)) &&
+      same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
+    set_working_directory (temp_string);
+  else if (home_string && interactive_shell && login_shell &&
+          same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
+    {
+      set_working_directory (home_string);
+      temp_var = bind_variable ("PWD", home_string, 0);
+      set_auto_export (temp_var);
+    }
+  else
+    {
+      temp_string = get_working_directory ("shell-init");
+      if (temp_string)
+       {
+         temp_var = bind_variable ("PWD", temp_string, 0);
+         set_auto_export (temp_var);
+         free (temp_string);
+       }
+    }
+
+  /* According to the Single Unix Specification, v2, $OLDPWD is an
+     `environment variable' and therefore should be auto-exported.
+     Make a dummy invisible variable for OLDPWD, and mark it as exported. */
+  temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
+  VSETATTR (temp_var, (att_exported | att_invisible));
+}
+
+/* Make a variable $PPID, which holds the pid of the shell's parent.  */
+void
+set_ppid ()
+{
+  char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
+  SHELL_VAR *temp_var;
+
+  name = inttostr (getppid (), namebuf, sizeof(namebuf));
+  temp_var = find_variable ("PPID");
+  if (temp_var)
+    VUNSETATTR (temp_var, (att_readonly | att_exported));
+  temp_var = bind_variable ("PPID", name, 0);
+  VSETATTR (temp_var, (att_readonly | att_integer));
+}
+
+static void
+uidset ()
+{
+  char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
+  register SHELL_VAR *v;
+
+  b = inttostr (current_user.uid, buff, sizeof (buff));
+  v = find_variable ("UID");
+  if (v == 0)
+    {
+      v = bind_variable ("UID", b, 0);
+      VSETATTR (v, (att_readonly | att_integer));
+    }
+
+  if (current_user.euid != current_user.uid)
+    b = inttostr (current_user.euid, buff, sizeof (buff));
+
+  v = find_variable ("EUID");
+  if (v == 0)
+    {
+      v = bind_variable ("EUID", b, 0);
+      VSETATTR (v, (att_readonly | att_integer));
+    }
+}
+
+#if defined (ARRAY_VARS)
+static void
+make_vers_array ()
+{
+  SHELL_VAR *vv;
+  ARRAY *av;
+  char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
+
+  unbind_variable ("BASH_VERSINFO");
+
+  vv = make_new_array_variable ("BASH_VERSINFO");
+  av = array_cell (vv);
+  strcpy (d, dist_version);
+  s = strchr (d, '.');
+  if (s)
+    *s++ = '\0';
+  array_insert (av, 0, d);
+  array_insert (av, 1, s);
+  s = inttostr (patch_level, b, sizeof (b));
+  array_insert (av, 2, s);
+  s = inttostr (build_version, b, sizeof (b));
+  array_insert (av, 3, s);
+  array_insert (av, 4, release_status);
+  array_insert (av, 5, MACHTYPE);
+
+  VSETATTR (vv, att_readonly);
+}
+#endif /* ARRAY_VARS */
+
+/* Set the environment variables $LINES and $COLUMNS in response to
+   a window size change. */
+void
+sh_set_lines_and_columns (lines, cols)
+     int lines, cols;
+{
+  char val[INT_STRLEN_BOUND(int) + 1], *v;
+
+#if defined (READLINE)
+  /* If we are currently assigning to LINES or COLUMNS, don't do anything. */
+  if (winsize_assignment)
+    return;
+#endif
+
+  v = inttostr (lines, val, sizeof (val));
+  bind_variable ("LINES", v, 0);
+
+  v = inttostr (cols, val, sizeof (val));
+  bind_variable ("COLUMNS", v, 0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                Printing variables and values                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Print LIST (a list of shell variables) to stdout in such a way that
+   they can be read back in. */
+void
+print_var_list (list)
+     register SHELL_VAR **list;
+{
+  register int i;
+  register SHELL_VAR *var;
+
+  for (i = 0; list && (var = list[i]); i++)
+    if (invisible_p (var) == 0)
+      print_assignment (var);
+}
+
+/* Print LIST (a list of shell functions) to stdout in such a way that
+   they can be read back in. */
+void
+print_func_list (list)
+     register SHELL_VAR **list;
+{
+  register int i;
+  register SHELL_VAR *var;
+
+  for (i = 0; list && (var = list[i]); i++)
+    {
+      printf ("%s ", var->name);
+      print_var_function (var);
+      printf ("\n");
+    }
+}
+      
+/* Print the value of a single SHELL_VAR.  No newline is
+   output, but the variable is printed in such a way that
+   it can be read back in. */
+void
+print_assignment (var)
+     SHELL_VAR *var;
+{
+  if (var_isset (var) == 0)
+    return;
+
+  if (function_p (var))
+    {
+      printf ("%s", var->name);
+      print_var_function (var);
+      printf ("\n");
+    }
+#if defined (ARRAY_VARS)
+  else if (array_p (var))
+    print_array_assignment (var, 0);
+  else if (assoc_p (var))
+    print_assoc_assignment (var, 0);
+#endif /* ARRAY_VARS */
+  else
+    {
+      printf ("%s=", var->name);
+      print_var_value (var, 1);
+      printf ("\n");
+    }
+}
+
+/* Print the value cell of VAR, a shell variable.  Do not print
+   the name, nor leading/trailing newline.  If QUOTE is non-zero,
+   and the value contains shell metacharacters, quote the value
+   in such a way that it can be read back in. */
+void
+print_var_value (var, quote)
+     SHELL_VAR *var;
+     int quote;
+{
+  char *t;
+
+  if (var_isset (var) == 0)
+    return;
+
+  if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
+    {
+      t = ansic_quote (value_cell (var), 0, (int *)0);
+      printf ("%s", t);
+      free (t);
+    }
+  else if (quote && sh_contains_shell_metas (value_cell (var)))
+    {
+      t = sh_single_quote (value_cell (var));
+      printf ("%s", t);
+      free (t);
+    }
+  else
+    printf ("%s", value_cell (var));
+}
+
+/* Print the function cell of VAR, a shell variable.  Do not
+   print the name, nor leading/trailing newline. */
+void
+print_var_function (var)
+     SHELL_VAR *var;
+{
+  char *x;
+
+  if (function_p (var) && var_isset (var))
+    {
+      x = named_function_string ((char *)NULL, function_cell(var), FUNC_MULTILINE|FUNC_EXTERNAL);
+      printf ("%s", x);
+    }
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Dynamic Variables                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* DYNAMIC VARIABLES
+
+   These are variables whose values are generated anew each time they are
+   referenced.  These are implemented using a pair of function pointers
+   in the struct variable: assign_func, which is called from bind_variable
+   and, if arrays are compiled into the shell, some of the functions in
+   arrayfunc.c, and dynamic_value, which is called from find_variable.
+
+   assign_func is called from bind_variable_internal, if
+   bind_variable_internal discovers that the variable being assigned to
+   has such a function.  The function is called as
+       SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
+   and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
+   is usually ENTRY (self).  IND is an index for an array variable, and
+   unused otherwise.
+
+   dynamic_value is called from find_variable_internal to return a `new'
+   value for the specified dynamic varible.  If this function is NULL,
+   the variable is treated as a `normal' shell variable.  If it is not,
+   however, then this function is called like this:
+       tempvar = (*(var->dynamic_value)) (var);
+
+   Sometimes `tempvar' will replace the value of `var'.  Other times, the
+   shell will simply use the string value.  Pretty object-oriented, huh?
+
+   Be warned, though: if you `unset' a special variable, it loses its
+   special meaning, even if you subsequently set it.
+
+   The special assignment code would probably have been better put in
+   subst.c: do_assignment_internal, in the same style as
+   stupidly_hack_special_variables, but I wanted the changes as
+   localized as possible.  */
+
+#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
+  do \
+    { \
+      v = bind_variable (var, (val), 0); \
+      v->dynamic_value = gfunc; \
+      v->assign_func = afunc; \
+    } \
+  while (0)
+
+#define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
+  do \
+    { \
+      v = make_new_array_variable (var); \
+      v->dynamic_value = gfunc; \
+      v->assign_func = afunc; \
+    } \
+  while (0)
+
+#define INIT_DYNAMIC_ASSOC_VAR(var, gfunc, afunc) \
+  do \
+    { \
+      v = make_new_assoc_variable (var); \
+      v->dynamic_value = gfunc; \
+      v->assign_func = afunc; \
+    } \
+  while (0)
+
+static SHELL_VAR *
+null_assign (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  return (self);
+}
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *
+null_array_assign (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  return (self);
+}
+#endif
+
+/* Degenerate `dynamic_value' function; just returns what's passed without
+   manipulation. */
+static SHELL_VAR *
+get_self (self)
+     SHELL_VAR *self;
+{
+  return (self);
+}
+
+#if defined (ARRAY_VARS)
+/* A generic dynamic array variable initializer.  Intialize array variable
+   NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
+static SHELL_VAR *
+init_dynamic_array_var (name, getfunc, setfunc, attrs)
+     char *name;
+     sh_var_value_func_t *getfunc;
+     sh_var_assign_func_t *setfunc;
+     int attrs;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v)
+    return (v);
+  INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
+  if (attrs)
+    VSETATTR (v, attrs);
+  return v;
+}
+
+static SHELL_VAR *
+init_dynamic_assoc_var (name, getfunc, setfunc, attrs)
+     char *name;
+     sh_var_value_func_t *getfunc;
+     sh_var_assign_func_t *setfunc;
+     int attrs;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v)
+    return (v);
+  INIT_DYNAMIC_ASSOC_VAR (name, getfunc, setfunc);
+  if (attrs)
+    VSETATTR (v, attrs);
+  return v;
+}
+#endif
+
+/* The value of $SECONDS.  This is the number of seconds since shell
+   invocation, or, the number of seconds since the last assignment + the
+   value of the last assignment. */
+static intmax_t seconds_value_assigned;
+
+static SHELL_VAR *
+assign_seconds (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  if (legal_number (value, &seconds_value_assigned) == 0)
+    seconds_value_assigned = 0;
+  shell_start_time = NOW;
+  return (self);
+}
+
+static SHELL_VAR *
+get_seconds (var)
+     SHELL_VAR *var;
+{
+  time_t time_since_start;
+  char *p;
+
+  time_since_start = NOW - shell_start_time;
+  p = itos(seconds_value_assigned + time_since_start);
+
+  FREE (value_cell (var));
+
+  VSETATTR (var, att_integer);
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+init_seconds_var ()
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("SECONDS");
+  if (v)
+    {
+      if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
+       seconds_value_assigned = 0;
+    }
+  INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
+  return v;      
+}
+     
+/* The random number seed.  You can change this by setting RANDOM. */
+static unsigned long rseed = 1;
+static int last_random_value;
+static int seeded_subshell = 0;
+
+/* A linear congruential random number generator based on the example
+   one in the ANSI C standard.  This one isn't very good, but a more
+   complicated one is overkill. */
+
+/* Returns a pseudo-random number between 0 and 32767. */
+static int
+brand ()
+{
+  /* From "Random number generators: good ones are hard to find",
+     Park and Miller, Communications of the ACM, vol. 31, no. 10,
+     October 1988, p. 1195. filtered through FreeBSD */
+  long h, l;
+
+  /* Can't seed with 0. */
+  if (rseed == 0)
+    rseed = 123459876;
+  h = rseed / 127773;
+  l = rseed % 127773;
+  rseed = 16807 * l - 2836 * h;
+#if 0
+  if (rseed < 0)
+    rseed += 0x7fffffff;
+#endif
+  return ((unsigned int)(rseed & 32767));      /* was % 32768 */
+}
+
+/* Set the random number generator seed to SEED. */
+static void
+sbrand (seed)
+     unsigned long seed;
+{
+  rseed = seed;
+  last_random_value = 0;
+}
+
+static void
+seedrand ()
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, NULL);
+  sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid ());
+}
+
+static SHELL_VAR *
+assign_random (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  sbrand (strtoul (value, (char **)NULL, 10));
+  if (subshell_environment)
+    seeded_subshell = getpid ();
+  return (self);
+}
+
+int
+get_random_number ()
+{
+  int rv, pid;
+
+  /* Reset for command and process substitution. */
+  pid = getpid ();
+  if (subshell_environment && seeded_subshell != pid)
+    {
+      seedrand ();
+      seeded_subshell = pid;
+    }
+
+  do
+    rv = brand ();
+  while (rv == last_random_value);
+  return rv;
+}
+
+static SHELL_VAR *
+get_random (var)
+     SHELL_VAR *var;
+{
+  int rv;
+  char *p;
+
+  rv = get_random_number ();
+  last_random_value = rv;
+  p = itos (rv);
+
+  FREE (value_cell (var));
+
+  VSETATTR (var, att_integer);
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+assign_lineno (var, value, unused, key)
+     SHELL_VAR *var;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  intmax_t new_value;
+
+  if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
+    new_value = 0;
+  line_number = line_number_base = new_value;
+  return var;
+}
+
+/* Function which returns the current line number. */
+static SHELL_VAR *
+get_lineno (var)
+     SHELL_VAR *var;
+{
+  char *p;
+  int ln;
+
+  ln = executing_line_number ();
+  p = itos (ln);
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+assign_subshell (var, value, unused, key)
+     SHELL_VAR *var;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  intmax_t new_value;
+
+  if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
+    new_value = 0;
+  subshell_level = new_value;
+  return var;
+}
+
+static SHELL_VAR *
+get_subshell (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  p = itos (subshell_level);
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+get_bashpid (var)
+     SHELL_VAR *var;
+{
+  int pid;
+  char *p;
+
+  pid = getpid ();
+  p = itos (pid);
+
+  FREE (value_cell (var));
+  VSETATTR (var, att_integer|att_readonly);
+  var_setvalue (var, p);
+  return (var);
+}
+
+static SHELL_VAR *
+get_bash_command (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  if (the_printed_command_except_trap)
+    p = savestring (the_printed_command_except_trap);
+  else
+    {
+      p = (char *)xmalloc (1);
+      p[0] = '\0';
+    }
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+
+#if defined (HISTORY)
+static SHELL_VAR *
+get_histcmd (var)
+     SHELL_VAR *var;
+{
+  char *p;
+
+  p = itos (history_number ());
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+#endif
+
+#if defined (READLINE)
+/* When this function returns, VAR->value points to malloced memory. */
+static SHELL_VAR *
+get_comp_wordbreaks (var)
+     SHELL_VAR *var;
+{
+  /* If we don't have anything yet, assign a default value. */
+  if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
+    enable_hostname_completion (perform_hostname_completion);
+
+  FREE (value_cell (var));
+  var_setvalue (var, savestring (rl_completer_word_break_characters));
+
+  return (var);
+}
+
+/* When this function returns, rl_completer_word_break_characters points to
+   malloced memory. */
+static SHELL_VAR *
+assign_comp_wordbreaks (self, value, unused, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t unused;
+     char *key;
+{
+  if (rl_completer_word_break_characters &&
+      rl_completer_word_break_characters != rl_basic_word_break_characters)
+    free (rl_completer_word_break_characters);
+
+  rl_completer_word_break_characters = savestring (value);
+  return self;
+}
+#endif /* READLINE */
+
+#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+static SHELL_VAR *
+assign_dirstack (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  set_dirstack_element (ind, 1, value);
+  return self;
+}
+
+static SHELL_VAR *
+get_dirstack (self)
+     SHELL_VAR *self;
+{
+  ARRAY *a;
+  WORD_LIST *l;
+
+  l = get_directory_stack (0);
+  a = array_from_word_list (l);
+  array_dispose (array_cell (self));
+  dispose_words (l);
+  var_setarray (self, a);
+  return self;
+}
+#endif /* PUSHD AND POPD && ARRAY_VARS */
+
+#if defined (ARRAY_VARS)
+/* We don't want to initialize the group set with a call to getgroups()
+   unless we're asked to, but we only want to do it once. */
+static SHELL_VAR *
+get_groupset (self)
+     SHELL_VAR *self;
+{
+  register int i;
+  int ng;
+  ARRAY *a;
+  static char **group_set = (char **)NULL;
+
+  if (group_set == 0)
+    {
+      group_set = get_group_list (&ng);
+      a = array_cell (self);
+      for (i = 0; i < ng; i++)
+       array_insert (a, i, group_set[i]);
+    }
+  return (self);
+}
+
+static SHELL_VAR *
+build_hashcmd (self)
+     SHELL_VAR *self;
+{
+  HASH_TABLE *h;
+  int i;
+  char *k, *v;
+  BUCKET_CONTENTS *item;
+
+  h = assoc_cell (self);
+  if (h)
+    assoc_dispose (h);
+
+  if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
+    {
+      var_setvalue (self, (char *)NULL);
+      return self;
+    }
+
+  h = assoc_create (hashed_filenames->nbuckets);
+  for (i = 0; i < hashed_filenames->nbuckets; i++)
+    {
+      for (item = hash_items (i, hashed_filenames); item; item = item->next)
+       {
+         k = savestring (item->key);
+         v = pathdata(item)->path;
+         assoc_insert (h, k, v);
+       }
+    }
+
+  var_setvalue (self, (char *)h);
+  return self;
+}
+
+static SHELL_VAR *
+get_hashcmd (self)
+     SHELL_VAR *self;
+{
+  build_hashcmd (self);
+  return (self);
+}
+
+static SHELL_VAR *
+assign_hashcmd (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  phash_insert (key, value, 0, 0);
+  return (build_hashcmd (self));
+}
+
+#if defined (ALIAS)
+static SHELL_VAR *
+build_aliasvar (self)
+     SHELL_VAR *self;
+{
+  HASH_TABLE *h;
+  int i;
+  char *k, *v;
+  BUCKET_CONTENTS *item;
+
+  h = assoc_cell (self);
+  if (h)
+    assoc_dispose (h);
+
+  if (aliases == 0 || HASH_ENTRIES (aliases) == 0)
+    {
+      var_setvalue (self, (char *)NULL);
+      return self;
+    }
+
+  h = assoc_create (aliases->nbuckets);
+  for (i = 0; i < aliases->nbuckets; i++)
+    {
+      for (item = hash_items (i, aliases); item; item = item->next)
+       {
+         k = savestring (item->key);
+         v = ((alias_t *)(item->data))->value;
+         assoc_insert (h, k, v);
+       }
+    }
+
+  var_setvalue (self, (char *)h);
+  return self;
+}
+
+static SHELL_VAR *
+get_aliasvar (self)
+     SHELL_VAR *self;
+{
+  build_aliasvar (self);
+  return (self);
+}
+
+static SHELL_VAR *
+assign_aliasvar (self, value, ind, key)
+     SHELL_VAR *self;
+     char *value;
+     arrayind_t ind;
+     char *key;
+{
+  add_alias (key, value);
+  return (build_aliasvar (self));
+}
+#endif /* ALIAS */
+
+#endif /* ARRAY_VARS */
+
+/* If ARRAY_VARS is not defined, this just returns the name of any
+   currently-executing function.  If we have arrays, it's a call stack. */
+static SHELL_VAR *
+get_funcname (self)
+     SHELL_VAR *self;
+{
+#if ! defined (ARRAY_VARS)
+  char *t;
+  if (variable_context && this_shell_function)
+    {
+      FREE (value_cell (self));
+      t = savestring (this_shell_function->name);
+      var_setvalue (self, t);
+    }
+#endif
+  return (self);
+}
+
+void
+make_funcname_visible (on_or_off)
+     int on_or_off;
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("FUNCNAME");
+  if (v == 0 || v->dynamic_value == 0)
+    return;
+
+  if (on_or_off)
+    VUNSETATTR (v, att_invisible);
+  else
+    VSETATTR (v, att_invisible);
+}
+
+static SHELL_VAR *
+init_funcname_var ()
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("FUNCNAME");
+  if (v)
+    return v;
+#if defined (ARRAY_VARS)
+  INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
+#else
+  INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
+#endif
+  VSETATTR (v, att_invisible|att_noassign);
+  return v;
+}
+
+static void
+initialize_dynamic_variables ()
+{
+  SHELL_VAR *v;
+
+  v = init_seconds_var ();
+
+  INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
+  INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
+
+  INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
+  VSETATTR (v, att_integer);
+  INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
+  VSETATTR (v, att_integer);
+
+  INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign);
+  VSETATTR (v, att_integer|att_readonly);
+
+#if defined (HISTORY)
+  INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
+  VSETATTR (v, att_integer);
+#endif
+
+#if defined (READLINE)
+  INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
+#endif
+
+#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
+  v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
+#endif /* PUSHD_AND_POPD && ARRAY_VARS */
+
+#if defined (ARRAY_VARS)
+  v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
+
+#  if defined (DEBUGGER)
+  v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
+  v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
+#  endif /* DEBUGGER */
+  v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
+  v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
+
+  v = init_dynamic_assoc_var ("BASH_CMDS", get_hashcmd, assign_hashcmd, att_nofree);
+#  if defined (ALIAS)
+  v = init_dynamic_assoc_var ("BASH_ALIASES", get_aliasvar, assign_aliasvar, att_nofree);
+#  endif
+#endif
+
+  v = init_funcname_var ();
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*             Retrieving variables and values                     */
+/*                                                                 */
+/* **************************************************************** */
+
+/* How to get a pointer to the shell variable or function named NAME.
+   HASHED_VARS is a pointer to the hash table containing the list
+   of interest (either variables or functions). */
+
+static SHELL_VAR *
+hash_lookup (name, hashed_vars)
+     const char *name;
+     HASH_TABLE *hashed_vars;
+{
+  BUCKET_CONTENTS *bucket;
+
+  bucket = hash_search (name, hashed_vars, 0);
+  return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
+}
+
+SHELL_VAR *
+var_lookup (name, vcontext)
+     const char *name;
+     VAR_CONTEXT *vcontext;
+{
+  VAR_CONTEXT *vc;
+  SHELL_VAR *v;
+
+  v = (SHELL_VAR *)NULL;
+  for (vc = vcontext; vc; vc = vc->down)
+    if (v = hash_lookup (name, vc->table))
+      break;
+
+  return v;
+}
+
+/* Look up the variable entry named NAME.  If SEARCH_TEMPENV is non-zero,
+   then also search the temporarily built list of exported variables.
+   The lookup order is:
+       temporary_env
+       shell_variables list
+*/
+
+SHELL_VAR *
+find_variable_internal (name, force_tempenv)
+     const char *name;
+     int force_tempenv;
+{
+  SHELL_VAR *var;
+  int search_tempenv;
+
+  var = (SHELL_VAR *)NULL;
+
+  /* If explicitly requested, first look in the temporary environment for
+     the variable.  This allows constructs such as "foo=x eval 'echo $foo'"
+     to get the `exported' value of $foo.  This happens if we are executing
+     a function or builtin, or if we are looking up a variable in a
+     "subshell environment". */
+  search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
+
+  if (search_tempenv && temporary_env)         
+    var = hash_lookup (name, temporary_env);
+
+  if (var == 0)
+    var = var_lookup (name, shell_variables);
+
+  if (var == 0)
+    return ((SHELL_VAR *)NULL);
+
+  return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
+}
+
+SHELL_VAR *
+find_global_variable (name)
+     const char *name;
+{
+  SHELL_VAR *var;
+
+  var = var_lookup (name, global_variables);
+
+  if (var == 0)
+    return ((SHELL_VAR *)NULL);
+
+  return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
+}
+
+/* Look up the variable entry named NAME.  Returns the entry or NULL. */
+SHELL_VAR *
+find_variable (name)
+     const char *name;
+{
+  return (find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin))));
+}
+
+/* Look up the function entry whose name matches STRING.
+   Returns the entry or NULL. */
+SHELL_VAR *
+find_function (name)
+     const char *name;
+{
+  return (hash_lookup (name, shell_functions));
+}
+
+/* Find the function definition for the shell function named NAME.  Returns
+   the entry or NULL. */
+FUNCTION_DEF *
+find_function_def (name)
+     const char *name;
+{
+#if defined (DEBUGGER)
+  return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
+#else
+  return ((FUNCTION_DEF *)0);
+#endif
+}
+
+/* Return the value of VAR.  VAR is assumed to have been the result of a
+   lookup without any subscript, if arrays are compiled into the shell. */
+char *
+get_variable_value (var)
+     SHELL_VAR *var;
+{
+  if (var == 0)
+    return ((char *)NULL);
+#if defined (ARRAY_VARS)
+  else if (array_p (var))
+    return (array_reference (array_cell (var), 0));
+  else if (assoc_p (var))
+    return (assoc_reference (assoc_cell (var), "0"));
+#endif
+  else
+    return (value_cell (var));
+}
+
+/* Return the string value of a variable.  Return NULL if the variable
+   doesn't exist.  Don't cons a new string.  This is a potential memory
+   leak if the variable is found in the temporary environment.  Since
+   functions and variables have separate name spaces, returns NULL if
+   var_name is a shell function only. */
+char *
+get_string_value (var_name)
+     const char *var_name;
+{
+  SHELL_VAR *var;
+
+  var = find_variable (var_name);
+  return ((var) ? get_variable_value (var) : (char *)NULL);
+}
+
+/* This is present for use by the tilde and readline libraries. */
+char *
+sh_get_env_value (v)
+     const char *v;
+{
+  return get_string_value (v);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Creating and setting variables                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set NAME to VALUE if NAME has no value. */
+SHELL_VAR *
+set_if_not (name, value)
+     char *name, *value;
+{
+  SHELL_VAR *v;
+
+  if (shell_variables == 0)
+    create_variable_tables ();
+
+  v = find_variable (name);
+  if (v == 0)
+    v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
+  return (v);
+}
+
+/* Create a local variable referenced by NAME. */
+SHELL_VAR *
+make_local_variable (name)
+     const char *name;
+{
+  SHELL_VAR *new_var, *old_var;
+  VAR_CONTEXT *vc;
+  int was_tmpvar;
+  char *tmp_value;
+
+  /* local foo; local foo;  is a no-op. */
+  old_var = find_variable (name);
+  if (old_var && local_p (old_var) && old_var->context == variable_context)
+    {
+      VUNSETATTR (old_var, att_invisible);
+      return (old_var);
+    }
+
+  was_tmpvar = old_var && tempvar_p (old_var);
+  if (was_tmpvar)
+    tmp_value = value_cell (old_var);
+
+  for (vc = shell_variables; vc; vc = vc->down)
+    if (vc_isfuncenv (vc) && vc->scope == variable_context)
+      break;
+
+  if (vc == 0)
+    {
+      internal_error (_("make_local_variable: no function context at current scope"));
+      return ((SHELL_VAR *)NULL);
+    }
+  else if (vc->table == 0)
+    vc->table = hash_create (TEMPENV_HASH_BUCKETS);
+
+  /* Since this is called only from the local/declare/typeset code, we can
+     call builtin_error here without worry (of course, it will also work
+     for anything that sets this_command_name).  Variables with the `noassign'
+     attribute may not be made local.  The test against old_var's context
+     level is to disallow local copies of readonly global variables (since I
+     believe that this could be a security hole).  Readonly copies of calling
+     function local variables are OK. */
+  if (old_var && (noassign_p (old_var) ||
+                (readonly_p (old_var) && old_var->context == 0)))
+    {
+      if (readonly_p (old_var))
+       sh_readonly (name);
+      return ((SHELL_VAR *)NULL);
+    }
+
+  if (old_var == 0)
+    new_var = make_new_variable (name, vc->table);
+  else
+    {
+      new_var = make_new_variable (name, vc->table);
+
+      /* If we found this variable in one of the temporary environments,
+        inherit its value.  Watch to see if this causes problems with
+        things like `x=4 local x'. */
+      if (was_tmpvar)
+       var_setvalue (new_var, savestring (tmp_value));
+
+      new_var->attributes = exported_p (old_var) ? att_exported : 0;
+    }
+
+  vc->flags |= VC_HASLOCAL;
+
+  new_var->context = variable_context;
+  VSETATTR (new_var, att_local);
+
+  if (ifsname (name))
+    setifs (new_var);
+
+  return (new_var);
+}
+
+/* Create a new shell variable with name NAME. */
+static SHELL_VAR *
+new_shell_variable (name)
+     const char *name;
+{
+  SHELL_VAR *entry;
+
+  entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+
+  entry->name = savestring (name);
+  var_setvalue (entry, (char *)NULL);
+  CLEAR_EXPORTSTR (entry);
+
+  entry->dynamic_value = (sh_var_value_func_t *)NULL;
+  entry->assign_func = (sh_var_assign_func_t *)NULL;
+
+  entry->attributes = 0;
+
+  /* Always assume variables are to be made at toplevel!
+     make_local_variable has the responsibilty of changing the
+     variable context. */
+  entry->context = 0;
+
+  return (entry);
+}
+
+/* Create a new shell variable with name NAME and add it to the hash table
+   TABLE. */
+static SHELL_VAR *
+make_new_variable (name, table)
+     const char *name;
+     HASH_TABLE *table;
+{
+  SHELL_VAR *entry;
+  BUCKET_CONTENTS *elt;
+
+  entry = new_shell_variable (name);
+
+  /* Make sure we have a shell_variables hash table to add to. */
+  if (shell_variables == 0)
+    create_variable_tables ();
+
+  elt = hash_insert (savestring (name), table, HASH_NOSRCH);
+  elt->data = (PTR_T)entry;
+
+  return entry;
+}
+
+#if defined (ARRAY_VARS)
+SHELL_VAR *
+make_new_array_variable (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+  ARRAY *array;
+
+  entry = make_new_variable (name, global_variables->table);
+  array = array_create ();
+
+  var_setarray (entry, array);
+  VSETATTR (entry, att_array);
+  return entry;
+}
+
+SHELL_VAR *
+make_local_array_variable (name)
+     char *name;
+{
+  SHELL_VAR *var;
+  ARRAY *array;
+
+  var = make_local_variable (name);
+  if (var == 0 || array_p (var))
+    return var;
+
+  array = array_create ();
+
+  dispose_variable_value (var);
+  var_setarray (var, array);
+  VSETATTR (var, att_array);
+  return var;
+}
+
+SHELL_VAR *
+make_new_assoc_variable (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+  HASH_TABLE *hash;
+
+  entry = make_new_variable (name, global_variables->table);
+  hash = assoc_create (0);
+
+  var_setassoc (entry, hash);
+  VSETATTR (entry, att_assoc);
+  return entry;
+}
+
+SHELL_VAR *
+make_local_assoc_variable (name)
+     char *name;
+{
+  SHELL_VAR *var;
+  HASH_TABLE *hash;
+
+  var = make_local_variable (name);
+  if (var == 0 || assoc_p (var))
+    return var;
+
+  dispose_variable_value (var);
+  hash = assoc_create (0);
+
+  var_setassoc (var, hash);
+  VSETATTR (var, att_assoc);
+  return var;
+}
+#endif
+
+char *
+make_variable_value (var, value, flags)
+     SHELL_VAR *var;
+     char *value;
+     int flags;
+{
+  char *retval, *oval;
+  intmax_t lval, rval;
+  int expok, olen, op;
+
+  /* If this variable has had its type set to integer (via `declare -i'),
+     then do expression evaluation on it and store the result.  The
+     functions in expr.c (evalexp()) and bind_int_variable() are responsible
+     for turning off the integer flag if they don't want further
+     evaluation done. */
+  if (integer_p (var))
+    {
+      if (flags & ASS_APPEND)
+       {
+         oval = value_cell (var);
+         lval = evalexp (oval, &expok);        /* ksh93 seems to do this */
+         if (expok == 0)
+           {
+             top_level_cleanup ();
+             jump_to_top_level (DISCARD);
+           }
+       }
+      rval = evalexp (value, &expok);
+      if (expok == 0)
+       {
+         top_level_cleanup ();
+         jump_to_top_level (DISCARD);
+       }
+      if (flags & ASS_APPEND)
+       rval += lval;
+      retval = itos (rval);
+    }
+#if defined (CASEMOD_ATTRS)
+  else if (capcase_p (var) || uppercase_p (var) || lowercase_p (var))
+    {
+      if (flags & ASS_APPEND)
+       {
+         oval = get_variable_value (var);
+         if (oval == 0)        /* paranoia */
+           oval = "";
+         olen = STRLEN (oval);
+         retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
+         strcpy (retval, oval);
+         if (value)
+           strcpy (retval+olen, value);
+       }
+      else if (*value)
+       retval = savestring (value);
+      else
+       {
+         retval = (char *)xmalloc (1);
+         retval[0] = '\0';
+       }
+      op = capcase_p (var) ? CASE_CAPITALIZE
+                        : (uppercase_p (var) ? CASE_UPPER : CASE_LOWER);
+      oval = sh_modcase (retval, (char *)0, op);
+      free (retval);
+      retval = oval;
+    }
+#endif /* CASEMOD_ATTRS */
+  else if (value)
+    {
+      if (flags & ASS_APPEND)
+       {
+         oval = get_variable_value (var);
+         if (oval == 0)        /* paranoia */
+           oval = "";
+         olen = STRLEN (oval);
+         retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
+         strcpy (retval, oval);
+         if (value)
+           strcpy (retval+olen, value);
+       }
+      else if (*value)
+       retval = savestring (value);
+      else
+       {
+         retval = (char *)xmalloc (1);
+         retval[0] = '\0';
+       }
+    }
+  else
+    retval = (char *)NULL;
+
+  return retval;
+}
+
+/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
+   temporary environment (but usually is not). */
+static SHELL_VAR *
+bind_variable_internal (name, value, table, hflags, aflags)
+     const char *name;
+     char *value;
+     HASH_TABLE *table;
+     int hflags, aflags;
+{
+  char *newval;
+  SHELL_VAR *entry;
+
+  entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
+
+  if (entry == 0)
+    {
+      entry = make_new_variable (name, table);
+      var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
+    }
+  else if (entry->assign_func) /* array vars have assign functions now */
+    {
+      INVALIDATE_EXPORTSTR (entry);
+      newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
+      if (assoc_p (entry))
+       entry = (*(entry->assign_func)) (entry, newval, -1, savestring ("0"));
+      else if (array_p (entry))
+       entry = (*(entry->assign_func)) (entry, newval, 0, 0);
+      else
+       entry = (*(entry->assign_func)) (entry, newval, -1, 0);
+      if (newval != value)
+       free (newval);
+      return (entry);
+    }
+  else
+    {
+      if (readonly_p (entry) || noassign_p (entry))
+       {
+         if (readonly_p (entry))
+           err_readonly (name);
+         return (entry);
+       }
+
+      /* Variables which are bound are visible. */
+      VUNSETATTR (entry, att_invisible);
+
+      newval = make_variable_value (entry, value, aflags);     /* XXX */
+
+      /* Invalidate any cached export string */
+      INVALIDATE_EXPORTSTR (entry);
+
+#if defined (ARRAY_VARS)
+      /* XXX -- this bears looking at again -- XXX */
+      /* If an existing array variable x is being assigned to with x=b or
+        `read x' or something of that nature, silently convert it to
+        x[0]=b or `read x[0]'. */
+      if (array_p (entry))
+       {
+         array_insert (array_cell (entry), 0, newval);
+         free (newval);
+       }
+      else if (assoc_p (entry))
+       {
+         assoc_insert (assoc_cell (entry), savestring ("0"), newval);
+         free (newval);
+       }
+      else
+#endif
+       {
+         FREE (value_cell (entry));
+         var_setvalue (entry, newval);
+       }
+    }
+
+  if (mark_modified_vars)
+    VSETATTR (entry, att_exported);
+
+  if (exported_p (entry))
+    array_needs_making = 1;
+
+  return (entry);
+}
+       
+/* Bind a variable NAME to VALUE.  This conses up the name
+   and value strings.  If we have a temporary environment, we bind there
+   first, then we bind into shell_variables. */
+
+SHELL_VAR *
+bind_variable (name, value, flags)
+     const char *name;
+     char *value;
+     int flags;
+{
+  SHELL_VAR *v;
+  VAR_CONTEXT *vc;
+
+  if (shell_variables == 0)
+    create_variable_tables ();
+
+  /* If we have a temporary environment, look there first for the variable,
+     and, if found, modify the value there before modifying it in the
+     shell_variables table.  This allows sourced scripts to modify values
+     given to them in a temporary environment while modifying the variable
+     value that the caller sees. */
+  if (temporary_env)
+    bind_tempenv_variable (name, value);
+
+  /* XXX -- handle local variables here. */
+  for (vc = shell_variables; vc; vc = vc->down)
+    {
+      if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
+       {
+         v = hash_lookup (name, vc->table);
+         if (v)
+           return (bind_variable_internal (name, value, vc->table, 0, flags));
+       }
+    }
+  return (bind_variable_internal (name, value, global_variables->table, 0, flags));
+}
+
+/* Make VAR, a simple shell variable, have value VALUE.  Once assigned a
+   value, variables are no longer invisible.  This is a duplicate of part
+   of the internals of bind_variable.  If the variable is exported, or
+   all modified variables should be exported, mark the variable for export
+   and note that the export environment needs to be recreated. */
+SHELL_VAR *
+bind_variable_value (var, value, aflags)
+     SHELL_VAR *var;
+     char *value;
+     int aflags;
+{
+  char *t;
+
+  VUNSETATTR (var, att_invisible);
+
+  if (var->assign_func)
+    {
+      /* If we're appending, we need the old value, so use
+        make_variable_value */
+      t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
+      (*(var->assign_func)) (var, t, -1, 0);
+      if (t != value && t)
+       free (t);      
+    }
+  else
+    {
+      t = make_variable_value (var, value, aflags);
+      FREE (value_cell (var));
+      var_setvalue (var, t);
+    }
+
+  INVALIDATE_EXPORTSTR (var);
+
+  if (mark_modified_vars)
+    VSETATTR (var, att_exported);
+
+  if (exported_p (var))
+    array_needs_making = 1;
+
+  return (var);
+}
+
+/* Bind/create a shell variable with the name LHS to the RHS.
+   This creates or modifies a variable such that it is an integer.
+
+   This used to be in expr.c, but it is here so that all of the
+   variable binding stuff is localized.  Since we don't want any
+   recursive evaluation from bind_variable() (possible without this code,
+   since bind_variable() calls the evaluator for variables with the integer
+   attribute set), we temporarily turn off the integer attribute for each
+   variable we set here, then turn it back on after binding as necessary. */
+
+SHELL_VAR *
+bind_int_variable (lhs, rhs)
+     char *lhs, *rhs;
+{
+  register SHELL_VAR *v;
+  int isint, isarr;
+
+  isint = isarr = 0;
+#if defined (ARRAY_VARS)
+  if (valid_array_reference (lhs))
+    {
+      isarr = 1;
+      v = array_variable_part (lhs, (char **)0, (int *)0);
+    }
+  else
+#endif
+    v = find_variable (lhs);
+
+  if (v)
+    {
+      isint = integer_p (v);
+      VUNSETATTR (v, att_integer);
+    }
+
+#if defined (ARRAY_VARS)
+  if (isarr)
+    v = assign_array_element (lhs, rhs, 0);
+  else
+#endif
+    v = bind_variable (lhs, rhs, 0);
+
+  if (v && isint)
+    VSETATTR (v, att_integer);
+
+  return (v);
+}
+
+SHELL_VAR *
+bind_var_to_int (var, val)
+     char *var;
+     intmax_t val;
+{
+  char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
+
+  p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
+  return (bind_int_variable (var, p));
+}
+
+/* Do a function binding to a variable.  You pass the name and
+   the command to bind to.  This conses the name and command. */
+SHELL_VAR *
+bind_function (name, value)
+     const char *name;
+     COMMAND *value;
+{
+  SHELL_VAR *entry;
+
+  entry = find_function (name);
+  if (entry == 0)
+    {
+      BUCKET_CONTENTS *elt;
+
+      elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
+      entry = new_shell_variable (name);
+      elt->data = (PTR_T)entry;
+    }
+  else
+    INVALIDATE_EXPORTSTR (entry);
+
+  if (var_isset (entry))
+    dispose_command (function_cell (entry));
+
+  if (value)
+    var_setfunc (entry, copy_command (value));
+  else
+    var_setfunc (entry, 0);
+
+  VSETATTR (entry, att_function);
+
+  if (mark_modified_vars)
+    VSETATTR (entry, att_exported);
+
+  VUNSETATTR (entry, att_invisible);           /* Just to be sure */
+
+  if (exported_p (entry))
+    array_needs_making = 1;
+
+#if defined (PROGRAMMABLE_COMPLETION)
+  set_itemlist_dirty (&it_functions);
+#endif
+
+  return (entry);
+}
+
+#if defined (DEBUGGER)
+/* Bind a function definition, which includes source file and line number
+   information in addition to the command, into the FUNCTION_DEF hash table.*/
+void
+bind_function_def (name, value)
+     const char *name;
+     FUNCTION_DEF *value;
+{
+  FUNCTION_DEF *entry;
+  BUCKET_CONTENTS *elt;
+  COMMAND *cmd;
+
+  entry = find_function_def (name);
+  if (entry)
+    {
+      dispose_function_def_contents (entry);
+      entry = copy_function_def_contents (value, entry);
+    }
+  else
+    {
+      cmd = value->command;
+      value->command = 0;
+      entry = copy_function_def (value);
+      value->command = cmd;
+
+      elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
+      elt->data = (PTR_T *)entry;
+    }
+}
+#endif /* DEBUGGER */
+
+/* Add STRING, which is of the form foo=bar, to the temporary environment
+   HASH_TABLE (temporary_env).  The functions in execute_cmd.c are
+   responsible for moving the main temporary env to one of the other
+   temporary environments.  The expansion code in subst.c calls this. */
+int
+assign_in_env (word, flags)
+     WORD_DESC *word;
+     int flags;
+{
+  int offset;
+  char *name, *temp, *value;
+  SHELL_VAR *var;
+  const char *string;
+
+  string = word->word;
+
+  offset = assignment (string, 0);
+  name = savestring (string);
+  value = (char *)NULL;
+
+  if (name[offset] == '=')
+    {
+      name[offset] = 0;
+
+      /* ignore the `+' when assigning temporary environment */
+      if (name[offset - 1] == '+')
+       name[offset - 1] = '\0';
+
+      var = find_variable (name);
+      if (var && (readonly_p (var) || noassign_p (var)))
+       {
+         if (readonly_p (var))
+           err_readonly (name);
+         free (name);
+         return (0);
+       }
+
+      temp = name + offset + 1;
+      value = expand_assignment_string_to_string (temp, 0);
+    }
+
+  if (temporary_env == 0)
+    temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
+
+  var = hash_lookup (name, temporary_env);
+  if (var == 0)
+    var = make_new_variable (name, temporary_env);
+  else
+    FREE (value_cell (var));
+
+  if (value == 0)
+    {
+      value = (char *)xmalloc (1);     /* like do_assignment_internal */
+      value[0] = '\0';
+    }
+
+  var_setvalue (var, value);
+  var->attributes |= (att_exported|att_tempvar);
+  var->context = variable_context;     /* XXX */
+
+  INVALIDATE_EXPORTSTR (var);
+  var->exportstr = mk_env_string (name, value);
+
+  array_needs_making = 1;
+
+#if 0
+  if (ifsname (name))
+    setifs (var);
+else
+#endif
+  if (flags)
+    stupidly_hack_special_variables (name);
+
+  if (echo_command_at_execute)
+    /* The Korn shell prints the `+ ' in front of assignment statements,
+       so we do too. */
+    xtrace_print_assignment (name, value, 0, 1);
+
+  free (name);
+  return 1;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Copying variables                           */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef INCLUDE_UNUSED
+/* Copy VAR to a new data structure and return that structure. */
+SHELL_VAR *
+copy_variable (var)
+     SHELL_VAR *var;
+{
+  SHELL_VAR *copy = (SHELL_VAR *)NULL;
+
+  if (var)
+    {
+      copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
+
+      copy->attributes = var->attributes;
+      copy->name = savestring (var->name);
+
+      if (function_p (var))
+       var_setfunc (copy, copy_command (function_cell (var)));
+#if defined (ARRAY_VARS)
+      else if (array_p (var))
+       var_setarray (copy, array_copy (array_cell (var)));
+      else if (assoc_p (var))
+       var_setassoc (copy, assoc_copy (assoc_cell (var)));
+#endif
+      else if (value_cell (var))
+       var_setvalue (copy, savestring (value_cell (var)));
+      else
+       var_setvalue (copy, (char *)NULL);
+
+      copy->dynamic_value = var->dynamic_value;
+      copy->assign_func = var->assign_func;
+
+      copy->exportstr = COPY_EXPORTSTR (var);
+
+      copy->context = var->context;
+    }
+  return (copy);
+}
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Deleting and unsetting variables                  */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Dispose of the information attached to VAR. */
+static void
+dispose_variable_value (var)
+     SHELL_VAR *var;
+{
+  if (function_p (var))
+    dispose_command (function_cell (var));
+#if defined (ARRAY_VARS)
+  else if (array_p (var))
+    array_dispose (array_cell (var));
+  else if (assoc_p (var))
+    assoc_dispose (assoc_cell (var));
+#endif
+  else
+    FREE (value_cell (var));
+}
+
+void
+dispose_variable (var)
+     SHELL_VAR *var;
+{
+  if (var == 0)
+    return;
+
+  if (nofree_p (var) == 0)
+    dispose_variable_value (var);
+
+  FREE_EXPORTSTR (var);
+
+  free (var->name);
+
+  if (exported_p (var))
+    array_needs_making = 1;
+
+  free (var);
+}
+
+/* Unset the shell variable referenced by NAME. */
+int
+unbind_variable (name)
+     const char *name;
+{
+  return makunbound (name, shell_variables);
+}
+
+/* Unset the shell function named NAME. */
+int
+unbind_func (name)
+     const char *name;
+{
+  BUCKET_CONTENTS *elt;
+  SHELL_VAR *func;
+
+  elt = hash_remove (name, shell_functions, 0);
+
+  if (elt == 0)
+    return -1;
+
+#if defined (PROGRAMMABLE_COMPLETION)
+  set_itemlist_dirty (&it_functions);
+#endif
+
+  func = (SHELL_VAR *)elt->data;
+  if (func)
+    {
+      if (exported_p (func))
+       array_needs_making++;
+      dispose_variable (func);
+    }
+
+  free (elt->key);
+  free (elt);
+
+  return 0;  
+}
+
+#if defined (DEBUGGER)
+int
+unbind_function_def (name)
+     const char *name;
+{
+  BUCKET_CONTENTS *elt;
+  FUNCTION_DEF *funcdef;
+
+  elt = hash_remove (name, shell_function_defs, 0);
+
+  if (elt == 0)
+    return -1;
+
+  funcdef = (FUNCTION_DEF *)elt->data;
+  if (funcdef)
+    dispose_function_def (funcdef);
+
+  free (elt->key);
+  free (elt);
+
+  return 0;  
+}
+#endif /* DEBUGGER */
+
+/* Make the variable associated with NAME go away.  HASH_LIST is the
+   hash table from which this variable should be deleted (either
+   shell_variables or shell_functions).
+   Returns non-zero if the variable couldn't be found. */
+int
+makunbound (name, vc)
+     const char *name;
+     VAR_CONTEXT *vc;
+{
+  BUCKET_CONTENTS *elt, *new_elt;
+  SHELL_VAR *old_var;
+  VAR_CONTEXT *v;
+  char *t;
+
+  for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
+    if (elt = hash_remove (name, v->table, 0))
+      break;
+
+  if (elt == 0)
+    return (-1);
+
+  old_var = (SHELL_VAR *)elt->data;
+
+  if (old_var && exported_p (old_var))
+    array_needs_making++;
+
+  /* If we're unsetting a local variable and we're still executing inside
+     the function, just mark the variable as invisible.  The function
+     eventually called by pop_var_context() will clean it up later.  This
+     must be done so that if the variable is subsequently assigned a new
+     value inside the function, the `local' attribute is still present.
+     We also need to add it back into the correct hash table. */
+  if (old_var && local_p (old_var) && variable_context == old_var->context)
+    {
+      if (nofree_p (old_var))
+       var_setvalue (old_var, (char *)NULL);
+#if defined (ARRAY_VARS)
+      else if (array_p (old_var))
+       array_dispose (array_cell (old_var));
+      else if (assoc_p (old_var))
+       assoc_dispose (assoc_cell (old_var));
+#endif
+      else
+       FREE (value_cell (old_var));
+      /* Reset the attributes.  Preserve the export attribute if the variable
+        came from a temporary environment.  Make sure it stays local, and
+        make it invisible. */ 
+      old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
+      VSETATTR (old_var, att_local);
+      VSETATTR (old_var, att_invisible);
+      var_setvalue (old_var, (char *)NULL);
+      INVALIDATE_EXPORTSTR (old_var);
+
+      new_elt = hash_insert (savestring (old_var->name), v->table, 0);
+      new_elt->data = (PTR_T)old_var;
+      stupidly_hack_special_variables (old_var->name);
+
+      free (elt->key);
+      free (elt);
+      return (0);
+    }
+
+  /* Have to save a copy of name here, because it might refer to
+     old_var->name.  If so, stupidly_hack_special_variables will
+     reference freed memory. */
+  t = savestring (name);
+
+  free (elt->key);
+  free (elt);
+
+  dispose_variable (old_var);
+  stupidly_hack_special_variables (t);
+  free (t);
+
+  return (0);
+}
+
+/* Get rid of all of the variables in the current context. */
+void
+kill_all_local_variables ()
+{
+  VAR_CONTEXT *vc;
+
+  for (vc = shell_variables; vc; vc = vc->down)
+    if (vc_isfuncenv (vc) && vc->scope == variable_context)
+      break;
+  if (vc == 0)
+    return;            /* XXX */
+
+  if (vc->table && vc_haslocals (vc))
+    {
+      delete_all_variables (vc->table);
+      hash_dispose (vc->table);
+    }
+  vc->table = (HASH_TABLE *)NULL;
+}
+
+static void
+free_variable_hash_data (data)
+     PTR_T data;
+{
+  SHELL_VAR *var;
+
+  var = (SHELL_VAR *)data;
+  dispose_variable (var);
+}
+
+/* Delete the entire contents of the hash table. */
+void
+delete_all_variables (hashed_vars)
+     HASH_TABLE *hashed_vars;
+{
+  hash_flush (hashed_vars, free_variable_hash_data);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Setting variable attributes                    */
+/*                                                                 */
+/* **************************************************************** */
+
+#define FIND_OR_MAKE_VARIABLE(name, entry) \
+  do \
+    { \
+      entry = find_variable (name); \
+      if (!entry) \
+       { \
+         entry = bind_variable (name, "", 0); \
+         if (!no_invisible_vars && entry) entry->attributes |= att_invisible; \
+       } \
+    } \
+  while (0)
+
+/* Make the variable associated with NAME be readonly.
+   If NAME does not exist yet, create it. */
+void
+set_var_read_only (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+
+  FIND_OR_MAKE_VARIABLE (name, entry);
+  VSETATTR (entry, att_readonly);
+}
+
+#ifdef INCLUDE_UNUSED
+/* Make the function associated with NAME be readonly.
+   If NAME does not exist, we just punt, like auto_export code below. */
+void
+set_func_read_only (name)
+     const char *name;
+{
+  SHELL_VAR *entry;
+
+  entry = find_function (name);
+  if (entry)
+    VSETATTR (entry, att_readonly);
+}
+
+/* Make the variable associated with NAME be auto-exported.
+   If NAME does not exist yet, create it. */
+void
+set_var_auto_export (name)
+     char *name;
+{
+  SHELL_VAR *entry;
+
+  FIND_OR_MAKE_VARIABLE (name, entry);
+  set_auto_export (entry);
+}
+
+/* Make the function associated with NAME be auto-exported. */
+void
+set_func_auto_export (name)
+     const char *name;
+{
+  SHELL_VAR *entry;
+
+  entry = find_function (name);
+  if (entry)
+    set_auto_export (entry);
+}
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                  Creating lists of variables                    */
+/*                                                                 */
+/* **************************************************************** */
+
+static VARLIST *
+vlist_alloc (nentries)
+     int nentries;
+{
+  VARLIST  *vlist;
+
+  vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
+  vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
+  vlist->list_size = nentries;
+  vlist->list_len = 0;
+  vlist->list[0] = (SHELL_VAR *)NULL;
+
+  return vlist;
+}
+
+static VARLIST *
+vlist_realloc (vlist, n)
+     VARLIST *vlist;
+     int n;
+{
+  if (vlist == 0)
+    return (vlist = vlist_alloc (n));
+  if (n > vlist->list_size)
+    {
+      vlist->list_size = n;
+      vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
+    }
+  return vlist;
+}
+
+static void
+vlist_add (vlist, var, flags)
+     VARLIST *vlist;
+     SHELL_VAR *var;
+     int flags;
+{
+  register int i;
+
+  for (i = 0; i < vlist->list_len; i++)
+    if (STREQ (var->name, vlist->list[i]->name))
+      break;
+  if (i < vlist->list_len)
+    return;
+
+  if (i >= vlist->list_size)
+    vlist = vlist_realloc (vlist, vlist->list_size + 16);
+
+  vlist->list[vlist->list_len++] = var;
+  vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
+}
+
+/* Map FUNCTION over the variables in VAR_HASH_TABLE.  Return an array of the
+   variables for which FUNCTION returns a non-zero value.  A NULL value
+   for FUNCTION means to use all variables. */
+SHELL_VAR **
+map_over (function, vc)
+     sh_var_map_func_t *function;
+     VAR_CONTEXT *vc;
+{
+  VAR_CONTEXT *v;
+  VARLIST *vlist;
+  SHELL_VAR **ret;
+  int nentries;
+
+  for (nentries = 0, v = vc; v; v = v->down)
+    nentries += HASH_ENTRIES (v->table);
+
+  if (nentries == 0)
+    return (SHELL_VAR **)NULL;
+
+  vlist = vlist_alloc (nentries);
+
+  for (v = vc; v; v = v->down)
+    flatten (v->table, function, vlist, 0);
+
+  ret = vlist->list;
+  free (vlist);
+  return ret;
+}
+
+SHELL_VAR **
+map_over_funcs (function)
+     sh_var_map_func_t *function;
+{
+  VARLIST *vlist;
+  SHELL_VAR **ret;
+
+  if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
+    return ((SHELL_VAR **)NULL);
+
+  vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
+
+  flatten (shell_functions, function, vlist, 0);
+
+  ret = vlist->list;
+  free (vlist);
+  return ret;
+}
+
+/* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
+   elements for which FUNC succeeds to VLIST->list.  FLAGS is reserved
+   for future use.  Only unique names are added to VLIST.  If FUNC is
+   NULL, each variable in VAR_HASH_TABLE is added to VLIST.  If VLIST is
+   NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE.  If VLIST
+   and FUNC are both NULL, nothing happens. */
+static void
+flatten (var_hash_table, func, vlist, flags)
+     HASH_TABLE *var_hash_table;
+     sh_var_map_func_t *func;
+     VARLIST *vlist;
+     int flags;
+{
+  register int i;
+  register BUCKET_CONTENTS *tlist;
+  int r;
+  SHELL_VAR *var;
+
+  if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
+    return;
+
+  for (i = 0; i < var_hash_table->nbuckets; i++)
+    {
+      for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
+       {
+         var = (SHELL_VAR *)tlist->data;
+
+         r = func ? (*func) (var) : 1;
+         if (r && vlist)
+           vlist_add (vlist, var, flags);
+       }
+    }
+}
+
+void
+sort_variables (array)
+     SHELL_VAR **array;
+{
+  qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
+}
+
+static int
+qsort_var_comp (var1, var2)
+     SHELL_VAR **var1, **var2;
+{
+  int result;
+
+  if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
+    result = strcmp ((*var1)->name, (*var2)->name);
+
+  return (result);
+}
+
+/* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
+   which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
+static SHELL_VAR **
+vapply (func)
+     sh_var_map_func_t *func;
+{
+  SHELL_VAR **list;
+
+  list = map_over (func, shell_variables);
+  if (list /* && posixly_correct */)
+    sort_variables (list);
+  return (list);
+}
+
+/* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
+   which FUNC succeeds to an array of SHELL_VAR *s.  Returns the array. */
+static SHELL_VAR **
+fapply (func)
+     sh_var_map_func_t *func;
+{
+  SHELL_VAR **list;
+
+  list = map_over_funcs (func);
+  if (list /* && posixly_correct */)
+    sort_variables (list);
+  return (list);
+}
+
+/* Create a NULL terminated array of all the shell variables. */
+SHELL_VAR **
+all_shell_variables ()
+{
+  return (vapply ((sh_var_map_func_t *)NULL));
+}
+
+/* Create a NULL terminated array of all the shell functions. */
+SHELL_VAR **
+all_shell_functions ()
+{
+  return (fapply ((sh_var_map_func_t *)NULL));
+}
+
+static int
+visible_var (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0);
+}
+
+SHELL_VAR **
+all_visible_functions ()
+{
+  return (fapply (visible_var));
+}
+
+SHELL_VAR **
+all_visible_variables ()
+{
+  return (vapply (visible_var));
+}
+
+/* Return non-zero if the variable VAR is visible and exported.  Array
+   variables cannot be exported. */
+static int
+visible_and_exported (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && exported_p (var));
+}
+
+/* Candidate variables for the export environment are either valid variables
+   with the export attribute or invalid variables inherited from the initial
+   environment and simply passed through. */
+static int
+export_environment_candidate (var)
+     SHELL_VAR *var;
+{
+  return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var)));
+}
+
+/* Return non-zero if VAR is a local variable in the current context and
+   is exported. */
+static int
+local_and_exported (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
+}
+
+SHELL_VAR **
+all_exported_variables ()
+{
+  return (vapply (visible_and_exported));
+}
+
+SHELL_VAR **
+local_exported_variables ()
+{
+  return (vapply (local_and_exported));
+}
+
+static int
+variable_in_context (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
+}
+
+SHELL_VAR **
+all_local_variables ()
+{
+  VARLIST *vlist;
+  SHELL_VAR **ret;
+  VAR_CONTEXT *vc;
+
+  vc = shell_variables;
+  for (vc = shell_variables; vc; vc = vc->down)
+    if (vc_isfuncenv (vc) && vc->scope == variable_context)
+      break;
+
+  if (vc == 0)
+    {
+      internal_error (_("all_local_variables: no function context at current scope"));
+      return (SHELL_VAR **)NULL;
+    }
+  if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
+    return (SHELL_VAR **)NULL;
+    
+  vlist = vlist_alloc (HASH_ENTRIES (vc->table));
+
+  flatten (vc->table, variable_in_context, vlist, 0);
+
+  ret = vlist->list;
+  free (vlist);
+  if (ret)
+    sort_variables (ret);
+  return ret;
+}
+
+#if defined (ARRAY_VARS)
+/* Return non-zero if the variable VAR is visible and an array. */
+static int
+visible_array_vars (var)
+     SHELL_VAR *var;
+{
+  return (invisible_p (var) == 0 && array_p (var));
+}
+
+SHELL_VAR **
+all_array_variables ()
+{
+  return (vapply (visible_array_vars));
+}
+#endif /* ARRAY_VARS */
+
+char **
+all_variables_matching_prefix (prefix)
+     const char *prefix;
+{
+  SHELL_VAR **varlist;
+  char **rlist;
+  int vind, rind, plen;
+
+  plen = STRLEN (prefix);
+  varlist = all_visible_variables ();
+  for (vind = 0; varlist && varlist[vind]; vind++)
+    ;
+  if (varlist == 0 || vind == 0)
+    return ((char **)NULL);
+  rlist = strvec_create (vind + 1);
+  for (vind = rind = 0; varlist[vind]; vind++)
+    {
+      if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
+       rlist[rind++] = savestring (varlist[vind]->name);
+    }
+  rlist[rind] = (char *)0;
+  free (varlist);
+
+  return rlist;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*              Managing temporary variable scopes                 */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Make variable NAME have VALUE in the temporary environment. */
+static SHELL_VAR *
+bind_tempenv_variable (name, value)
+     const char *name;
+     char *value;
+{
+  SHELL_VAR *var;
+
+  var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
+
+  if (var)
+    {
+      FREE (value_cell (var));
+      var_setvalue (var, savestring (value));
+      INVALIDATE_EXPORTSTR (var);
+    }
+
+  return (var);
+}
+
+/* Find a variable in the temporary environment that is named NAME.
+   Return the SHELL_VAR *, or NULL if not found. */
+SHELL_VAR *
+find_tempenv_variable (name)
+     const char *name;
+{
+  return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
+}
+
+char **tempvar_list;
+int tvlist_ind;
+
+/* Push the variable described by (SHELL_VAR *)DATA down to the next
+   variable context from the temporary environment. */
+static void
+push_temp_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var, *v;
+  HASH_TABLE *binding_table;
+
+  var = (SHELL_VAR *)data;
+
+  binding_table = shell_variables->table;
+  if (binding_table == 0)
+    {
+      if (shell_variables == global_variables)
+       /* shouldn't happen */
+       binding_table = shell_variables->table = global_variables->table = hash_create (0);
+      else
+       binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
+    }
+
+  v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
+
+  /* XXX - should we set the context here?  It shouldn't matter because of how
+     assign_in_env works, but might want to check. */
+  if (binding_table == global_variables->table)                /* XXX */
+    var->attributes &= ~(att_tempvar|att_propagate);
+  else
+    {
+      var->attributes |= att_propagate;
+      if  (binding_table == shell_variables->table)
+       shell_variables->flags |= VC_HASTMPVAR;
+    }
+  v->attributes |= var->attributes;
+
+  if (find_special_var (var->name) >= 0)
+    tempvar_list[tvlist_ind++] = savestring (var->name);
+
+  dispose_variable (var);
+}
+
+static void
+propagate_temp_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var;
+
+  var = (SHELL_VAR *)data;
+  if (tempvar_p (var) && (var->attributes & att_propagate))
+    push_temp_var (data);
+  else
+    {
+      if (find_special_var (var->name) >= 0)
+       tempvar_list[tvlist_ind++] = savestring (var->name);
+      dispose_variable (var);
+    }
+}
+
+/* Free the storage used in the hash table for temporary
+   environment variables.  PUSHF is a function to be called
+   to free each hash table entry.  It takes care of pushing variables
+   to previous scopes if appropriate.  PUSHF stores names of variables
+   that require special handling (e.g., IFS) on tempvar_list, so this
+   function can call stupidly_hack_special_variables on all the
+   variables in the list when the temporary hash table is destroyed. */
+static void
+dispose_temporary_env (pushf)
+     sh_free_func_t *pushf;
+{
+  int i;
+
+  tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
+  tempvar_list[tvlist_ind = 0] = 0;
+    
+  hash_flush (temporary_env, pushf);
+  hash_dispose (temporary_env);
+  temporary_env = (HASH_TABLE *)NULL;
+
+  tempvar_list[tvlist_ind] = 0;
+
+  array_needs_making = 1;
+
+#if 0
+  sv_ifs ("IFS");              /* XXX here for now -- check setifs in assign_in_env */  
+#endif
+  for (i = 0; i < tvlist_ind; i++)
+    stupidly_hack_special_variables (tempvar_list[i]);
+
+  strvec_dispose (tempvar_list);
+  tempvar_list = 0;
+  tvlist_ind = 0;
+}
+
+void
+dispose_used_env_vars ()
+{
+  if (temporary_env)
+    {
+      dispose_temporary_env (propagate_temp_var);
+      maybe_make_export_env ();
+    }
+}
+
+/* Take all of the shell variables in the temporary environment HASH_TABLE
+   and make shell variables from them at the current variable context. */
+void
+merge_temporary_env ()
+{
+  if (temporary_env)
+    dispose_temporary_env (push_temp_var);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*          Creating and manipulating the environment              */
+/*                                                                 */
+/* **************************************************************** */
+
+static inline char *
+mk_env_string (name, value)
+     const char *name, *value;
+{
+  int name_len, value_len;
+  char *p;
+
+  name_len = strlen (name);
+  value_len = STRLEN (value);
+  p = (char *)xmalloc (2 + name_len + value_len);
+  strcpy (p, name);
+  p[name_len] = '=';
+  if (value && *value)
+    strcpy (p + name_len + 1, value);
+  else
+    p[name_len + 1] = '\0';
+  return (p);
+}
+
+#ifdef DEBUG
+/* Debugging */
+static int
+valid_exportstr (v)
+     SHELL_VAR *v;
+{
+  char *s;
+
+  s = v->exportstr;
+  if (s == 0)
+    {
+      internal_error (_("%s has null exportstr"), v->name);
+      return (0);
+    }
+  if (legal_variable_starter ((unsigned char)*s) == 0)
+    {
+      internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
+      return (0);
+    }
+  for (s = v->exportstr + 1; s && *s; s++)
+    {
+      if (*s == '=')
+       break;
+      if (legal_variable_char ((unsigned char)*s) == 0)
+       {
+         internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
+         return (0);
+       }
+    }
+  if (*s != '=')
+    {
+      internal_error (_("no `=' in exportstr for %s"), v->name);
+      return (0);
+    }
+  return (1);
+}
+#endif
+
+static char **
+make_env_array_from_var_list (vars)
+     SHELL_VAR **vars;
+{
+  register int i, list_index;
+  register SHELL_VAR *var;
+  char **list, *value;
+
+  list = strvec_create ((1 + strvec_len ((char **)vars)));
+
+#define USE_EXPORTSTR (value == var->exportstr)
+
+  for (i = 0, list_index = 0; var = vars[i]; i++)
+    {
+#if defined (__CYGWIN__)
+      /* We don't use the exportstr stuff on Cygwin at all. */
+      INVALIDATE_EXPORTSTR (var);
+#endif
+      if (var->exportstr)
+       value = var->exportstr;
+      else if (function_p (var))
+       value = named_function_string ((char *)NULL, function_cell (var), 0);
+#if defined (ARRAY_VARS)
+      else if (array_p (var))
+#  if 0
+       value = array_to_assignment_string (array_cell (var));
+#  else
+       continue;       /* XXX array vars cannot yet be exported */
+#  endif
+      else if (assoc_p (var))
+#  if 0
+       value = assoc_to_assignment_string (assoc_cell (var));
+#  else
+       continue;       /* XXX associative array vars cannot yet be exported */
+#  endif
+#endif
+      else
+       value = value_cell (var);
+
+      if (value)
+       {
+         /* Gee, I'd like to get away with not using savestring() if we're
+            using the cached exportstr... */
+         list[list_index] = USE_EXPORTSTR ? savestring (value)
+                                          : mk_env_string (var->name, value);
+
+         if (USE_EXPORTSTR == 0)
+           SAVE_EXPORTSTR (var, list[list_index]);
+
+         list_index++;
+#undef USE_EXPORTSTR
+
+#if 0  /* not yet */
+#if defined (ARRAY_VARS)
+         if (array_p (var) || assoc_p (var))
+           free (value);
+#endif
+#endif
+       }
+    }
+
+  list[list_index] = (char *)NULL;
+  return (list);
+}
+
+/* Make an array of assignment statements from the hash table
+   HASHED_VARS which contains SHELL_VARs.  Only visible, exported
+   variables are eligible. */
+static char **
+make_var_export_array (vcxt)
+     VAR_CONTEXT *vcxt;
+{
+  char **list;
+  SHELL_VAR **vars;
+
+#if 0
+  vars = map_over (visible_and_exported, vcxt);
+#else
+  vars = map_over (export_environment_candidate, vcxt);
+#endif
+
+  if (vars == 0)
+    return (char **)NULL;
+
+  list = make_env_array_from_var_list (vars);
+
+  free (vars);
+  return (list);
+}
+
+static char **
+make_func_export_array ()
+{
+  char **list;
+  SHELL_VAR **vars;
+
+  vars = map_over_funcs (visible_and_exported);
+  if (vars == 0)
+    return (char **)NULL;
+
+  list = make_env_array_from_var_list (vars);
+
+  free (vars);
+  return (list);
+}
+
+/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
+#define add_to_export_env(envstr,do_alloc) \
+do \
+  { \
+    if (export_env_index >= (export_env_size - 1)) \
+      { \
+       export_env_size += 16; \
+       export_env = strvec_resize (export_env, export_env_size); \
+       environ = export_env; \
+      } \
+    export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
+    export_env[export_env_index] = (char *)NULL; \
+  } while (0)
+
+/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
+   array with the same left-hand side.  Return the new EXPORT_ENV. */
+char **
+add_or_supercede_exported_var (assign, do_alloc)
+     char *assign;
+     int do_alloc;
+{
+  register int i;
+  int equal_offset;
+
+  equal_offset = assignment (assign, 0);
+  if (equal_offset == 0)
+    return (export_env);
+
+  /* If this is a function, then only supersede the function definition.
+     We do this by including the `=() {' in the comparison, like
+     initialize_shell_variables does. */
+  if (assign[equal_offset + 1] == '(' &&
+     strncmp (assign + equal_offset + 2, ") {", 3) == 0)               /* } */
+    equal_offset += 4;
+
+  for (i = 0; i < export_env_index; i++)
+    {
+      if (STREQN (assign, export_env[i], equal_offset + 1))
+       {
+         free (export_env[i]);
+         export_env[i] = do_alloc ? savestring (assign) : assign;
+         return (export_env);
+       }
+    }
+  add_to_export_env (assign, do_alloc);
+  return (export_env);
+}
+
+static void
+add_temp_array_to_env (temp_array, do_alloc, do_supercede)
+     char **temp_array;
+     int do_alloc, do_supercede;
+{
+  register int i;
+
+  if (temp_array == 0)
+    return;
+
+  for (i = 0; temp_array[i]; i++)
+    {
+      if (do_supercede)
+       export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
+      else
+       add_to_export_env (temp_array[i], do_alloc);
+    }
+
+  free (temp_array);
+}
+
+/* Make the environment array for the command about to be executed, if the
+   array needs making.  Otherwise, do nothing.  If a shell action could
+   change the array that commands receive for their environment, then the
+   code should `array_needs_making++'.
+
+   The order to add to the array is:
+       temporary_env
+       list of var contexts whose head is shell_variables
+       shell_functions
+
+  This is the shell variable lookup order.  We add only new variable
+  names at each step, which allows local variables and variables in
+  the temporary environments to shadow variables in the global (or
+  any previous) scope.
+*/
+
+static int
+n_shell_variables ()
+{
+  VAR_CONTEXT *vc;
+  int n;
+
+  for (n = 0, vc = shell_variables; vc; vc = vc->down)
+    n += HASH_ENTRIES (vc->table);
+  return n;
+}
+
+int
+chkexport (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v && exported_p (v))
+    {
+      array_needs_making = 1;
+      maybe_make_export_env ();
+      return 1;
+    }
+  return 0;
+}
+
+void
+maybe_make_export_env ()
+{
+  register char **temp_array;
+  int new_size;
+  VAR_CONTEXT *tcxt;
+
+  if (array_needs_making)
+    {
+      if (export_env)
+       strvec_flush (export_env);
+
+      /* Make a guess based on how many shell variables and functions we
+        have.  Since there will always be array variables, and array
+        variables are not (yet) exported, this will always be big enough
+        for the exported variables and functions. */
+      new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
+                HASH_ENTRIES (temporary_env);
+      if (new_size > export_env_size)
+       {
+         export_env_size = new_size;
+         export_env = strvec_resize (export_env, export_env_size);
+         environ = export_env;
+       }
+      export_env[export_env_index = 0] = (char *)NULL;
+
+      /* Make a dummy variable context from the temporary_env, stick it on
+        the front of shell_variables, call make_var_export_array on the
+        whole thing to flatten it, and convert the list of SHELL_VAR *s
+        to the form needed by the environment. */
+      if (temporary_env)
+       {
+         tcxt = new_var_context ((char *)NULL, 0);
+         tcxt->table = temporary_env;
+         tcxt->down = shell_variables;
+       }
+      else
+       tcxt = shell_variables;
+      
+      temp_array = make_var_export_array (tcxt);
+      if (temp_array)
+       add_temp_array_to_env (temp_array, 0, 0);
+
+      if (tcxt != shell_variables)
+       free (tcxt);
+
+#if defined (RESTRICTED_SHELL)
+      /* Restricted shells may not export shell functions. */
+      temp_array = restricted ? (char **)0 : make_func_export_array ();
+#else
+      temp_array = make_func_export_array ();
+#endif
+      if (temp_array)
+       add_temp_array_to_env (temp_array, 0, 0);
+
+      array_needs_making = 0;
+    }
+}
+
+/* This is an efficiency hack.  PWD and OLDPWD are auto-exported, so
+   we will need to remake the exported environment every time we
+   change directories.  `_' is always put into the environment for
+   every external command, so without special treatment it will always
+   cause the environment to be remade.
+
+   If there is no other reason to make the exported environment, we can
+   just update the variables in place and mark the exported environment
+   as no longer needing a remake. */
+void
+update_export_env_inplace (env_prefix, preflen, value)
+     char *env_prefix;
+     int preflen;
+     char *value;
+{
+  char *evar;
+
+  evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
+  strcpy (evar, env_prefix);
+  if (value)
+    strcpy (evar + preflen, value);
+  export_env = add_or_supercede_exported_var (evar, 0);
+}
+
+/* We always put _ in the environment as the name of this command. */
+void
+put_command_name_into_env (command_name)
+     char *command_name;
+{
+  update_export_env_inplace ("_=", 2, command_name);
+}
+
+#if 0  /* UNUSED -- it caused too many problems */
+void
+put_gnu_argv_flags_into_env (pid, flags_string)
+     intmax_t pid;
+     char *flags_string;
+{
+  char *dummy, *pbuf;
+  int l, fl;
+
+  pbuf = itos (pid);
+  l = strlen (pbuf);
+
+  fl = strlen (flags_string);
+
+  dummy = (char *)xmalloc (l + fl + 30);
+  dummy[0] = '_';
+  strcpy (dummy + 1, pbuf);
+  strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
+  dummy[l + 27] = '=';
+  strcpy (dummy + l + 28, flags_string);
+
+  free (pbuf);
+
+  export_env = add_or_supercede_exported_var (dummy, 0);
+}
+#endif
+
+/* **************************************************************** */
+/*                                                                 */
+/*                   Managing variable contexts                    */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Allocate and return a new variable context with NAME and FLAGS.
+   NAME can be NULL. */
+
+VAR_CONTEXT *
+new_var_context (name, flags)
+     char *name;
+     int flags;
+{
+  VAR_CONTEXT *vc;
+
+  vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
+  vc->name = name ? savestring (name) : (char *)NULL;
+  vc->scope = variable_context;
+  vc->flags = flags;
+
+  vc->up = vc->down = (VAR_CONTEXT *)NULL;
+  vc->table = (HASH_TABLE *)NULL;
+
+  return vc;
+}
+
+/* Free a variable context and its data, including the hash table.  Dispose
+   all of the variables. */
+void
+dispose_var_context (vc)
+     VAR_CONTEXT *vc;
+{
+  FREE (vc->name);
+
+  if (vc->table)
+    {
+      delete_all_variables (vc->table);
+      hash_dispose (vc->table);
+    }
+
+  free (vc);
+}
+
+/* Set VAR's scope level to the current variable context. */
+static int
+set_context (var)
+     SHELL_VAR *var;
+{
+  return (var->context = variable_context);
+}
+
+/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
+   temporary variables, and push it onto shell_variables.  This is
+   for shell functions. */
+VAR_CONTEXT *
+push_var_context (name, flags, tempvars)
+     char *name;
+     int flags;
+     HASH_TABLE *tempvars;
+{
+  VAR_CONTEXT *vc;
+
+  vc = new_var_context (name, flags);
+  vc->table = tempvars;
+  if (tempvars)
+    {
+      /* Have to do this because the temp environment was created before
+        variable_context was incremented. */
+      flatten (tempvars, set_context, (VARLIST *)NULL, 0);
+      vc->flags |= VC_HASTMPVAR;
+    }
+  vc->down = shell_variables;
+  shell_variables->up = vc;
+
+  return (shell_variables = vc);
+}
+
+static void
+push_func_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var, *v;
+
+  var = (SHELL_VAR *)data;
+
+  if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
+    {
+      /* Make sure we have a hash table to store the variable in while it is
+        being propagated down to the global variables table.  Create one if
+        we have to */
+      if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0)
+       shell_variables->table = hash_create (0);
+      /* XXX - should we set v->context here? */
+      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
+      if (shell_variables == global_variables)
+       var->attributes &= ~(att_tempvar|att_propagate);
+      else
+       shell_variables->flags |= VC_HASTMPVAR;
+      v->attributes |= var->attributes;
+    }
+  else
+    stupidly_hack_special_variables (var->name);       /* XXX */
+
+  dispose_variable (var);
+}
+
+/* Pop the top context off of VCXT and dispose of it, returning the rest of
+   the stack. */
+void
+pop_var_context ()
+{
+  VAR_CONTEXT *ret, *vcxt;
+
+  vcxt = shell_variables;
+  if (vc_isfuncenv (vcxt) == 0)
+    {
+      internal_error (_("pop_var_context: head of shell_variables not a function context"));
+      return;
+    }
+
+  if (ret = vcxt->down)
+    {
+      ret->up = (VAR_CONTEXT *)NULL;
+      shell_variables = ret;
+      if (vcxt->table)
+       hash_flush (vcxt->table, push_func_var);
+      dispose_var_context (vcxt);
+    }
+  else
+    internal_error (_("pop_var_context: no global_variables context"));
+}
+
+/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
+   all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
+void
+delete_all_contexts (vcxt)
+     VAR_CONTEXT *vcxt;
+{
+  VAR_CONTEXT *v, *t;
+
+  for (v = vcxt; v != global_variables; v = t)
+    {
+      t = v->down;
+      dispose_var_context (v);
+    }    
+
+  delete_all_variables (global_variables->table);
+  shell_variables = global_variables;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*        Pushing and Popping temporary variable scopes            */
+/*                                                                 */
+/* **************************************************************** */
+
+VAR_CONTEXT *
+push_scope (flags, tmpvars)
+     int flags;
+     HASH_TABLE *tmpvars;
+{
+  return (push_var_context ((char *)NULL, flags, tmpvars));
+}
+
+static void
+push_exported_var (data)
+     PTR_T data;
+{
+  SHELL_VAR *var, *v;
+
+  var = (SHELL_VAR *)data;
+
+  /* If a temp var had its export attribute set, or it's marked to be
+     propagated, bind it in the previous scope before disposing it. */
+  /* XXX - This isn't exactly right, because all tempenv variables have the
+    export attribute set. */
+#if 0
+  if (exported_p (var) || (var->attributes & att_propagate))
+#else
+  if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
+#endif
+    {
+      var->attributes &= ~att_tempvar;         /* XXX */
+      v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
+      if (shell_variables == global_variables)
+       var->attributes &= ~att_propagate;
+      v->attributes |= var->attributes;
+    }
+  else
+    stupidly_hack_special_variables (var->name);       /* XXX */
+
+  dispose_variable (var);
+}
+
+void
+pop_scope (is_special)
+     int is_special;
+{
+  VAR_CONTEXT *vcxt, *ret;
+
+  vcxt = shell_variables;
+  if (vc_istempscope (vcxt) == 0)
+    {
+      internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
+      return;
+    }
+
+  ret = vcxt->down;
+  if (ret)
+    ret->up = (VAR_CONTEXT *)NULL;
+
+  shell_variables = ret;
+
+  /* Now we can take care of merging variables in VCXT into set of scopes
+     whose head is RET (shell_variables). */
+  FREE (vcxt->name);
+  if (vcxt->table)
+    {
+      if (is_special)
+       hash_flush (vcxt->table, push_func_var);
+      else
+       hash_flush (vcxt->table, push_exported_var);
+      hash_dispose (vcxt->table);
+    }
+  free (vcxt);
+
+  sv_ifs ("IFS");      /* XXX here for now */
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*              Pushing and Popping function contexts              */
+/*                                                                 */
+/* **************************************************************** */
+
+static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
+static int dollar_arg_stack_slots;
+static int dollar_arg_stack_index;
+
+/* XXX - we might want to consider pushing and popping the `getopts' state
+   when we modify the positional parameters. */
+void
+push_context (name, is_subshell, tempvars)
+     char *name;       /* function name */
+     int is_subshell;
+     HASH_TABLE *tempvars;
+{
+  if (is_subshell == 0)
+    push_dollar_vars ();
+  variable_context++;
+  push_var_context (name, VC_FUNCENV, tempvars);
+}
+
+/* Only called when subshell == 0, so we don't need to check, and can
+   unconditionally pop the dollar vars off the stack. */
+void
+pop_context ()
+{
+  pop_dollar_vars ();
+  variable_context--;
+  pop_var_context ();
+
+  sv_ifs ("IFS");              /* XXX here for now */
+}
+
+/* Save the existing positional parameters on a stack. */
+void
+push_dollar_vars ()
+{
+  if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
+    {
+      dollar_arg_stack = (WORD_LIST **)
+       xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
+                 * sizeof (WORD_LIST **));
+    }
+  dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
+  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+}
+
+/* Restore the positional parameters from our stack. */
+void
+pop_dollar_vars ()
+{
+  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+    return;
+
+  remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
+  dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
+  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+  set_dollar_vars_unchanged ();
+}
+
+void
+dispose_saved_dollar_vars ()
+{
+  if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+    return;
+
+  dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
+  dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+}
+
+/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
+
+void
+push_args (list)
+     WORD_LIST *list;
+{
+#if defined (ARRAY_VARS) && defined (DEBUGGER)
+  SHELL_VAR *bash_argv_v, *bash_argc_v;
+  ARRAY *bash_argv_a, *bash_argc_a;
+  WORD_LIST *l;
+  arrayind_t i;
+  char *t;
+
+  GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
+  GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
+
+  for (l = list, i = 0; l; l = l->next, i++)
+    array_push (bash_argv_a, l->word->word);
+
+  t = itos (i);
+  array_push (bash_argc_a, t);
+  free (t);
+#endif /* ARRAY_VARS && DEBUGGER */
+}
+
+/* Remove arguments from BASH_ARGV array.  Pop top element off BASH_ARGC
+   array and use that value as the count of elements to remove from
+   BASH_ARGV. */
+void
+pop_args ()
+{
+#if defined (ARRAY_VARS) && defined (DEBUGGER)
+  SHELL_VAR *bash_argv_v, *bash_argc_v;
+  ARRAY *bash_argv_a, *bash_argc_a;
+  ARRAY_ELEMENT *ce;
+  intmax_t i;
+
+  GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
+  GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
+
+  ce = array_shift (bash_argc_a, 1, 0);
+  if (ce == 0 || legal_number (element_value (ce), &i) == 0)
+    i = 0;
+
+  for ( ; i > 0; i--)
+    array_pop (bash_argv_a);
+  array_dispose_element (ce);
+#endif /* ARRAY_VARS && DEBUGGER */
+}
+
+/*************************************************
+ *                                              *
+ *     Functions to manage special variables    *
+ *                                              *
+ *************************************************/
+
+/* Extern declarations for variables this code has to manage. */
+extern int eof_encountered, eof_encountered_limit, ignoreeof;
+
+#if defined (READLINE)
+extern int hostname_list_initialized;
+#endif
+
+/* An alist of name.function for each special variable.  Most of the
+   functions don't do much, and in fact, this would be faster with a
+   switch statement, but by the end of this file, I am sick of switch
+   statements. */
+
+#define SET_INT_VAR(name, intvar)  intvar = find_variable (name) != 0
+
+/* This table will be sorted with qsort() the first time it's accessed. */
+struct name_and_function {
+  char *name;
+  sh_sv_func_t *function;
+};
+
+static struct name_and_function special_vars[] = {
+  { "BASH_XTRACEFD", sv_xtracefd },
+
+#if defined (READLINE)
+#  if defined (STRICT_POSIX)
+  { "COLUMNS", sv_winsize },
+#  endif
+  { "COMP_WORDBREAKS", sv_comp_wordbreaks },
+#endif
+
+  { "FUNCNEST", sv_funcnest },
+
+  { "GLOBIGNORE", sv_globignore },
+
+#if defined (HISTORY)
+  { "HISTCONTROL", sv_history_control },
+  { "HISTFILESIZE", sv_histsize },
+  { "HISTIGNORE", sv_histignore },
+  { "HISTSIZE", sv_histsize },
+  { "HISTTIMEFORMAT", sv_histtimefmt },
+#endif
+
+#if defined (__CYGWIN__)
+  { "HOME", sv_home },
+#endif
+
+#if defined (READLINE)
+  { "HOSTFILE", sv_hostfile },
+#endif
+
+  { "IFS", sv_ifs },
+  { "IGNOREEOF", sv_ignoreeof },
+
+  { "LANG", sv_locale },
+  { "LC_ALL", sv_locale },
+  { "LC_COLLATE", sv_locale },
+  { "LC_CTYPE", sv_locale },
+  { "LC_MESSAGES", sv_locale },
+  { "LC_NUMERIC", sv_locale },
+  { "LC_TIME", sv_locale },
+
+#if defined (READLINE) && defined (STRICT_POSIX)
+  { "LINES", sv_winsize },
+#endif
+
+  { "MAIL", sv_mail },
+  { "MAILCHECK", sv_mail },
+  { "MAILPATH", sv_mail },
+
+  { "OPTERR", sv_opterr },
+  { "OPTIND", sv_optind },
+
+  { "PATH", sv_path },
+  { "POSIXLY_CORRECT", sv_strict_posix },
+
+#if defined (READLINE)
+  { "TERM", sv_terminal },
+  { "TERMCAP", sv_terminal },
+  { "TERMINFO", sv_terminal },
+#endif /* READLINE */
+
+  { "TEXTDOMAIN", sv_locale },
+  { "TEXTDOMAINDIR", sv_locale },
+
+#if defined (HAVE_TZSET)
+  { "TZ", sv_tz },
+#endif
+
+#if defined (HISTORY) && defined (BANG_HISTORY)
+  { "histchars", sv_histchars },
+#endif /* HISTORY && BANG_HISTORY */
+
+  { "ignoreeof", sv_ignoreeof },
+
+  { (char *)0, (sh_sv_func_t *)0 }
+};
+
+#define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
+
+static int
+sv_compare (sv1, sv2)
+     struct name_and_function *sv1, *sv2;
+{
+  int r;
+
+  if ((r = sv1->name[0] - sv2->name[0]) == 0)
+    r = strcmp (sv1->name, sv2->name);
+  return r;
+}
+
+static inline int
+find_special_var (name)
+     const char *name;
+{
+  register int i, r;
+
+  for (i = 0; special_vars[i].name; i++)
+    {
+      r = special_vars[i].name[0] - name[0];
+      if (r == 0)
+       r = strcmp (special_vars[i].name, name);
+      if (r == 0)
+       return i;
+      else if (r > 0)
+       /* Can't match any of rest of elements in sorted list.  Take this out
+          if it causes problems in certain environments. */
+       break;
+    }
+  return -1;
+}
+
+/* The variable in NAME has just had its state changed.  Check to see if it
+   is one of the special ones where something special happens. */
+void
+stupidly_hack_special_variables (name)
+     char *name;
+{
+  static int sv_sorted = 0;
+  int i;
+
+  if (sv_sorted == 0)  /* shouldn't need, but it's fairly cheap. */
+    {
+      qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
+               (QSFUNC *)sv_compare);
+      sv_sorted = 1;
+    }
+
+  i = find_special_var (name);
+  if (i != -1)
+    (*(special_vars[i].function)) (name);
+}
+
+/* Special variables that need hooks to be run when they are unset as part
+   of shell reinitialization should have their sv_ functions run here. */
+void
+reinit_special_variables ()
+{
+#if defined (READLINE)
+  sv_comp_wordbreaks ("COMP_WORDBREAKS");
+#endif
+  sv_globignore ("GLOBIGNORE");
+  sv_opterr ("OPTERR");
+}
+
+void
+sv_ifs (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable ("IFS");
+  setifs (v);
+}
+
+/* What to do just after the PATH variable has changed. */
+void
+sv_path (name)
+     char *name;
+{
+  /* hash -r */
+  phash_flush ();
+}
+
+/* What to do just after one of the MAILxxxx variables has changed.  NAME
+   is the name of the variable.  This is called with NAME set to one of
+   MAIL, MAILCHECK, or MAILPATH.  */
+void
+sv_mail (name)
+     char *name;
+{
+  /* If the time interval for checking the files has changed, then
+     reset the mail timer.  Otherwise, one of the pathname vars
+     to the users mailbox has changed, so rebuild the array of
+     filenames. */
+  if (name[4] == 'C')  /* if (strcmp (name, "MAILCHECK") == 0) */
+    reset_mail_timer ();
+  else
+    {
+      free_mail_files ();
+      remember_mail_dates ();
+    }
+}
+
+void
+sv_funcnest (name)
+     char *name;
+{
+  SHELL_VAR *v;
+  intmax_t num;
+
+  v = find_variable (name);
+  if (v == 0)
+    funcnest_max = 0;
+  else if (legal_number (value_cell (v), &num) == 0)
+    funcnest_max = 0;
+  else
+    funcnest_max = num;
+}
+
+/* What to do when GLOBIGNORE changes. */
+void
+sv_globignore (name)
+     char *name;
+{
+  if (privileged_mode == 0)
+    setup_glob_ignore (name);
+}
+
+#if defined (READLINE)
+void
+sv_comp_wordbreaks (name)
+     char *name;
+{
+  SHELL_VAR *sv;
+
+  sv = find_variable (name);
+  if (sv == 0)
+    reset_completer_word_break_chars ();
+}
+
+/* What to do just after one of the TERMxxx variables has changed.
+   If we are an interactive shell, then try to reset the terminal
+   information in readline. */
+void
+sv_terminal (name)
+     char *name;
+{
+  if (interactive_shell && no_line_editing == 0)
+    rl_reset_terminal (get_string_value ("TERM"));
+}
+
+void
+sv_hostfile (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  if (v == 0)
+    clear_hostname_list ();
+  else
+    hostname_list_initialized = 0;
+}
+
+#if defined (STRICT_POSIX)
+/* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
+   found in the initial environment) to override the terminal size reported by
+   the kernel. */
+void
+sv_winsize (name)
+     char *name;
+{
+  SHELL_VAR *v;
+  intmax_t xd;
+  int d;
+
+  if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
+    return;
+
+  v = find_variable (name);
+  if (v == 0 || var_isnull (v))
+    rl_reset_screen_size ();
+  else
+    {
+      if (legal_number (value_cell (v), &xd) == 0)
+       return;
+      winsize_assignment = 1;
+      d = xd;                  /* truncate */
+      if (name[0] == 'L')      /* LINES */
+       rl_set_screen_size (d, -1);
+      else                     /* COLUMNS */
+       rl_set_screen_size (-1, d);
+      winsize_assignment = 0;
+    }
+}
+#endif /* STRICT_POSIX */
+#endif /* READLINE */
+
+/* Update the value of HOME in the export environment so tilde expansion will
+   work on cygwin. */
+#if defined (__CYGWIN__)
+sv_home (name)
+     char *name;
+{
+  array_needs_making = 1;
+  maybe_make_export_env ();
+}
+#endif
+
+#if defined (HISTORY)
+/* What to do after the HISTSIZE or HISTFILESIZE variables change.
+   If there is a value for this HISTSIZE (and it is numeric), then stifle
+   the history.  Otherwise, if there is NO value for this variable,
+   unstifle the history.  If name is HISTFILESIZE, and its value is
+   numeric, truncate the history file to hold no more than that many
+   lines. */
+void
+sv_histsize (name)
+     char *name;
+{
+  char *temp;
+  intmax_t num;
+  int hmax;
+
+  temp = get_string_value (name);
+
+  if (temp && *temp)
+    {
+      if (legal_number (temp, &num))
+       {
+         hmax = num;
+         if (name[4] == 'S')
+           {
+             stifle_history (hmax);
+             hmax = where_history ();
+             if (history_lines_this_session > hmax)
+               history_lines_this_session = hmax;
+           }
+         else
+           {
+             history_truncate_file (get_string_value ("HISTFILE"), hmax);
+             if (hmax <= history_lines_in_file)
+               history_lines_in_file = hmax;
+           }
+       }
+    }
+  else if (name[4] == 'S')
+    unstifle_history ();
+}
+
+/* What to do after the HISTIGNORE variable changes. */
+void
+sv_histignore (name)
+     char *name;
+{
+  setup_history_ignore (name);
+}
+
+/* What to do after the HISTCONTROL variable changes. */
+void
+sv_history_control (name)
+     char *name;
+{
+  char *temp;
+  char *val;
+  int tptr;
+
+  history_control = 0;
+  temp = get_string_value (name);
+
+  if (temp == 0 || *temp == 0)
+    return;
+
+  tptr = 0;
+  while (val = extract_colon_unit (temp, &tptr))
+    {
+      if (STREQ (val, "ignorespace"))
+       history_control |= HC_IGNSPACE;
+      else if (STREQ (val, "ignoredups"))
+       history_control |= HC_IGNDUPS;
+      else if (STREQ (val, "ignoreboth"))
+       history_control |= HC_IGNBOTH;
+      else if (STREQ (val, "erasedups"))
+       history_control |= HC_ERASEDUPS;
+
+      free (val);
+    }
+}
+
+#if defined (BANG_HISTORY)
+/* Setting/unsetting of the history expansion character. */
+void
+sv_histchars (name)
+     char *name;
+{
+  char *temp;
+
+  temp = get_string_value (name);
+  if (temp)
+    {
+      history_expansion_char = *temp;
+      if (temp[0] && temp[1])
+       {
+         history_subst_char = temp[1];
+         if (temp[2])
+             history_comment_char = temp[2];
+       }
+    }
+  else
+    {
+      history_expansion_char = '!';
+      history_subst_char = '^';
+      history_comment_char = '#';
+    }
+}
+#endif /* BANG_HISTORY */
+
+void
+sv_histtimefmt (name)
+     char *name;
+{
+  SHELL_VAR *v;
+
+  v = find_variable (name);
+  history_write_timestamps = (v != 0);
+}
+#endif /* HISTORY */
+
+#if defined (HAVE_TZSET)
+void
+sv_tz (name)
+     char *name;
+{
+  if (chkexport (name))
+    tzset ();
+}
+#endif
+
+/* If the variable exists, then the value of it can be the number
+   of times we actually ignore the EOF.  The default is small,
+   (smaller than csh, anyway). */
+void
+sv_ignoreeof (name)
+     char *name;
+{
+  SHELL_VAR *tmp_var;
+  char *temp;
+
+  eof_encountered = 0;
+
+  tmp_var = find_variable (name);
+  ignoreeof = tmp_var != 0;
+  temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
+  if (temp)
+    eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
+  set_shellopts ();    /* make sure `ignoreeof' is/is not in $SHELLOPTS */
+}
+
+void
+sv_optind (name)
+     char *name;
+{
+  char *tt;
+  int s;
+
+  tt = get_string_value ("OPTIND");
+  if (tt && *tt)
+    {
+      s = atoi (tt);
+
+      /* According to POSIX, setting OPTIND=1 resets the internal state
+        of getopt (). */
+      if (s < 0 || s == 1)
+       s = 0;
+    }
+  else
+    s = 0;
+  getopts_reset (s);
+}
+
+void
+sv_opterr (name)
+     char *name;
+{
+  char *tt;
+
+  tt = get_string_value ("OPTERR");
+  sh_opterr = (tt && *tt) ? atoi (tt) : 1;
+}
+
+void
+sv_strict_posix (name)
+     char *name;
+{
+itrace("sv_strict_posix: entry");
+  SET_INT_VAR (name, posixly_correct);
+  posix_initialize (posixly_correct);
+#if defined (READLINE)
+  if (interactive_shell)
+    posix_readline_initialize (posixly_correct);
+#endif /* READLINE */
+  set_shellopts ();    /* make sure `posix' is/is not in $SHELLOPTS */
+itrace("sv_strict_posix: return");
+}
+
+void
+sv_locale (name)
+     char *name;
+{
+  char *v;
+
+  v = get_string_value (name);
+  if (name[0] == 'L' && name[1] == 'A')        /* LANG */
+    set_lang (name, v);
+  else
+    set_locale_var (name, v);          /* LC_*, TEXTDOMAIN* */
+}
+
+#if defined (ARRAY_VARS)
+void
+set_pipestatus_array (ps, nproc)
+     int *ps;
+     int nproc;
+{
+  SHELL_VAR *v;
+  ARRAY *a;
+  ARRAY_ELEMENT *ae;
+  register int i;
+  char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
+
+  v = find_variable ("PIPESTATUS");
+  if (v == 0)
+    v = make_new_array_variable ("PIPESTATUS");
+  if (array_p (v) == 0)
+    return;            /* Do nothing if not an array variable. */
+  a = array_cell (v);
+
+  if (a == 0 || array_num_elements (a) == 0)
+    {
+      for (i = 0; i < nproc; i++)      /* was ps[i] != -1, not i < nproc */
+       {
+         t = inttostr (ps[i], tbuf, sizeof (tbuf));
+         array_insert (a, i, t);
+       }
+      return;
+    }
+
+  /* Fast case */
+  if (array_num_elements (a) == nproc && nproc == 1)
+    {
+      ae = element_forw (a->head);
+      free (element_value (ae));
+      ae->value = itos (ps[0]);
+    }
+  else if (array_num_elements (a) <= nproc)
+    {
+      /* modify in array_num_elements members in place, then add */
+      ae = a->head;
+      for (i = 0; i < array_num_elements (a); i++)
+       {
+         ae = element_forw (ae);
+         free (element_value (ae));
+         ae->value = itos (ps[i]);
+       }
+      /* add any more */
+      for ( ; i < nproc; i++)
+       {
+         t = inttostr (ps[i], tbuf, sizeof (tbuf));
+         array_insert (a, i, t);
+       }
+    }
+  else
+    {
+      /* deleting elements.  it's faster to rebuild the array. */        
+      array_flush (a);
+      for (i = 0; ps[i] != -1; i++)
+       {
+         t = inttostr (ps[i], tbuf, sizeof (tbuf));
+         array_insert (a, i, t);
+       }
+    }
+}
+
+ARRAY *
+save_pipestatus_array ()
+{
+  SHELL_VAR *v;
+  ARRAY *a, *a2;
+
+  v = find_variable ("PIPESTATUS");
+  if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
+    return ((ARRAY *)NULL);
+    
+  a = array_cell (v);
+  a2 = array_copy (array_cell (v));
+
+  return a2;
+}
+
+void
+restore_pipestatus_array (a)
+     ARRAY *a;
+{
+  SHELL_VAR *v;
+  ARRAY *a2;
+
+  v = find_variable ("PIPESTATUS");
+  /* XXX - should we still assign even if existing value is NULL? */
+  if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
+    return;
+
+  a2 = array_cell (v);
+  var_setarray (v, a); 
+
+  array_dispose (a2);
+}
+#endif
+
+void
+set_pipestatus_from_exit (s)
+     int s;
+{
+#if defined (ARRAY_VARS)
+  static int v[2] = { 0, -1 };
+
+  v[0] = s;
+  set_pipestatus_array (v, 1);
+#endif
+}
+
+void
+sv_xtracefd (name)
+     char *name;
+{
+  SHELL_VAR *v;
+  char *t, *e;
+  int fd;
+  FILE *fp;
+
+  v = find_variable (name);
+  if (v == 0)
+    {
+      xtrace_reset ();
+      return;
+    }
+
+  t = value_cell (v);
+  if (t == 0 || *t == 0)
+    xtrace_reset ();
+  else
+    {
+      fd = (int)strtol (t, &e, 10);
+      if (e != t && *e == '\0' && sh_validfd (fd))
+       {
+         fp = fdopen (fd, "w");
+         if (fp == 0)
+           internal_error (_("%s: %s: cannot open as FILE"), name, value_cell (v));
+         else
+           xtrace_set (fd, fp);
+       }
+      else
+       internal_error (_("%s: %s: invalid value for trace file descriptor"), name, value_cell (v));
+    }
+}