summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2012-01-09 08:29:54 -0500
committerChet Ramey <chet.ramey@case.edu>2012-01-09 08:29:54 -0500
commitc5402025f163afaf66b54f1ed57a17d16c61a284 (patch)
tree1a44d4d72b8e9aaa6208f3b5e332a63b3d546d55
parent122f603c917da62f45531a1cf715f78f99463dd8 (diff)
downloadbash-c5402025f163afaf66b54f1ed57a17d16c61a284.tar.gz
commit bash-20111007 snapshot
-rw-r--r--CWRU/CWRU.chlog59
-rw-r--r--CWRU/CWRU.chlog~54
-rw-r--r--MANIFEST1
-rw-r--r--Makefile.in24
-rw-r--r--Makefile.in~1534
-rw-r--r--assoc.c32
-rw-r--r--assoc.h1
-rw-r--r--builtins/common.c~892
-rw-r--r--builtins/set.def~859
-rw-r--r--doc/bash.114
-rw-r--r--doc/bash.1~11
-rw-r--r--doc/bashref.texi12
-rw-r--r--doc/bashref.texi~11
-rw-r--r--doc/version.texi6
-rw-r--r--doc/version.texi~4
-rw-r--r--error.c~457
-rw-r--r--flags.c1
-rw-r--r--jobs.c2
-rw-r--r--jobs.c~4308
-rw-r--r--lib/sh/Makefile.in35
-rw-r--r--lib/sh/Makefile.in~554
-rw-r--r--pathexp.c4
-rw-r--r--pcomplete.c20
-rw-r--r--pcomplete.c~27
-rw-r--r--po/LINGUAS2
-rw-r--r--po/LINGUAS~2
-rw-r--r--po/it.po5226
-rw-r--r--po/nl.po54
-rw-r--r--print_cmd.c7
-rw-r--r--tests/array.right6
-rw-r--r--tests/array2.sub3
-rw-r--r--tests/redir.right1
-rw-r--r--tests/redir.tests2
-rw-r--r--tests/redir10.sub25
-rw-r--r--variables.c14
-rw-r--r--variables.c~4822
36 files changed, 18996 insertions, 90 deletions
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog
index 8a25a511..c00ea942 100644
--- a/CWRU/CWRU.chlog
+++ b/CWRU/CWRU.chlog
@@ -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>
diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~
index 34079445..3cd9be24 100644
--- a/CWRU/CWRU.chlog~
+++ b/CWRU/CWRU.chlog~
@@ -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>
diff --git a/MANIFEST b/MANIFEST
index 878b7626..2e2163b9 100644
--- 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
diff --git a/Makefile.in b/Makefile.in
index ad57b27a..b5a2193c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
index 00000000..20c2d195
--- /dev/null
+++ b/Makefile.in~
@@ -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 bbc7b177..5d3cd11b 100644
--- 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 1ec1f6b2..db8383b2 100644
--- 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
index 00000000..83328319
--- /dev/null
+++ b/builtins/common.c~
@@ -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
index 00000000..b0939bfa
--- /dev/null
+++ b/builtins/set.def~
@@ -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);
+}
diff --git a/doc/bash.1 b/doc/bash.1
index bfe60293..27e26ac0 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -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
diff --git a/doc/bash.1~ b/doc/bash.1~
index 3a61ea48..0a39cd34 100644
--- a/doc/bash.1~
+++ b/doc/bash.1~
@@ -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
diff --git a/doc/bashref.texi b/doc/bashref.texi
index ec4cc91c..29a04216 100644
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -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
diff --git a/doc/bashref.texi~ b/doc/bashref.texi~
index f5c83d5d..aeac1945 100644
--- a/doc/bashref.texi~
+++ b/doc/bashref.texi~
@@ -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
diff --git a/doc/version.texi b/doc/version.texi
index 40b6027a..9af33959 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -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
diff --git a/doc/version.texi~ b/doc/version.texi~
index 87225465..40b6027a 100644
--- a/doc/version.texi~
+++ b/doc/version.texi~
@@ -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
index 00000000..bcee176a
--- /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 d3b38ad3..0ccdb0bb 100644
--- 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 17615c71..2f21b171 100644
--- 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
index 00000000..17615c71
--- /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 */
diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in
index d97cd99b..52482552 100644
--- a/lib/sh/Makefile.in
+++ b/lib/sh/Makefile.in
@@ -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
index 00000000..d97cd99b
--- /dev/null
+++ b/lib/sh/Makefile.in~
@@ -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
diff --git a/pathexp.c b/pathexp.c
index f2399568..31d730a0 100644
--- 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;
diff --git a/pcomplete.c b/pcomplete.c
index a0d27bab..1ed5ac93 100644
--- a/pcomplete.c
+++ b/pcomplete.c
@@ -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
diff --git a/pcomplete.c~ b/pcomplete.c~
index 942aae4d..522f765b 100644
--- a/pcomplete.c~
+++ b/pcomplete.c~
@@ -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);
diff --git a/po/LINGUAS b/po/LINGUAS
index 031b800c..afa579c9 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -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
index 00000000..031b800c
--- /dev/null
+++ b/po/LINGUAS~
@@ -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
index 00000000..81cf39d4
--- /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\"."
diff --git a/po/nl.po b/po/nl.po
index 7c3f3906..6788ea82 100644
--- 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"
diff --git a/print_cmd.c b/print_cmd.c
index d4823edf..3ceccc66 100644
--- a/print_cmd.c
+++ b/print_cmd.c
@@ -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);
diff --git a/tests/array.right b/tests/array.right
index dbb566d1..056892d4 100644
--- a/tests/array.right
+++ b/tests/array.right
@@ -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
diff --git a/tests/array2.sub b/tests/array2.sub
index 0e6417d7..44bb7c5b 100644
--- a/tests/array2.sub
+++ b/tests/array2.sub
@@ -1 +1,4 @@
+declare -r []=asdf
+declare -r a[]=asdf
+
declare -a ''=(a 'b c')
diff --git a/tests/redir.right b/tests/redir.right
index f816c63b..12b944b1 100644
--- a/tests/redir.right
+++ b/tests/redir.right
@@ -139,3 +139,4 @@ bix ()
echo foo 2>&1 | cat
}
foo
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
diff --git a/tests/redir.tests b/tests/redir.tests
index 37759b5a..c2e48663 100644
--- a/tests/redir.tests
+++ b/tests/redir.tests
@@ -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
index 00000000..27c48e82
--- /dev/null
+++ b/tests/redir10.sub
@@ -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
diff --git a/variables.c b/variables.c
index 7bb850fa..85f7bb4f 100644
--- a/variables.c
+++ b/variables.c
@@ -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
index 00000000..98d75164
--- /dev/null
+++ b/variables.c~
@@ -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));
+ }
+}