diff --color -Naur zsh-4.3.6.ori/configure.ac zsh-4.3.6.new/configure.ac
--- zsh-4.3.6.ori/configure.ac	2008-03-28 12:49:32.000000000 +0100
+++ zsh-4.3.6.new/configure.ac	2022-03-02 12:32:49.070991312 +0100
@@ -1113,6 +1113,7 @@
 	       getlogin getpwent getpwnam getpwuid getgrgid getgrnam \
 	       initgroups nis_list \
 	       setuid seteuid setreuid setresuid setsid \
+	       setgid setegid setregid setresgid \
 	       memcpy memmove strstr strerror strtoul \
 	       getrlimit getrusage \
 	       setlocale \
diff --color -Naur zsh-4.3.6.ori/configure.ac.orig zsh-4.3.6.new/configure.ac.orig
--- zsh-4.3.6.ori/configure.ac.orig	1970-01-01 01:00:00.000000000 +0100
+++ zsh-4.3.6.new/configure.ac.orig	2022-03-02 12:31:34.134390590 +0100
@@ -0,0 +1,2880 @@
+dnl
+dnl  configure.ac: Configure template for zsh.
+dnl  Process this file with autoconf to produce a configure script.
+dnl
+dnl  Copyright (c) 1995-1997 Richard Coleman
+dnl  All rights reserved.
+dnl
+dnl  Permission is hereby granted, without written agreement and without
+dnl  license or royalty fees, to use, copy, modify, and distribute this
+dnl  software and to distribute modified versions of this software for any
+dnl  purpose, provided that the above copyright notice and the following
+dnl  two paragraphs appear in all copies of this software.
+dnl
+dnl  In no event shall Richard Coleman or the Zsh Development Group be liable
+dnl  to any party for direct, indirect, special, incidental, or consequential
+dnl  damages arising out of the use of this software and its documentation,
+dnl  even if Richard Coleman and the Zsh Development Group have been advised of
+dnl  the possibility of such damage.
+dnl
+dnl  Richard Coleman and the Zsh Development Group specifically disclaim any
+dnl  warranties, including, but not limited to, the implied warranties of
+dnl  merchantability and fitness for a particular purpose.  The software
+dnl  provided hereunder is on an "as is" basis, and Richard Coleman and the
+dnl  Zsh Development Group have no obligation to provide maintenance,
+dnl  support, updates, enhancements, or modifications.
+dnl
+
+AC_INIT(Src/zsh.h)
+AC_PREREQ(2.53b)
+AC_CONFIG_HEADER(config.h)
+
+dnl What version of zsh are we building ?
+. ${srcdir}/Config/version.mk
+echo "configuring for zsh $VERSION"
+
+dnl ----------------------------------------------
+dnl CHECK FOR MACHINE/VENDOR/OPERATING SYSTEM TYPE
+dnl ----------------------------------------------
+dnl Find out machine type, vendor, and operating system
+dnl What type of host is this?
+AC_CANONICAL_HOST
+AC_DEFINE_UNQUOTED(MACHTYPE, "$host_cpu",
+[Define to be the machine type (microprocessor class or machine model).])
+AC_DEFINE_UNQUOTED(VENDOR,   "$host_vendor",
+[Define to be a string corresponding the vendor of the machine.])
+AC_DEFINE_UNQUOTED(OSTYPE,   "$host_os",
+[Define to be the name of the operating system.])
+
+dnl -----------------------------
+dnl CHECKING COMMAND LINE OPTIONS
+dnl -----------------------------
+dnl Handle --program-prefix, --program-suffix, etc.
+zsh_ARG_PROGRAM
+
+dnl Handle setting of compile flags (CPPFLAGS, CFLAGS, LDFLAGS, LIBS).
+zsh_COMPILE_FLAGS($CPPFLAGS, $CFLAGS, $LDFLAGS, $LIBS)
+
+dnl Do you want to debug zsh?
+ifdef([zsh-debug],[undefine([zsh-debug])])dnl
+AH_TEMPLATE([DEBUG],
+[Define to 1 if you want to debug zsh.])
+AC_ARG_ENABLE(zsh-debug,
+AC_HELP_STRING([--enable-zsh-debug], [compile with debug code and debugger symbols]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(DEBUG)
+fi])
+
+dnl Do you want zsh memory allocation routines.
+ifdef([zsh-mem],[undefine([zsh-mem])])dnl
+AH_TEMPLATE([ZSH_MEM],
+[Define to 1 if you want to use zsh's own memory allocation routines])
+AC_ARG_ENABLE(zsh-mem,
+AC_HELP_STRING([--enable-zsh-mem], [compile with zsh memory allocation routines]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(ZSH_MEM)
+fi])
+
+dnl Do you want to debug zsh memory allocation routines.
+ifdef([zsh-mem-debug],[undefine([zsh-mem-debug])])dnl
+AH_TEMPLATE([ZSH_MEM_DEBUG],
+[Define to 1 if you want to debug zsh memory allocation routines.])
+AC_ARG_ENABLE(zsh-mem-debug,
+AC_HELP_STRING([--enable-zsh-mem-debug], [debug zsh memory allocation routines]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(ZSH_MEM_DEBUG)
+fi])
+
+dnl Do you want to print warnings when errors in memory allocation.
+AH_TEMPLATE([ZSH_MEM_WARNING],
+[Define to 1 if you want to turn on warnings of memory allocation errors])
+ifdef([zsh-mem-warning],[undefine([zsh-mem-warning])])dnl
+AC_ARG_ENABLE(zsh-mem-warning,
+AC_HELP_STRING([--enable-zsh-mem-warning], [print warnings for errors in memory allocation]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(ZSH_MEM_WARNING)
+fi])
+
+dnl Do you want to turn on error checking for free().
+ifdef([zsh-secure-free],[undefine([zsh-secure-free])])dnl
+AH_TEMPLATE([ZSH_SECURE_FREE],
+[Define to 1 if you want to turn on memory checking for free().])
+AC_ARG_ENABLE(zsh-secure-free,
+AC_HELP_STRING([--enable-zsh-secure-free], [turn on error checking for free()]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(ZSH_SECURE_FREE)
+fi])
+
+dnl Do you want debugging information on internal hash tables.
+dnl This turns on the `hashinfo' builtin command.
+ifdef([zsh-hash-debug],[undefine([zsh-hash-debug])])dnl
+AH_TEMPLATE([ZSH_HASH_DEBUG],
+[Define to 1 if you want to get debugging information on internal
+ hash tables.  This turns on the `hashinfo' builtin.])
+AC_ARG_ENABLE(zsh-hash-debug,
+AC_HELP_STRING([--enable-zsh-hash-debug], [turn on debugging of internal hash tables]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(ZSH_HASH_DEBUG)
+fi])
+
+dnl Pathnames for global zsh scripts
+ifdef([etcdir],[undefine([etcdir])])dnl
+AC_ARG_ENABLE(etcdir,
+AC_HELP_STRING([--enable-etcdir=DIR], [the default directory for global zsh scripts]),
+[etcdir="$enableval"], [etcdir=/etc])
+
+ifdef([zshenv],[undefine([zshenv])])dnl
+AC_ARG_ENABLE(zshenv,
+AC_HELP_STRING([--enable-zshenv=FILE], [the full pathname of the global zshenv script]),
+[zshenv="$enableval"],
+[if test "x$etcdir" = xno; then
+  zshenv=no
+else
+  zshenv="$etcdir/zshenv"
+fi])
+AH_TEMPLATE([GLOBAL_ZSHENV],
+[The global file to source absolutely first whenever zsh is run;
+ if undefined, don't source anything.])
+if test "x$zshenv" != xno; then
+  AC_DEFINE_UNQUOTED(GLOBAL_ZSHENV, "$zshenv")
+fi
+
+ifdef([zshrc],[undefine([zshrc])])dnl
+AC_ARG_ENABLE(zshrc,
+AC_HELP_STRING([--enable-zshrc=FILE], [the full pathname of the global zshrc script]),
+[zshrc="$enableval"],
+[if test "x$etcdir" = xno; then
+  zshrc=no
+else
+  zshrc="$etcdir/zshrc"
+fi])
+AH_TEMPLATE([GLOBAL_ZSHRC],
+[The global file to source whenever zsh is run;
+ if undefined, don't source anything])
+if test "x$zshrc" != xno; then
+  AC_DEFINE_UNQUOTED(GLOBAL_ZSHRC, "$zshrc")
+fi
+
+ifdef([zprofile],[undefine([zprofile])])dnl
+AC_ARG_ENABLE(zprofile,
+AC_HELP_STRING([--enable-zprofile=FILE], [the full pathname of the global zprofile script]),
+[zprofile="$enableval"],
+[if test "x$etcdir" = xno; then
+  zprofile=no
+else
+  zprofile="$etcdir/zprofile"
+fi])
+AH_TEMPLATE([GLOBAL_ZPROFILE],
+[The global file to source whenever zsh is run as a login shell,
+ before zshrc is read; if undefined, don't source anything.])
+if test "x$zprofile" != xno; then
+  AC_DEFINE_UNQUOTED(GLOBAL_ZPROFILE, "$zprofile")
+fi
+
+ifdef([zlogin],[undefine([zlogin])])dnl
+AC_ARG_ENABLE(zlogin,
+AC_HELP_STRING([--enable-zlogin=FILE], [the full pathname of the global zlogin script]),
+[zlogin="$enableval"],
+[if test "x$etcdir" = xno; then
+  zlogin=no
+else
+  zlogin="$etcdir/zlogin"
+fi])
+AH_TEMPLATE([GLOBAL_ZLOGIN],
+[The global file to source whenever zsh is run as a login shell;
+ if undefined, don't source anything])
+if test "x$zlogin" != xno; then
+  AC_DEFINE_UNQUOTED(GLOBAL_ZLOGIN, "$zlogin")
+fi
+
+ifdef([zlogout],[undefine([zlogout])])dnl
+AC_ARG_ENABLE(zlogout,
+AC_HELP_STRING([--enable-zlogout=FILE], [the full pathname of the global zlogout script]),
+[zlogout="$enableval"],
+[if test "x$etcdir" = xno; then
+  zlogout=no
+else
+  zlogout="$etcdir/zlogout"
+fi])
+AH_TEMPLATE([GLOBAL_ZLOGOUT],
+[The global file to source whenever zsh was run as a login shell.
+ This is sourced right before exiting.  If undefined, don't source
+ anything.])
+if test "x$zlogout" != xno; then
+  AC_DEFINE_UNQUOTED(GLOBAL_ZLOGOUT, "$zlogout")
+fi
+
+AC_SUBST(zshenv)dnl
+AC_SUBST(zshrc)dnl
+AC_SUBST(zprofile)dnl
+AC_SUBST(zlogin)dnl
+AC_SUBST(zlogout)dnl
+
+dnl Do you want large file support, if available?
+ifdef([lfs],[undefine([lfs])])dnl
+AC_ARG_ENABLE(lfs,
+AC_HELP_STRING([--disable-lfs], [turn off support for large files]),
+[lfs="$enableval"], [lfs=yes])
+
+dnl Do you want dynamically loaded binary modules.
+ifdef([dynamic],[undefine([dynamic])])dnl
+AC_ARG_ENABLE(dynamic,
+AC_HELP_STRING([--disable-dynamic], [turn off dynamically loaded binary modules]),
+[dynamic="$enableval"], [dynamic=yes])
+
+dnl Do you want to disable restricted on r* commands
+ifdef([restricted-r],[undefine([restricted-r])])dnl
+AH_TEMPLATE([RESTRICTED_R],
+[Undefine this if you don't want to get a restricted shell
+ when zsh is exec'd with basename that starts with r.
+ By default this is defined.])
+AC_ARG_ENABLE(restricted-r,
+AC_HELP_STRING([--disable-restricted-r], [turn off r* invocation for restricted shell]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(RESTRICTED_R)
+fi],
+AC_DEFINE(RESTRICTED_R)
+)
+
+dnl Do you want to disable use of locale functions
+AH_TEMPLATE([CONFIG_LOCALE],
+[Undefine if you don't want local features.  By default this is defined.])
+AC_ARG_ENABLE([locale],
+AC_HELP_STRING([--disable-locale], [turn off locale features]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(CONFIG_LOCALE)
+fi],
+AC_DEFINE(CONFIG_LOCALE)
+)
+
+dnl Do you want to compile as K&R C.
+AC_ARG_ENABLE(ansi2knr,
+AC_HELP_STRING([--enable-ansi2knr], [translate source to K&R C before compiling]),
+[ansi2knr="$enableval"], [ansi2knr=default])
+
+ifdef([fndir],[undefine([fndir])])dnl
+AC_ARG_ENABLE(fndir,
+AC_HELP_STRING([--enable-fndir=DIR], [the directory in which to install functions]),
+dnl ${VERSION} to be determined at compile time.
+[if test x$enableval = xyes; then
+  fndir=${datadir}/${tzsh_name}/'${VERSION}'/functions
+else
+  fndir="$enableval"
+fi], [fndir=${datadir}/${tzsh_name}/'${VERSION}'/functions])
+
+ifdef([sitefndir],[undefine([sitefndir])])dnl
+AC_ARG_ENABLE(site-fndir,
+AC_HELP_STRING([--enable-site-fndir=DIR], [same for site functions (not version specific)]),
+[if test x$enableval = xyes; then
+  sitefndir=${datadir}/${tzsh_name}/site-functions
+else
+  sitefndir="$enableval"
+fi], [sitefndir=${datadir}/${tzsh_name}/site-functions])
+
+ifdef([function_subdirs],[undefine([function_subdirs])])
+AC_ARG_ENABLE(function-subdirs,
+AC_HELP_STRING([--enable-function-subdirs], [install functions in subdirectories]))
+
+if test "x${enable_function_subdirs}" != x &&
+  test "x${enable_function_subdirs}" != xno; then
+  FUNCTIONS_SUBDIRS=yes
+else
+  FUNCTIONS_SUBDIRS=no
+fi
+
+AC_SUBST(fndir)dnl
+AC_SUBST(sitefndir)dnl
+AC_SUBST(FUNCTIONS_SUBDIRS)dnl
+
+dnl Directories for scripts such as newuser.
+
+ifdef([scriptdir],[undefine([scriptdir])])dnl
+AC_ARG_ENABLE(scriptdir,
+AC_HELP_STRING([--enable-scriptdir=DIR], [the directory in which to install scripts]),
+dnl ${VERSION} to be determined at compile time.
+[if test x$enableval = xyes; then
+  scriptdir=${datadir}/${tzsh_name}/'${VERSION}'/scripts
+else
+  scriptdir="$enableval"
+fi], [scriptdir=${datadir}/${tzsh_name}/'${VERSION}'/scripts])
+
+ifdef([sitescriptdir],[undefine([sitescriptdir])])dnl
+AC_ARG_ENABLE(site-scriptdir,
+AC_HELP_STRING([--enable-site-scriptdir=DIR], [same for site scripts (not version specific)]),
+[if test x$enableval = xyes; then
+  sitescriptdir=${datadir}/${tzsh_name}/scripts
+else
+  sitescriptdir="$enableval"
+fi], [sitescriptdir=${datadir}/${tzsh_name}/scripts])
+
+AC_SUBST(scriptdir)dnl
+AC_SUBST(sitescriptdir)dnl
+
+dnl Do you want maildir support?
+ifdef([maildir_support],[undefine([maildir_support])])dnl
+AH_TEMPLATE([MAILDIR_SUPPORT],
+[Define for Maildir support])
+AC_ARG_ENABLE(maildir-support,
+AC_HELP_STRING([--enable-maildir-support], [enable maildir support in MAIL and MAILPATH]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(MAILDIR_SUPPORT)
+fi])
+
+dnl Do you want to set a maximum function depth?
+ifdef([max_function_depth],[undefine([max_function_depth])])dnl
+AH_TEMPLATE([MAX_FUNCTION_DEPTH],
+[Define for function depth limits])
+AC_ARG_ENABLE(max-function-depth,
+AC_HELP_STRING([--enable-max-function-depth=MAX], [limit function depth to MAX, default 1000]),
+[if test x$enableval = xyes; then
+  AC_DEFINE(MAX_FUNCTION_DEPTH, 1000)
+elif test x$enableval != xno; then
+  AC_DEFINE_UNQUOTED(MAX_FUNCTION_DEPTH, $enableval)
+fi],
+[AC_DEFINE(MAX_FUNCTION_DEPTH, 1000)]
+)
+
+dnl Do you want to look for pcre support?
+AC_ARG_ENABLE(pcre,
+AC_HELP_STRING([--enable-pcre],
+[enable the search for the pcre library (may create run-time library dependencies)]))
+
+dnl Do you want to look for capability support?
+AC_ARG_ENABLE(cap,
+AC_HELP_STRING([--enable-cap],
+[enable the search for POSIX capabilities (may require additional headers to be added by hand)]))
+
+dnl ------------------
+dnl CHECK THE COMPILER
+dnl ------------------
+dnl We want these before the checks, so the checks can modify their values.
+test -z "${CFLAGS+set}"  && CFLAGS=  auto_cflags=1
+test -z "${LDFLAGS+set}" && LDFLAGS= auto_ldflags=1
+
+AC_PROG_CC
+
+dnl Check for large file support.
+dnl This needs to be done early to get the stuff into the flags.
+if test x$lfs != xno; then
+dnl Gross hack for ReliantUNIX - GCC does not understand getconf options
+dnl For now just disable LFS in this case
+dnl Any takers?
+  if test "$host" = mips-sni-sysv4 && test -n "$GCC"; then
+    : 
+  else
+    zsh_LARGE_FILE_SUPPORT
+  fi
+fi
+
+dnl if the user hasn't specified CFLAGS, then
+dnl   if compiler is gcc, then use -O2 and some warning flags
+dnl   else use -O
+if test -n "$auto_cflags" && test ."$ansi2knr" != .yes; then
+  if test "${enable_zsh_debug}" = yes; then
+    if test -n "$GCC"; then
+      CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -ggdb"
+    else
+      CFLAGS="$CFLAGS -g"
+    fi
+  else
+    if test -n "$GCC"; then
+      CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -O2"
+    else
+      CFLAGS="$CFLAGS -O"
+    fi
+  fi
+fi
+if test -n "$auto_ldflags"; then
+  case "${enable_zsh_debug}$host_os" in
+    yesaix*|yeshpux*|yesnetbsd*|yesopenbsd*) ;;  # "ld -g" is not valid on these systems
+    darwin*) LDFLAGS=-Wl,-x ;;
+    yes*)    LDFLAGS=-g ;;
+    *)       LDFLAGS=-s ;;
+  esac
+fi
+
+dnl ----------
+dnl SCO KLUDGE
+dnl ----------
+dnl Sco doesn't define any useful compiler symbol,
+dnl so we will check for sco and define __sco if
+dnl found.
+case "$host_os" in
+  sco*) CFLAGS="-D__sco $CFLAGS" ;;
+esac
+
+sed=':1
+     s/ -s / /g
+     t1
+     s/^ *//
+     s/ *$//'
+
+case " $LDFLAGS " in
+  *" -s "*) strip_exeldflags=true strip_libldflags=true
+    LDFLAGS=`echo " $LDFLAGS " | sed "$sed"` ;;
+  *) strip_exeldflags=false strip_libldflags=false ;;
+esac
+
+case " ${EXELDFLAGS+$EXELDFLAGS }" in
+  " ") ;;
+  *" -s "*) strip_exeldflags=true
+    EXELDFLAGS=`echo " $EXELDFLAGS " | sed "$sed"` ;;
+  *) strip_exeldflags=false ;;
+esac
+
+case " ${LIBLDFLAGS+$LIBLDFLAGS }" in
+  " ") ;;
+  *" -s "*) strip_libldflags=true
+    LIBLDFLAGS=`echo " $LIBLDFLAGS " | sed "$sed"` ;;
+  *) strip_libldflags=false ;;
+esac
+
+AC_SUBST(CFLAGS)dnl
+AC_SUBST(LDFLAGS)dnl
+AC_SUBST(EXELDFLAGS)dnl
+AC_SUBST(LIBLDFLAGS)dnl
+
+AC_PROG_CPP                 dnl Figure out how to run C preprocessor.
+AC_PROG_GCC_TRADITIONAL     dnl Do we need -traditional flag for gcc.
+AC_C_CONST                  dnl Does compiler support `const'.
+
+dnl Default preprocessing on Mac OS X produces warnings
+case "$host_os" in
+  darwin*) CPP="$CPP -traditional-cpp" ;;
+esac
+
+fp_PROG_CC_STDC
+AC_MSG_CHECKING([whether to use prototypes])
+if test ."$ansi2knr" = .yes || test ."$ansi2knr" = .no; then
+  msg="(overridden) "
+else
+  msg=
+  if test ."$fp_cv_prog_cc_stdc" = .no; then
+    ansi2knr=yes
+  else
+    ansi2knr=no
+  fi
+fi
+AH_TEMPLATE([PROTOTYPES],
+[Define to 1 if ANSI function prototypes are usable.])
+if test "$ansi2knr" = yes; then
+  AC_MSG_RESULT(${msg}no)
+  U=_
+else
+  AC_MSG_RESULT(${msg}yes)
+  AC_DEFINE(PROTOTYPES)
+  U=
+fi
+AC_SUBST(U)
+
+AC_FUNC_ALLOCA              dnl Check how to get `alloca'.
+
+dnl If the compiler supports union initialisation
+AC_CACHE_CHECK(if the compiler supports union initialisation,
+zsh_cv_c_have_union_init,
+[AC_TRY_COMPILE([union{void *p;long l;}u={0};], [u.l=1;],
+  zsh_cv_c_have_union_init=yes,
+  zsh_cv_c_have_union_init=no)])
+AH_TEMPLATE([HAVE_UNION_INIT],
+[Define to 1 if the compiler can initialise a union.])
+if test x$zsh_cv_c_have_union_init = xyes; then
+  AC_DEFINE(HAVE_UNION_INIT)
+fi
+
+dnl  Checking if compiler correctly cast signed to unsigned.
+AC_CACHE_CHECK(if signed to unsigned casting is broken,
+zsh_cv_c_broken_signed_to_unsigned_casting,
+[AC_TRY_RUN([main(){return((int)(unsigned char)((char) -1) == 255);}],
+  zsh_cv_c_broken_signed_to_unsigned_casting=yes,
+  zsh_cv_c_broken_signed_to_unsigned_casting=no,
+  zsh_cv_c_broken_signed_to_unsigned_casting=no)])
+AH_TEMPLATE([BROKEN_SIGNED_TO_UNSIGNED_CASTING],
+[Define to 1 if compiler incorrectly cast signed to unsigned.])
+if test x$zsh_cv_c_broken_signed_to_unsigned_casting = xyes; then
+  AC_DEFINE(BROKEN_SIGNED_TO_UNSIGNED_CASTING)
+fi
+
+dnl Checking if the compiler supports variable-length arrays
+AC_CACHE_CHECK(if the compiler supports variable-length arrays,
+zsh_cv_c_variable_length_arrays,
+[AC_TRY_COMPILE([int foo(), n;], [int i[foo()], a[n+1];],
+  zsh_cv_c_variable_length_arrays=yes,
+  zsh_cv_c_variable_length_arrays=no)])
+AH_TEMPLATE([HAVE_VARIABLE_LENGTH_ARRAYS],
+[Define to 1 if compiler supports variable-length arrays])
+if test x$zsh_cv_c_variable_length_arrays = xyes; then
+  AC_DEFINE(HAVE_VARIABLE_LENGTH_ARRAYS)
+fi
+
+dnl ------------------
+dnl CHECK FOR PROGRAMS
+dnl ------------------
+AC_PROG_MAKE_SET            dnl Does make define $MAKE
+AC_PROG_INSTALL             dnl Check for BSD compatible `install'
+AC_PROG_AWK                 dnl Check for mawk,gawk,nawk, then awk.
+AC_PROG_LN                  dnl Check for working ln, for "make install"
+AC_PROG_EGREP               dnl sets $EGREP to grep -E or egrep
+AC_CHECK_PROGS([YODL], [yodl], [: yodl])
+AC_CHECK_PROGS([PDFETEX], [pdfetex], [: pdfetex])
+AC_CHECK_PROGS([TEXI2PDF], [texi2pdf], [])
+AC_CHECK_PROGS([ANSI2KNR], [ansi2knr], [: ansi2knr])
+
+if test x"$ansi2knr" = xyes && test x"$ANSI2KNR" = x": ansi2knr"; then
+    echo "----------"
+    echo "configure fatal error:"
+    echo "ansi2knr was specified (--enable-ansi2knr) but the program could not be found."
+    echo "Either remove the configure option if it is not required or build the ansi2knr"
+    echo "program before reconfiguring Zsh.  The source code for ansi2knr is also"
+    echo "available in the GPL directory on Zsh distribution sites."
+    exit 1
+fi
+
+dnl ------------------
+dnl CHECK HEADER FILES
+dnl ------------------
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_TIME
+AC_HEADER_STAT
+AC_HEADER_SYS_WAIT
+
+oldcflags="$CFLAGS"
+if test x$enable_pcre = xyes; then
+AC_CHECK_PROG([PCRECONF], pcre-config, pcre-config)
+dnl Typically (meaning on this single RedHat 9 box in front of me)
+dnl pcre-config --cflags produces a -I output which needs to go into
+dnl CPPFLAGS else configure's preprocessor tests don't pick it up,
+dnl producing a warning.
+if test "x$ac_cv_prog_PCRECONF" = xpcre-config; then
+  CPPFLAGS="$CPPFLAGS `pcre-config --cflags`"
+fi
+fi
+
+AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \
+		 termios.h sys/param.h sys/filio.h string.h memory.h \
+		 limits.h fcntl.h libc.h sys/utsname.h sys/resource.h \
+		 locale.h errno.h stdio.h stdarg.h varargs.h stdlib.h \
+		 unistd.h sys/capability.h \
+		 utmp.h utmpx.h sys/types.h pwd.h grp.h poll.h sys/mman.h \
+		 netinet/in_systm.h pcre.h langinfo.h wchar.h stddef.h \
+		 sys/stropts.h iconv.h ncurses.h ncursesw/ncurses.h \
+		 ncurses/ncurses.h)
+if test x$dynamic = xyes; then
+  AC_CHECK_HEADERS(dlfcn.h)
+  AC_CHECK_HEADERS(dl.h)
+fi
+
+dnl Some SCO systems cannot include both sys/time.h and sys/select.h
+AH_TEMPLATE([TIME_H_SELECT_H_CONFLICTS],
+[Define if sys/time.h and sys/select.h cannot be both included.])
+if test x$ac_cv_header_sys_time_h = xyes && test x$ac_cv_header_sys_select_h = xyes; then
+  AC_CACHE_CHECK(for conflicts in sys/time.h and sys/select.h,
+  zsh_cv_header_time_h_select_h_conflicts,
+  [AC_TRY_COMPILE([#include <sys/time.h>
+#include <sys/select.h>], [int i;],
+  zsh_cv_header_time_h_select_h_conflicts=no,
+  zsh_cv_header_time_h_select_h_conflicts=yes)])
+  if test x$zsh_cv_header_time_h_select_h_conflicts = xyes; then
+    AC_DEFINE(TIME_H_SELECT_H_CONFLICTS)
+  fi
+fi
+
+AH_TEMPLATE([GWINSZ_IN_SYS_IOCTL],
+[Define if TIOCGWINSZ is defined in sys/ioctl.h but not in termios.h.])
+if test x$ac_cv_header_termios_h = xyes; then
+  AC_CACHE_CHECK(TIOCGWINSZ in termios.h,
+  zsh_cv_header_termios_h_tiocgwinsz,
+  [AC_TRY_LINK([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <termios.h>],
+  [int x = TIOCGWINSZ;],
+  zsh_cv_header_termios_h_tiocgwinsz=yes,
+  zsh_cv_header_termios_h_tiocgwinsz=no)])
+else
+  zsh_cv_header_termios_h_tiocgwinsz=no
+fi
+if test x$zsh_cv_header_termios_h_tiocgwinsz = xno; then
+  AC_CACHE_CHECK(TIOCGWINSZ in sys/ioctl.h,
+  zsh_cv_header_sys_ioctl_h_tiocgwinsz,
+  [AC_TRY_LINK([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <sys/ioctl.h>],
+  [int x = TIOCGWINSZ;],
+  zsh_cv_header_sys_ioctl_h_tiocgwinsz=yes,
+  zsh_cv_header_sys_ioctl_h_tiocgwinsz=no)])
+  if test x$zsh_cv_header_sys_ioctl_h_tiocgwinsz = xyes; then
+    AC_DEFINE(GWINSZ_IN_SYS_IOCTL)
+  fi
+fi
+ 
+AH_TEMPLATE([WINSIZE_IN_PTEM],
+[Define if your should include sys/stream.h and sys/ptem.h.])
+AC_CACHE_CHECK(for streams headers including struct winsize,
+ac_cv_winsize_in_ptem,
+[AC_TRY_COMPILE([#include <sys/stream.h>
+#include <sys/ptem.h>],
+[struct winsize wsz],
+ac_cv_winsize_in_ptem=yes,
+ac_cv_winsize_in_ptem=no)])
+if test x$ac_cv_winsize_in_ptem = xyes; then
+  AC_DEFINE(WINSIZE_IN_PTEM)
+fi
+
+dnl -------------------
+dnl CHECK FOR LIBRARIES
+dnl -------------------
+
+dnl On some systems, modules need to be linked against libc explicitly,
+dnl in case they require objects that exist only in the static version
+dnl and might not be compiled into the zsh executable.
+dnl On ReliantUNIX -lc better be the last library, else funny things
+dnl may happen.
+AC_CHECK_LIB(c, printf, [LIBS="$LIBS -lc"])
+
+AC_CHECK_LIB(m, pow)
+
+dnl Various features of ncurses depend on having the right header
+dnl (the system's own curses.h may well not be good enough).
+dnl So don't search for ncurses unless we found the header.
+if test x$ac_cv_header_ncurses_h = xyes || test x$ac_cv_header_ncurses_ncurses_h = xyes || test x$ac_cv_header_ncursesw_ncurses_h = xyes; then
+  ncursesw_test=ncursesw
+  ncurses_test=ncurses
+else
+  ncursesw_test=
+  ncurses_test=
+fi
+
+dnl Prefer BSD termcap library to SysV curses library, except on certain
+dnl SYSV-derived systems.  However, if we find terminfo and termcap
+dnl stuff in the same library we will use that; typically this
+dnl is ncurses or curses.
+dnl On HPUX, Hcurses is reported to work better than curses.
+dnl Prefer ncurses to curses on all systems.  tinfo isn't very common now.
+AC_ARG_WITH(term-lib,
+AC_HELP_STRING([--with-term-lib=LIBS], [search space-separated LIBS for terminal handling]),
+[if test "x$withval" != xno && test "x$withval" != x ; then
+  termcap_curses_order="$withval"
+  AC_SEARCH_LIBS(tigetstr, [$termcap_curses_order])
+else
+  termcap_curses_order="$ncursesw_test tinfo termcap $ncurses_test curses"
+fi],
+[case "$host_os" in
+  hpux10.*|hpux11.*|solaris*)
+   termcap_curses_order="Hcurses $ncursesw_test $ncurses_test curses termcap" ;;
+  *)
+   termcap_curses_order="$ncursesw_test tinfo termcap $ncurses_test curses" ;;
+esac])dnl
+
+AH_TEMPLATE([ZSH_CURSES_NEEDS_XOPEN],
+[Define if the curses libraries need _XOPEN_SOURCE_EXTENDED defined])
+AC_CACHE_CHECK(if the curses library needs _XOPEN_SOURCE_EXTENDED,
+zsh_cv_curses_needs_xopen,
+[case "$host_os" in
+  *openbsd*)
+  zsh_cv_curses_needs_xopen=no
+  ;;
+  *)
+  zsh_cv_curses_needs_xopen=yes
+  ;;
+esac])
+if test x$zsh_cv_curses_needs_xopen = xyes; then
+  AC_DEFINE(ZSH_CURSES_NEEDS_XOPEN)
+fi
+
+dnl Check for tigetflag (terminfo) before tgetent (termcap).
+dnl That's so that on systems where termcap and [n]curses are
+dnl both available and both contain termcap functions, while
+dnl only [n]curses contains terminfo functions, we only link against
+dnl [n]curses.
+AC_SEARCH_LIBS(tigetflag, [$termcap_curses_order])
+AC_SEARCH_LIBS(tgetent, [$termcap_curses_order],
+  true,
+  AC_MSG_FAILURE(["No terminal handling library was found on your system.
+This is probably a library called 'curses' or 'ncurses'.  You may
+need to install a package called 'curses-devel' or 'ncurses-devel' on your
+system."], 255))
+AC_CHECK_HEADERS(curses.h, [],
+[AC_CACHE_CHECK(for Solaris 8 curses.h mistake, ac_cv_header_curses_solaris,
+AC_TRY_COMPILE([#include <curses.h>], [],
+[ac_cv_header_curses_h=yes
+ac_cv_header_curses_solaris=yes],
+ac_cv_header_curses_h=no
+ac_cv_header_curses_solaris=no))
+if test x$ac_cv_header_curses_solaris = xyes; then
+AC_DEFINE(HAVE_CURSES_H)
+fi])
+
+dnl If our terminal library is not ncurses, don't try including
+dnl any ncurses headers.
+AC_CACHE_CHECK(if we need to ignore ncurses, zsh_cv_ignore_ncurses,
+[case $LIBS in
+  *-lncurses*)
+  zsh_cv_ignore_ncurses=no
+  ;;
+  *)
+  zsh_cv_ignore_ncurses=yes
+  ;;
+esac])
+
+AC_SEARCH_LIBS(getpwnam, nsl)
+
+dnl I am told that told that unicos reqire these for nis_list
+if test `echo $host_os | sed 's/^\(unicos\).*/\1/'` = unicos; then
+  LIBS="-lcraylm -lkrb -lnisdb -lnsl -lrpcsvc $LIBS"
+fi
+
+if test "x$dynamic" = xyes; then
+  AC_CHECK_LIB(dl, dlopen)
+fi
+
+if test x$enable_cap = xyes; then
+  AC_CHECK_LIB(cap, cap_get_proc)
+fi
+
+AC_CHECK_LIB(socket, socket)
+
+dnl ---------------
+dnl CHECK FOR ICONV
+dnl ---------------
+
+dnl Find iconv. It may be in libiconv and may be iconv() or libiconv()
+if test "x$ac_cv_header_iconv_h" = "xyes"; then
+  AC_CHECK_FUNC(iconv, ac_found_iconv=yes, ac_found_iconv=no)
+  if test "x$ac_found_iconv" = "xno"; then
+    AC_CHECK_LIB(iconv, iconv, ac_found_iconv=yes)
+    if test "x$ac_found_iconv" = "xno"; then
+      AC_CHECK_LIB(iconv, libiconv, ac_found_iconv=yes)
+    fi
+    if test "x$ac_found_iconv" != "xno"; then
+      LIBS="-liconv $LIBS"
+    fi
+  else
+    dnl Handle case where there is a native iconv but iconv.h is from libiconv
+    AC_CHECK_DECL(_libiconv_version,
+      [ AC_CHECK_LIB(iconv, libiconv, LIBS="-liconv $LIBS") ],,
+      [ #include <iconv.h> ])
+  fi
+fi
+AH_TEMPLATE([ICONV_FROM_LIBICONV],
+[Define to 1 if iconv() is linked from libiconv])
+if test "x$ac_found_iconv" = xyes; then
+  AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
+  AC_TRY_LINK([#include <iconv.h>],
+    [int myversion = _libiconv_version],
+    AC_DEFINE(ICONV_FROM_LIBICONV), )
+fi
+
+dnl Check if iconv uses const in prototype declaration
+if test "x$ac_found_iconv" = "xyes"; then
+  AC_CACHE_CHECK(for iconv declaration, ac_cv_iconv_const,
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>
+        #include <iconv.h>]],
+        [[#ifdef __cplusplus
+          "C"
+          #endif
+          #if defined(__STDC__) || defined(__cplusplus)
+          size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+          #else
+          size_t iconv();
+          #endif]])],
+      [ac_cv_iconv_const=],
+      [ac_cv_iconv_const=const])])
+  AC_DEFINE_UNQUOTED([ICONV_CONST], $ac_cv_iconv_const,
+    [Define as const if the declaration of iconv() needs const.])
+fi
+
+if test x$enable_pcre = xyes; then
+dnl pcre-config should probably be employed here
+dnl AC_SEARCH_LIBS(pcre_compile, pcre)
+  LIBS="`pcre-config --libs` $LIBS"
+fi
+
+dnl ---------------------
+dnl CHECK TERMCAP LIBRARY
+dnl ---------------------
+dnl Checks for external variable ospeed in the termcap library.
+AC_CACHE_CHECK(if an include file defines ospeed,
+zsh_cv_decl_ospeed_include_defines,
+[AC_TRY_LINK(
+[#include <sys/types.h>
+#if HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#if HAVE_TERMCAP_H
+#include <termcap.h>
+#endif], [ospeed = 0;],
+zsh_cv_decl_ospeed_include_defines=yes,
+zsh_cv_decl_ospeed_include_defines=no)])
+
+if test x$zsh_cv_decl_ospeed_include_defines = xno; then
+  AC_CACHE_CHECK(if you must define ospeed,
+  zsh_cv_decl_ospeed_must_define,
+  [AC_TRY_LINK( ,[extern short ospeed; ospeed = 0;],
+  zsh_cv_decl_ospeed_must_define=yes,
+  zsh_cv_decl_ospeed_must_define=no)])
+fi
+
+AH_TEMPLATE([HAVE_OSPEED],
+[Define to 1 if your termcap library has the ospeed variable])
+AH_TEMPLATE([MUST_DEFINE_OSPEED],
+[Define to 1 if you have ospeed, but it is not defined in termcap.h])
+if test x$zsh_cv_decl_ospeed_include_defines = xyes; then
+  AC_DEFINE(HAVE_OSPEED)
+elif test x$zsh_cv_decl_ospeed_must_define = xyes; then
+  AC_DEFINE(HAVE_OSPEED)
+  AC_DEFINE(MUST_DEFINE_OSPEED)
+fi
+
+dnl --------------
+dnl CHECK TYPEDEFS
+dnl --------------
+
+AC_TYPE_SIGNAL
+AC_TYPE_PID_T
+AC_TYPE_OFF_T
+AC_CHECK_TYPE(ino_t, unsigned long)
+AC_TYPE_MODE_T
+AC_TYPE_UID_T
+AC_TYPE_SIZE_T
+
+dnl ------------------------------------------------
+dnl Check size of long and try to find a 64-bit type
+dnl ------------------------------------------------
+dnl AC_CHECK_SIZEOF is no good, because we need the result here,
+dnl and that doesn't seem to define a shell parameter.
+AC_CACHE_CHECK(if long is 64 bits, zsh_cv_long_is_64_bit,
+[AC_TRY_RUN([int main() { return sizeof(long) < 8; }],
+zsh_cv_long_is_64_bit=yes,
+zsh_cv_long_is_64_bit=no,
+zsh_cv_long_is_64_bit=no)])
+
+AH_TEMPLATE([ino_t],
+[Define to `unsigned long' if <sys/types.h> doesn't define.])
+AH_TEMPLATE([LONG_IS_64_BIT],
+[Definitions used when a long is less than eight byte, to try to
+ provide some support for eight byte operations.
+
+ Note that ZSH_64_BIT_TYPE, OFF_T_IS_64_BIT, INO_T_IS_64_BIT do *not* get
+ defined if long is already 64 bits, since in that case no special handling
+ is required.
+
+ Define to 1 if long is 64 bits])
+AH_TEMPLATE([ZSH_64_BIT_TYPE],
+[Define to a 64 bit integer type if there is one, but long is shorter.])
+AH_TEMPLATE([ZSH_64_BIT_UTYPE],
+[Define to an unsigned variant of ZSH_64_BIT_TYPE if that is defined.])
+AH_TEMPLATE([OFF_T_IS_64_BIT],
+[Define to 1 if off_t is 64 bit (for large file support)])
+AH_TEMPLATE([INO_T_IS_64_BIT],
+[Define to 1 if ino_t is 64 bit (for large file support).])
+if test x$zsh_cv_long_is_64_bit = xyes; then
+  AC_DEFINE(LONG_IS_64_BIT)
+else
+  AC_CACHE_CHECK(if off_t is 64 bit, zsh_cv_off_t_is_64_bit,
+  [AC_TRY_RUN([
+#include <sys/types.h>
+
+main() { return sizeof(off_t) < 8; }
+],
+  zsh_cv_off_t_is_64_bit=yes,
+  zsh_cv_off_t_is_64_bit=no,
+  zsh_cv_off_t_is_64_bit=no)])
+  if test x$zsh_cv_off_t_is_64_bit = xyes; then
+    AC_DEFINE(OFF_T_IS_64_BIT)
+  fi
+
+  AC_CACHE_CHECK(if ino_t is 64 bit, zsh_cv_ino_t_is_64_bit,
+  [AC_TRY_RUN([
+#include <sys/types.h>
+
+main() { return sizeof(ino_t) < 8; }
+],
+  zsh_cv_ino_t_is_64_bit=yes,
+  zsh_cv_ino_t_is_64_bit=no,
+  zsh_cv_ino_t_is_64_bit=no)])
+  if test x$zsh_cv_ino_t_is_64_bit = xyes; then
+    AC_DEFINE(INO_T_IS_64_BIT)
+  fi
+
+  if test x$lfs != xno -o x$zsh_cv_off_t_is_64_bit = xyes \
+  -o $zsh_cv_ino_t_is_64_bit = yes; then
+    AC_CACHE_CHECK(if compiler has a 64 bit type, zsh_cv_64_bit_type,
+    [if test x$lfs != xyes && test x$lfs != xno; then
+      zsh_64_BIT_TYPE(${lfs}, zsh_cv_64_bit_type, force)
+     else
+       zsh_64_BIT_TYPE(long long, zsh_cv_64_bit_type)
+       if test "$zsh_cv_64_bit_type" = no; then
+         zsh_64_BIT_TYPE(quad_t, zsh_cv_64_bit_type)
+       fi
+       if test "$zsh_cv_64_bit_type" = no; then
+         zsh_64_BIT_TYPE(__int64_t, zsh_cv_64_bit_type)
+       fi
+       dnl As a last resort, if we know off_t has 64 bits, use that as
+       dnl the 64-bit integer type.  I don't dare try ino_t since there's
+       dnl probably nothing to stop that being unsigned.
+       if test "$zsh_cv_64_bit_type" = no &&
+          test "$zsh_cv_off_t_is_64_bit" = yes; then
+         zsh_64_BIT_TYPE(off_t, zsh_cv_64_bit_type)
+       fi
+     fi])
+    if test "$zsh_cv_64_bit_type" != no; then
+      AC_DEFINE_UNQUOTED(ZSH_64_BIT_TYPE, $zsh_cv_64_bit_type)
+
+      dnl Handle cases where unsigned type cannot be simply
+      dnl `unsigned ZSH_64_BIT_TYPE'.  More tests may be required.
+      AC_CACHE_CHECK(for a corresponding unsigned 64 bit type,
+      zsh_cv_64_bit_utype,
+      [zsh_64_BIT_TYPE(unsigned $zsh_cv_64_bit_type, zsh_cv_64_bit_utype,
+       force)
+       if test "$zsh_cv_64_bit_utype" = no; then
+         zsh_64_BIT_TYPE(__uint64_t, zsh_cv_64_bit_utype)
+       fi])
+      if test "$zsh_cv_64_bit_utype" != no; then
+        AC_DEFINE_UNQUOTED(ZSH_64_BIT_UTYPE, $zsh_cv_64_bit_utype)
+      fi
+    fi
+  fi
+fi
+
+dnl Check for sigset_t.  Currently I'm looking in
+dnl <sys/types.h> and <signal.h>.  Others might need
+dnl to be added.
+AC_CACHE_CHECK(for sigset_t, zsh_cv_type_sigset_t,
+[AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <signal.h>], [sigset_t tempsigset;],
+  zsh_cv_type_sigset_t=yes, zsh_cv_type_sigset_t=no)])
+AH_TEMPLATE([sigset_t],
+[Define to `unsigned int' if <sys/types.h> or <signal.h> doesn't define])
+if test x$zsh_cv_type_sigset_t = xno; then
+  AC_DEFINE(sigset_t, unsigned int)
+fi
+
+dnl check structures for high resolution timestamps
+AC_CHECK_MEMBERS([struct stat.st_atim.tv_nsec,
+                  struct stat.st_atimespec.tv_nsec,
+                  struct stat.st_atimensec,
+                  struct stat.st_mtim.tv_nsec,
+                  struct stat.st_mtimespec.tv_nsec,
+                  struct stat.st_mtimensec,
+                  struct stat.st_ctim.tv_nsec,
+                  struct stat.st_ctimespec.tv_nsec,
+                  struct stat.st_ctimensec])
+
+dnl Check for struct timezone since some old SCO versions do not define it
+zsh_TYPE_EXISTS([
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+], struct timezone)
+
+dnl Check for utmp structures, for watch
+zsh_TYPE_EXISTS([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UTMP_H
+# include <utmp.h>
+#endif
+], struct utmp)
+zsh_TYPE_EXISTS([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h>
+#endif
+], struct utmpx)
+
+dnl Check contents of utmp structures
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UTMP_H
+# include <utmp.h>
+#endif
+], struct utmp, ut_host)
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h>
+#endif
+], struct utmpx, ut_host)
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h>
+#endif
+], struct utmpx, ut_xtime)
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h>
+#endif
+], struct utmpx, ut_tv)
+
+dnl Check for inode numbers in directory entry structures
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+], struct dirent, d_ino)
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+], struct dirent, d_stat)
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+#endif
+#ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+#endif
+#ifdef HAVE_NDIR_H
+# include <ndir.h>
+#endif
+], struct direct, d_ino)
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+#endif
+#ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+#endif
+#ifdef HAVE_NDIR_H
+# include <ndir.h>
+#endif
+], struct direct, d_stat)
+
+dnl Check IPv6 socket address structure type
+zsh_STRUCT_MEMBER([
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <netinet/in.h>
+], struct sockaddr_in6, sin6_scope_id)
+
+dnl Check for h_errno external variable
+AH_TEMPLATE([USE_LOCAL_H_ERRNO],
+[Define to 1 if h_errno is not defined by the system.])
+AC_CACHE_CHECK(if we need our own h_errno,
+  zsh_cv_decl_h_errno_use_local,
+  [AC_TRY_LINK( ,[extern int h_errno; h_errno = 0;],
+  zsh_cv_decl_h_errno_use_local=no,
+  zsh_cv_decl_h_errno_use_local=yes)])
+
+if test x$zsh_cv_decl_h_errno_use_local = xyes; then
+  AC_DEFINE(USE_LOCAL_H_ERRNO)
+fi
+
+dnl ---------------
+dnl CHECK FUNCTIONS
+dnl ---------------
+
+dnl need to integrate this function
+dnl AC_FUNC_STRFTIME
+
+AC_CHECK_FUNCS(strftime strptime mktime timelocal \
+	       difftime gettimeofday \
+	       select poll \
+	       readlink faccessx fchdir ftruncate \
+	       fstat lstat lchown fchown fchmod \
+	       fseeko ftello \
+	       mkfifo _mktemp mkstemp \
+	       waitpid wait3 \
+	       sigaction sigblock sighold sigrelse sigsetmask sigprocmask \
+	       killpg setpgid setpgrp tcsetpgrp tcgetattr nice \
+	       gethostname gethostbyname2 getipnodebyname \
+	       inet_aton inet_pton inet_ntop \
+	       getlogin getpwent getpwnam getpwuid getgrgid getgrnam \
+	       initgroups nis_list \
+	       getuid setuid seteuid setreuid setresuid setsid \
+	       getgid setgid setegid setregid setresgid \
+	       geteuid getegid \
+	       memcpy memmove strstr strerror strtoul \
+	       getrlimit getrusage \
+	       setlocale \
+	       uname \
+	       signgam \
+	       putenv getenv setenv unsetenv xw\
+	       brk sbrk \
+	       pathconf sysconf \
+	       tgetent tigetflag tigetnum tigetstr setupterm initscr \
+	       getcchar setcchar waddwstr wget_wch win_wch use_default_colors \
+	       pcre_compile pcre_study pcre_exec \
+	       nl_langinfo \
+	       erand48 open_memstream \
+	       wctomb iconv \
+	       grantpt unlockpt ptsname \
+	       htons ntohs \
+	       regcomp regexec regerror regfree)
+AC_FUNC_STRCOLL
+
+if test x$enable_cap = xyes; then
+  AC_CHECK_FUNCS(cap_get_proc)
+fi
+
+dnl  Check if tgetent accepts NULL (and will allocate its own termcap buffer)
+dnl  Some termcaps reportedly accept a zero buffer, but then dump core
+dnl  in tgetstr().
+dnl  Under Cygwin test program crashes but exit code is still 0. So,
+dnl  we test for a file that porgram should create
+AH_TEMPLATE([TGETENT_ACCEPTS_NULL],
+[Define to 1 if tgetent() accepts NULL as a buffer.])
+AC_CACHE_CHECK(if tgetent accepts NULL,
+zsh_cv_func_tgetent_accepts_null,
+[AC_TRY_RUN([
+main()
+{
+    char buf[4096];
+    int r1 = tgetent(buf, "vt100");
+    int r2 = tgetent((char*)0,"vt100");
+    if (r1 >= 0 && r1 == r2) {
+        char tbuf[1024], *u;
+        u = tbuf;
+    	tgetstr("cl", &u);
+	creat("conftest.tgetent", 0640);
+    }
+    exit((r1 != r2) || r2 == -1);
+}
+],
+  if test -f conftest.tgetent; then
+    zsh_cv_func_tgetent_accepts_null=yes
+  else
+    zsh_cv_func_tgetent_accepts_null=no
+  fi,
+  zsh_cv_func_tgetent_accepts_null=no,
+  zsh_cv_func_tgetent_accepts_null=no)])
+if test x$zsh_cv_func_tgetent_accepts_null = xyes; then
+  AC_DEFINE(TGETENT_ACCEPTS_NULL)
+fi
+AC_CACHE_CHECK(if tgetent returns 0 on success,
+zsh_cv_func_tgetent_zero_success,
+[AC_TRY_RUN([
+main()
+{
+    char buf[4096];
+    int r1 = tgetent(buf, "!@#$%^&*");
+    int r2 = tgetent(buf, "vt100");
+    if (r1 < 0 && r2 == 0) {
+        char tbuf[1024], *u;
+        u = tbuf;
+    	tgetstr("cl", &u);
+	creat("conftest.tgetent0", 0640);
+    }
+    exit(r1 == r2);
+}
+],
+  if test -f conftest.tgetent0; then
+    zsh_cv_func_tgetent_zero_success=yes
+  else
+    zsh_cv_func_tgetent_zero_success=no
+  fi,
+  zsh_cv_func_tgetent_zero_success=no,
+  zsh_cv_func_tgetent_zero_success=no)])
+AH_TEMPLATE([TGETENT_SUCCESS],
+[Define to what tgetent() returns on success (0 on HP-UX X/Open curses).])
+if test x$zsh_cv_func_tgetent_zero_success = xyes; then
+  AC_DEFINE(TGETENT_SUCCESS, 0)
+else
+  AC_DEFINE(TGETENT_SUCCESS, 1)
+fi
+
+AC_FUNC_MMAP
+if test x$ac_cv_func_mmap_fixed_mapped = xyes; then
+  AC_CHECK_FUNCS(munmap msync)
+fi
+
+if test x$ac_cv_func_setpgrp = xyes; then
+  AC_FUNC_GETPGRP
+else
+  dnl If there is no setpgrp, the test for getpgrp(void) will fail
+  dnl because the program will not compile.  However, in that case
+  dnl we can be reasonably confident we are not dealing with a
+  dnl Berkeleyesque system, so assume getpgrp does take void.
+  ac_cv_func_getpgrp_void=yes
+  AC_DEFINE(GETPGRP_VOID)
+fi
+
+if test x$dynamic = xyes; then
+  AC_CHECK_FUNCS(dlopen dlerror dlsym dlclose load loadquery loadbind unload \
+		shl_load shl_unload shl_findsym)
+fi
+
+
+dnl -------------
+dnl CHECK SIGNALS
+dnl -------------
+dnl What style of signal do you have (POSIX, BSD, or SYSV)?
+AH_TEMPLATE([POSIX_SIGNALS],
+[Define to 1 if you use POSIX style signal handling.])
+AH_TEMPLATE([BSD_SIGNALS],
+[Define to 1 if you use BSD style signal handling (and can block signals).])
+AH_TEMPLATE([SYSV_SIGNALS],
+[Define to 1 if you use SYS style signal handling (and can block signals).])
+AH_TEMPLATE([NO_SIGNAL_BLOCKING],
+[Define to 1 if you have no signal blocking at all (bummer).])
+AC_MSG_CHECKING(what style of signals to use)
+if test x$ac_cv_func_sigaction = xyes && test x$ac_cv_func_sigprocmask = xyes; then
+  signals_style=POSIX_SIGNALS
+  AC_DEFINE(POSIX_SIGNALS)
+elif test x$ac_cv_func_sigblock = xyes && test x$ac_cv_func_sigsetmask = xyes; then
+  signals_style=BSD_SIGNALS
+  AC_DEFINE(BSD_SIGNALS)
+elif test x$ac_cv_func_sighold = xyes && test x$ac_cv_func_sigrelse = xyes; then
+  signals_style=SYSV_SIGNALS
+  AC_DEFINE(SYSV_SIGNALS)
+else
+  signals_style=NO_SIGNAL_BLOCKING
+  AC_DEFINE(NO_SIGNAL_BLOCKING)
+fi
+AC_DEFINE_UNQUOTED($signals_style)
+AC_MSG_RESULT($signals_style)
+
+dnl Where is <signal.h> located?  Needed as input for signals.awk
+AC_CACHE_CHECK(where signal.h is located, zsh_cv_path_signal_h,
+[dnl Look at the output from the preprocessor.
+dnl We should get lines of the form `# 1 "/usr/include/signal.h"'
+dnl The following assumes the real definitions are in a file which
+dnl contains the name `sig'; we could relax this if necessary,
+dnl but then you can get a rather long list of files to test.
+dnl The backslash substitution is to persuade cygwin to cough up
+dnl slashes rather than doubled backslashes in the path.
+echo "#include <signal.h>" > nametmp.c
+sigfile_list="`$CPP nametmp.c |
+sed -n -e 's/^#line[ 	].*\"\(.*\)\"/\1/p' \
+       -e 's/^#[ 	].*\"\(.*\)\"/\1/p' |
+sed 's/\\\\\\\\/\//g' |
+$AWK '{ if ($1 ~ /sig/) files[[$1]] = $1 }
+  END { for (var in files) print var }'`"
+rm -f nametmp.c
+if test -z "$sigfile_list"; then
+  dnl In case we don't get the stuff from the preprocesor, use the old
+  dnl list of standard places.
+  sigfile_list="/usr/include/sys/iso/signal_iso.h
+/usr/include/bsd/sys/signal.h
+/usr/include/signum.h
+/usr/include/asm/signum.h
+/usr/include/asm/signal.h
+/usr/include/linux/signal.h
+/usr/include/sys/signal.h
+/usr/include/bits/signum.h
+/dev/null"
+fi
+for SIGNAL_H in $sigfile_list
+do
+  dnl Try to make sure it doesn't get confused by files that don't
+  dnl have real signal definitions in, but do #define SIG* by counting
+  dnl the number of signals.  Maybe we could even check for e.g. SIGHUP?
+  nsigs=`test -f $SIGNAL_H && \
+  grep '#[ 	]*define[ 	][ 	]*SIG[0-9A-Z]*[ 	]*[0-9][0-9]*' $SIGNAL_H | \
+  wc -l | sed 's/[ 	]//g'`
+  test "x$nsigs" != x && test "$nsigs" -ge 7 && break
+done
+if test x$SIGNAL_H = x"/dev/null"; then
+  AC_MSG_ERROR(SIGNAL MACROS NOT FOUND:  please report to developers)
+fi
+zsh_cv_path_signal_h=$SIGNAL_H
+])
+SIGNAL_H=$zsh_cv_path_signal_h
+AC_SUBST(SIGNAL_H)dnl
+
+dnl Where are error names located?  Needed as input for errnames1.awk
+AC_CACHE_CHECK(where error names are located, zsh_cv_path_errno_h,
+[dnl Look at the output from the preprocessor.
+dnl We should get lines of the form `# 1 "/usr/include/errno.h"'
+dnl The following assumes the real definitions are in a file which
+dnl contains the name `err'; we could relax this if necessary,
+dnl but then you can get a rather long list of files to test.
+dnl The backslash substitution is to persuade cygwin to cough up
+dnl slashes rather than doubled backslashes in the path.
+echo "#include <errno.h>" > nametmp.c
+errfile_list="`$CPP nametmp.c |
+sed -n -e 's/^#line[ 	].*\"\(.*\)\"/\1/p' \
+       -e 's/^#[ 	0-9].*\"\(.*\)\"/\1/p' |
+sed 's/\\\\\\\\/\//g' |
+$AWK '{ if ($1 ~ /err/) files[[$1]] = $1 }
+  END { for (var in files) print var }'`"
+rm -f nametmp.c
+for ERRNO_TRY_H in $errfile_list /dev/null
+do
+  dnl Try to make sure it doesn't get confused by files that don't
+  dnl have real error definitions in.  Count definitions to make sure.
+  dnl Definitions of error numbers have become more and more general, so
+  dnl make a list of files containing any definitions in and keep them all.
+  dnl Careful with cut and paste in the pattern: the square brackets
+  dnl must contain a space and a tab.
+  nerrs=`test -f $ERRNO_TRY_H && \
+  $EGREP '#[ 	]*define[ 	][ 	]*E[0-9A-Z]*[ 	]*(_HURD_ERRNO )?\(?[_A-Z0-9]' $ERRNO_TRY_H | \
+  wc -l | sed 's/[ 	]//g'`
+  if test "x$nerrs" != x && test "$nerrs" -ge 1
+  then
+    ERRNO_H="$ERRNO_H $ERRNO_TRY_H"
+  fi
+done
+if test x"$ERRNO_H" = x; then
+  AC_MSG_ERROR(ERROR MACROS NOT FOUND:  please report to developers)
+fi
+zsh_cv_path_errno_h="$ERRNO_H"
+])
+ERRNO_H="$zsh_cv_path_errno_h"
+AC_SUBST(ERRNO_H)dnl
+
+AC_CACHE_CHECK(location of curses header, zsh_cv_path_curses_header,
+[if test x$zsh_cv_ignore_ncurses = xyes; then
+  if test x$ac_cv_header_curses_h = xyes; then
+    zsh_cv_path_curses_header=curses.h
+  else
+    zsh_cv_path_curses_header=none
+  fi
+elif test x$ac_cv_header_ncursesw_ncurses_h = xyes; then
+  zsh_cv_path_curses_header=ncursesw/ncurses.h
+elif test x$ac_cv_header_ncurses_ncurses_h = xyes; then
+  zsh_cv_path_curses_header=ncurses/ncurses.h
+elif test x$ac_cv_header_ncurses_h = xyes; then
+  zsh_cv_path_curses_header=ncurses.h
+elif test x$ac_cv_header_curses_h = xyes; then
+  zsh_cv_path_curses_header=curses.h
+else
+  zsh_cv_path_curses_header=none
+fi])
+AH_TEMPLATE([ZSH_HAVE_CURSES_H],
+[Define to 1 if some variant of a curses header can be included])
+if test x$zsh_cv_path_curses_header != xnone; then
+  AC_DEFINE(ZSH_HAVE_CURSES_H)
+  ZSH_CURSES_H=$zsh_cv_path_curses_header
+else
+  ZSH_CURSES_H=
+fi
+AC_SUBST(ZSH_CURSES_H)
+
+dnl Where are curses key definitions located?  Need for keypad() mode.
+AC_CACHE_CHECK(where curses key definitions are located, zsh_cv_path_curses_keys_h,
+[dnl This is an identical trick to errno.h, except we use ncurses.h
+dnl if we can.
+if test x$zsh_cv_path_curses_header = xnone; then
+  echo >nametmp.c
+else
+  echo "#include <$zsh_cv_path_curses_header>" >nametmp.c
+fi
+
+curses_list="`$CPP nametmp.c |
+sed -n -e 's/^#line[ 	].*\"\(.*\)\"/\1/p' \
+       -e 's/^#[ 	0-9].*\"\(.*\)\"/\1/p' |
+sed 's/\\\\\\\\/\//g' |
+$AWK '{ if ($1 ~ /\.h/) files[[$1]] = $1 }
+  END { for (var in files) print var }'`"
+rm -f nametmp.c
+for CURSES_TRY_H in $curses_list /dev/null
+do
+  nkeys=`test -f $CURSES_TRY_H && \
+  $EGREP '#[ 	]*define[ 	][ 	]*KEY_' $CURSES_TRY_H | \
+  wc -l | sed 's/[ 	]//g'`
+  if test "x$nkeys" != x && test "$nkeys" -ge 10
+  then
+    CURSES_KEYS_H=$CURSES_TRY_H
+    break
+  fi
+done
+zsh_cv_path_curses_keys_h="$CURSES_KEYS_H"
+])
+CURSES_KEYS_H="$zsh_cv_path_curses_keys_h"
+AC_SUBST(CURSES_KEYS_H)dnl
+
+dnl See if there are variants of term.h.  For testing each one
+dnl we include the most likely variant of the curses header.
+AC_CHECK_HEADERS(ncursesw/term.h,
+true, true,
+[#include <ncursesw/ncurses.h>])
+AC_CHECK_HEADERS(ncurses/term.h,
+true, true,
+[#include <ncurses/ncurses.h>])
+AC_CHECK_HEADERS(term.h,
+true, true,
+[#include <curses.h>])
+
+dnl See if term.h is bundled along with the curses library we
+dnl are using.  If this isn't the default system curses, compilation
+dnl could barf unless we include from the right subdirectory.
+AC_CACHE_CHECK(where term.h is located, zsh_cv_path_term_header,
+[case x$zsh_cv_path_curses_header in
+  xncursesw/*)
+  if test x$ac_cv_header_ncursesw_term_h = xyes; then
+    zsh_cv_path_term_header=ncursesw/term.h
+  fi
+  ;;
+  xncurses/*)
+  if test x$ac_cv_header_ncurses_term_h = xyes; then
+    zsh_cv_path_term_header=ncurses/term.h
+  fi
+  ;;
+esac
+if test x$zsh_cv_path_term_header = x; then
+  if test x$ac_cv_header_term_h = xyes; then
+    zsh_cv_path_term_header=term.h
+  else
+    zsh_cv_path_term_header=none
+  fi
+fi])
+
+AH_TEMPLATE([ZSH_HAVE_TERM_H],
+[Define to 1 if some variant of term.h can be included])
+AH_TEMPLATE([HAVE_BOOLCODES],
+[Define if you have the termcap boolcodes symbol.])
+AH_TEMPLATE([HAVE_NUMCODES],
+[Define if you have the termcap numcodes symbol.])
+AH_TEMPLATE([HAVE_STRCODES],
+[Define if you have the termcap strcodes symbol.])
+AH_TEMPLATE([HAVE_BOOLNAMES],
+[Define if you have the terminfo boolnames symbol.])
+AH_TEMPLATE([HAVE_NUMNAMES],
+[Define if you have the terminfo numnames symbol.])
+AH_TEMPLATE([HAVE_STRNAMES],
+[Define if you have the terminfo strnames symbol.])
+
+if test x$zsh_cv_path_term_header != xnone; then
+  AC_DEFINE(ZSH_HAVE_TERM_H)
+  ZSH_TERM_H=$zsh_cv_path_term_header
+  if test x$zsh_cv_path_curses_header != xnone; then
+    term_includes="#include <$zsh_cv_path_curses_header>
+#include <$zsh_cv_path_term_header>"
+  else
+    term_includes="#include <$zsh_cv_path_term_header>"
+  fi
+
+  AC_MSG_CHECKING(if boolcodes is available)
+  AC_TRY_LINK($term_includes, [char **test = boolcodes; printf(*test);],
+  AC_DEFINE(HAVE_BOOLCODES) boolcodes=yes, boolcodes=no)
+  AC_MSG_RESULT($boolcodes)
+  AC_MSG_CHECKING(if numcodes is available)
+  AC_TRY_LINK($term_includes, [char **test = numcodes; printf(*test);],
+  AC_DEFINE(HAVE_NUMCODES) numcodes=yes, numcodes=no)
+  AC_MSG_RESULT($numcodes)
+  AC_MSG_CHECKING(if strcodes is available)
+  AC_TRY_LINK($term_includes, [char **test = strcodes; printf(*test);],
+  AC_DEFINE(HAVE_STRCODES) strcodes=yes, strcodes=no)
+  AC_MSG_RESULT($strcodes)
+  AC_MSG_CHECKING(if boolnames is available)
+  AC_TRY_LINK($term_includes, [char **test = boolnames; printf(*test);],
+  AC_DEFINE(HAVE_BOOLNAMES) boolnames=yes, boolnames=no)
+  AC_MSG_RESULT($boolnames)
+  AC_MSG_CHECKING(if numnames is available)
+  AC_TRY_LINK($term_includes, [char **test = numnames; printf(*test);],
+  AC_DEFINE(HAVE_NUMNAMES) numnames=yes, numnames=no)
+  AC_MSG_RESULT($numnames)
+  AC_MSG_CHECKING(if strnames is available)
+  AC_TRY_LINK($term_includes, [char **test = strnames; printf(*test);],
+  AC_DEFINE(HAVE_STRNAMES) strnames=yes, strnames=no)
+  AC_MSG_RESULT($strnames)
+else
+  ZSH_TERM_H=
+fi
+AC_SUBST(ZSH_TERM_H)
+
+
+dnl -----------------------------------------------------
+dnl Look for the file containing the RLIMIT_* definitions
+dnl -----------------------------------------------------
+dnl CALL FOR MORE (FEWER?) LOCATIONS:  I've just copied the signal checking.
+AC_CACHE_CHECK(where the RLIMIT macros are located,zsh_cv_path_rlimit_h,
+[dnl Look at the output from the preprocessor.
+dnl Copied from the search for the signal names above.
+echo "#include <sys/resource.h>" >restmp.c
+resourcefile_list="`$CPP restmp.c |
+sed -n -e 's/^#line[ 	].*\"\(.*\)\"/\1/p' \
+       -e 's/^#[ 	].*\"\(.*\)\"/\1/p' |
+sed 's/\\\\\\\\/\//g' |
+$AWK '{ if ($1 ~ /resource/) files[[$1]] = $1 }
+  END { for (var in files) print var }'`"
+rm -f restmp.c
+if test -z "$resourcefile_list"; then
+  dnl No list: look at standard places.
+  resourcefile_list="/usr/include/bsd/sys/resource.h
+/usr/include/asm/resource.h
+/usr/include/linux/resource.h
+/usr/include/sys/resource.h
+/usr/include/bits/resource.h
+/usr/include/resourcebits.h"
+fi
+for RESOURCE_H in $resourcefile_list /dev/null;
+do
+  test -f $RESOURCE_H && \
+  grep '#[ 	]*define[ 	][ 	]*RLIMIT_[A-Z]*[ 	]*[0-9A-Z][0-9]*' $RESOURCE_H > /dev/null && \
+  break
+done
+zsh_cv_path_rlimit_h=$RESOURCE_H
+if test x$RESOURCE_H = x"/dev/null" && test x$ac_cv_func_getrlimit = xyes; then
+  AC_MSG_WARN(RLIMIT MACROS NOT FOUND:  please report to developers)
+fi])
+RLIMITS_INC_H=$zsh_cv_path_rlimit_h
+if test "$RLIMITS_INC_H" = "/dev/null"; then
+  RLIMITS_INC_H=''
+fi
+dnl rlimits.h only appears in dependencies if we are actually using it.
+dnl We are using it any time we have getrlimit, though if the macros were
+dnl not found we simply awk through /dev/null and fail to find them.
+dnl Thus, limit won't work, but at least the shell will compile.
+AC_SUBST(RLIMITS_INC_H)dnl
+
+dnl ------------------
+dnl rlimit type checks
+dnl ------------------
+AH_TEMPLATE([RLIM_T_IS_QUAD_T],
+[Define to 1 if struct rlimit uses quad_t.])
+AH_TEMPLATE([RLIM_T_IS_LONG_LONG],
+[Define to 1 if struct rlimit uses long long])
+AH_TEMPLATE([RLIM_T_IS_UNSIGNED],
+[Define to 1 if struct rlimit uses unsigned.])
+AH_TEMPLATE([rlim_t],
+[Define to the type used in struct rlimit.])
+DEFAULT_RLIM_T=long
+AC_CACHE_CHECK(if rlim_t is longer than a long,
+zsh_cv_rlim_t_is_longer,
+[AC_TRY_RUN([
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>
+main(){struct rlimit r;exit(sizeof(r.rlim_cur) <= sizeof(long));}],
+zsh_cv_rlim_t_is_longer=yes,
+zsh_cv_rlim_t_is_longer=no,
+zsh_cv_rlim_t_is_longer=yes)])
+if test x$zsh_cv_rlim_t_is_longer = xyes; then
+  AC_CACHE_CHECK(if rlim_t is a quad,
+  zsh_cv_rlim_t_is_quad_t,
+  [AC_TRY_RUN([
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+#include <sys/resource.h>
+main() { 
+  struct rlimit r;
+  char buf[20];
+  r.rlim_cur = 0;
+  sprintf(buf, "%qd", r.rlim_cur);
+  exit(strcmp(buf, "0"));
+}],
+  zsh_cv_rlim_t_is_quad_t=yes,
+  zsh_cv_rlim_t_is_quad_t=no,
+  zsh_cv_rlim_t_is_quad_t=no)])
+  if test x$zsh_cv_rlim_t_is_quad_t = xyes; then
+    AC_DEFINE(RLIM_T_IS_QUAD_T)
+    DEFAULT_RLIM_T=quad_t
+  else
+    AC_DEFINE(RLIM_T_IS_LONG_LONG)
+    DEFAULT_RLIM_T='long long'
+  fi
+else
+  AC_CACHE_CHECK(if the rlim_t is unsigned,
+  zsh_cv_type_rlim_t_is_unsigned,
+  [AC_TRY_RUN([
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>
+  main(){struct rlimit r;r.rlim_cur=-1;exit(r.rlim_cur<0);}],
+  zsh_cv_type_rlim_t_is_unsigned=yes,
+  zsh_cv_type_rlim_t_is_unsigned=no,
+  zsh_cv_type_rlim_t_is_unsigned=no)])
+  if test x$zsh_cv_type_rlim_t_is_unsigned = xyes; then
+    AC_DEFINE(RLIM_T_IS_UNSIGNED)
+    DEFAULT_RLIM_T="unsigned $DEFAULT_RLIM_T"
+  fi
+fi
+
+AC_CACHE_CHECK(for rlim_t, zsh_cv_type_rlim_t,
+[AC_TRY_COMPILE([
+#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>],
+[rlim_t l;],
+zsh_cv_type_rlim_t=yes,
+zsh_cv_type_rlim_t=no)])
+if test x$zsh_cv_type_rlim_t = xno; then
+  AC_DEFINE_UNQUOTED(rlim_t, $DEFAULT_RLIM_T)
+fi
+
+
+dnl On some systems the RLIMIT_* don't evaluate to integers at compile time
+dnl (they may be enums).  In this case we are not able to do preprocessor
+dnl comparisons and need our tests to determine what values exist and
+dnl if there are clashing definitions.
+
+zsh_LIMIT_PRESENT(RLIMIT_AIO_MEM)
+zsh_LIMIT_PRESENT(RLIMIT_AIO_OPS)
+zsh_LIMIT_PRESENT(RLIMIT_AS)
+zsh_LIMIT_PRESENT(RLIMIT_LOCKS)
+zsh_LIMIT_PRESENT(RLIMIT_MEMLOCK)
+zsh_LIMIT_PRESENT(RLIMIT_NPROC)
+zsh_LIMIT_PRESENT(RLIMIT_NOFILE)
+zsh_LIMIT_PRESENT(RLIMIT_PTHREAD)
+zsh_LIMIT_PRESENT(RLIMIT_RSS)
+zsh_LIMIT_PRESENT(RLIMIT_SBSIZE)
+zsh_LIMIT_PRESENT(RLIMIT_TCACHE)
+zsh_LIMIT_PRESENT(RLIMIT_VMEM)
+zsh_LIMIT_PRESENT(RLIMIT_SIGPENDING)
+zsh_LIMIT_PRESENT(RLIMIT_MSGQUEUE)
+zsh_LIMIT_PRESENT(RLIMIT_NICE)
+zsh_LIMIT_PRESENT(RLIMIT_RTPRIO)
+
+AH_TEMPLATE([RLIMIT_VMEM_IS_RSS],
+[Define to 1 if RLIMIT_VMEM and RLIMIT_RSS both exist and are equal.])
+AC_CACHE_CHECK(if RLIMIT_VMEM and RLIMIT_RSS are the same,
+zsh_cv_rlimit_vmem_is_rss,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>
+int main()
+{
+int ret = 1;
+#if defined(HAVE_RLIMIT_VMEM) && defined(HAVE_RLIMIT_RSS)
+if (RLIMIT_RSS == RLIMIT_VMEM) ret = 0;
+#endif
+return ret;
+}],
+  zsh_cv_rlimit_vmem_is_rss=yes,
+  zsh_cv_rlimit_vmem_is_rss=no,
+  zsh_cv_rlimit_vmem_is_rss=no)])
+
+if test x$zsh_cv_rlimit_vmem_is_rss = xyes; then
+  AC_DEFINE(RLIMIT_VMEM_IS_RSS)
+fi
+
+
+AH_TEMPLATE([RLIMIT_VMEM_IS_AS],
+[Define to 1 if RLIMIT_VMEM and RLIMIT_AS both exist and are equal.])
+AC_CACHE_CHECK(if RLIMIT_VMEM and RLIMIT_AS are the same,
+zsh_cv_rlimit_vmem_is_as,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>
+int main()
+{
+int ret = 1;
+#if defined(HAVE_RLIMIT_VMEM) && defined(HAVE_RLIMIT_AS)
+if (RLIMIT_AS == RLIMIT_VMEM) ret = 0;
+#endif
+return ret;
+}],
+  zsh_cv_rlimit_vmem_is_as=yes,
+  zsh_cv_rlimit_vmem_is_as=no,
+  zsh_cv_rlimit_vmem_is_as=no)])
+
+if test x$zsh_cv_rlimit_vmem_is_as = xyes; then
+  AC_DEFINE(RLIMIT_VMEM_IS_AS)
+fi
+
+
+AH_TEMPLATE([RLIMIT_RSS_IS_AS],
+[Define to 1 if RLIMIT_RSS and RLIMIT_AS both exist and are equal.])
+AC_CACHE_CHECK(if RLIMIT_RSS and RLIMIT_AS are the same,
+zsh_cv_rlimit_rss_is_as,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>
+int main()
+{
+int ret = 1;
+#if defined(HAVE_RLIMIT_RSS) && defined(HAVE_RLIMIT_AS)
+if (RLIMIT_AS == RLIMIT_RSS) ret = 0;
+#endif
+return ret;
+}],
+  zsh_cv_rlimit_rss_is_as=yes,
+  zsh_cv_rlimit_rss_is_as=no,
+  zsh_cv_rlimit_rss_is_as=no)])
+
+if test x$zsh_cv_rlimit_rss_is_as = xyes; then
+  AC_DEFINE(RLIMIT_RSS_IS_AS)
+fi
+
+
+dnl --------------------------------------------
+dnl Check for members of struct rusage
+dnl --------------------------------------------
+if test x$ac_cv_func_getrusage = xyes; then
+  AC_CHECK_MEMBERS([struct rusage.ru_maxrss,
+		    struct rusage.ru_ixrss,
+		    struct rusage.ru_idrss,
+		    struct rusage.ru_isrss,
+		    struct rusage.ru_minflt,
+		    struct rusage.ru_majflt,
+		    struct rusage.ru_nswap,
+		    struct rusage.ru_inblock,
+		    struct rusage.ru_oublock,
+		    struct rusage.ru_msgsnd,
+		    struct rusage.ru_msgrcv,
+		    struct rusage.ru_nsignals,
+		    struct rusage.ru_nvcsw,
+		    struct rusage.ru_nivcsw],,,
+[#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>])
+fi
+
+
+dnl --------------------------------------------
+dnl CHECK FOR DEFAULT PATH (used for command -p)
+dnl --------------------------------------------
+AC_CACHE_VAL(zsh_cv_cs_path,
+[if getconf _CS_PATH >/dev/null 2>&1; then
+  zsh_cv_cs_path=`getconf _CS_PATH`
+elif getconf CS_PATH >/dev/null 2>&1; then
+  zsh_cv_cs_path=`getconf CS_PATH`
+else
+  zsh_cv_cs_path="/bin:/usr/bin"
+fi])
+AC_DEFINE_UNQUOTED(DEFAULT_PATH, "$zsh_cv_cs_path",
+[The default path; used when running commands with command -p])
+
+
+dnl ----------------------------
+dnl CHECK FOR /dev/fd FILESYSTEM
+dnl ----------------------------
+dnl FreeBSD 5 only supports /dev/fd/0 to /dev/fd/2 without mounting
+dnl a special file system.  As zsh needs arbitrary /dev/fd (typically
+dnl >10) for its own use, we need to make sure higher fd's are available.
+dnl Since we're using the shell, we're restricted to 0 to 9 but 3 should
+dnl be good enough.
+AH_TEMPLATE([PATH_DEV_FD],
+[Define to the path of the /dev/fd filesystem.])
+AC_CACHE_CHECK(for /dev/fd filesystem, zsh_cv_sys_path_dev_fd,
+[for zsh_cv_sys_path_dev_fd in /proc/self/fd /dev/fd no; do
+   test x`echo ok|(exec 3<&0; cat $zsh_cv_sys_path_dev_fd/3 2>/dev/null;)` = xok && break
+ done])
+if test x$zsh_cv_sys_path_dev_fd != xno; then
+  AC_DEFINE_UNQUOTED(PATH_DEV_FD, "$zsh_cv_sys_path_dev_fd")
+fi
+
+dnl ---------------------------------
+dnl CHECK FOR RFS SUPERROOT DIRECTORY
+dnl ---------------------------------
+AC_CACHE_CHECK(for RFS superroot directory, zsh_cv_sys_superroot,
+[test -d /../.LOCALROOT && zsh_cv_sys_superroot=yes || zsh_cv_sys_superroot=no])
+AH_TEMPLATE([HAVE_SUPERROOT],
+[Define to 1 if you have RFS superroot directory.])
+if test x$zsh_cv_sys_superroot = xyes; then
+  AC_DEFINE(HAVE_SUPERROOT)
+fi
+
+dnl CHECK FOR SYSTEMS REQUIRING GETCWD
+AC_CACHE_CHECK(whether we should use the native getcwd,
+zsh_cv_use_getcwd,
+[case "${host_cpu}-${host_vendor}-${host_os}" in
+    *QNX*) zsh_cv_use_getcwd=yes ;;
+    *) zsh_cv_use_getcwd=no ;;
+ esac])
+AH_TEMPLATE([USE_GETCWD],
+[Define to 1 if you need to use the native getcwd.])
+if test x$zsh_cv_use_getcwd = xyes; then
+  AC_DEFINE(USE_GETCWD)
+fi
+
+dnl -------------
+dnl CHECK FOR NIS
+dnl -------------
+AH_TEMPLATE([HAVE_NIS],
+[Define to 1 if you have NIS.])
+AC_CACHE_CHECK(for NIS, zsh_cv_sys_nis,
+[test -f /usr/bin/ypcat && /usr/bin/ypcat passwd.byname > /dev/null 2>&1 && \
+zsh_cv_sys_nis=yes || zsh_cv_sys_nis=no])
+if test x$zsh_cv_sys_nis = xyes; then
+  AC_DEFINE(HAVE_NIS)
+dnl Some systems (Solaris 2.x, Linux Redhat 5.x) require
+dnl libnsl (Network Services Library) to find yp_all
+  AC_SEARCH_LIBS(yp_all, nsl)
+fi
+
+dnl -----------------
+dnl CHECK FOR NISPLUS
+dnl -----------------
+AH_TEMPLATE([HAVE_NIS_PLUS],
+[Define to 1 if you have NISPLUS.])
+AC_CACHE_CHECK(for NIS+, zsh_cv_sys_nis_plus,
+[test x$ac_cv_func_nis_list = xyes && test -f /usr/bin/nisls && \
+ /usr/bin/nisls > /dev/null 2>&1 && \
+zsh_cv_sys_nis_plus=yes || zsh_cv_sys_nis_plus=no])
+if test x$zsh_cv_sys_nis_plus = xyes; then
+  AC_DEFINE(HAVE_NIS_PLUS)
+fi
+
+dnl ----------------------------------------
+dnl CHECK FOR LOCATION OF {U,W}TMP{,X} FILES
+dnl ----------------------------------------
+zsh_PATH_UTMP(utmp)
+zsh_PATH_UTMP(wtmp)
+zsh_PATH_UTMP(utmpx)
+zsh_PATH_UTMP(wtmpx)
+
+dnl -------------------
+dnl brk/sbrk PROTOTYPES
+dnl -------------------
+AC_CACHE_CHECK(for brk() prototype in <unistd.h>,
+zsh_cv_header_unistd_h_brk_proto,
+[AC_TRY_COMPILE([#include <unistd.h>
+double brk();], [int i;],
+zsh_cv_header_unistd_h_brk_proto=no, zsh_cv_header_unistd_h_brk_proto=yes)])
+AH_TEMPLATE([HAVE_BRK_PROTO],
+[Define to 1 if there is a prototype defined for brk() on your system.])
+if test x$zsh_cv_header_unistd_h_brk_proto = xyes; then
+  AC_DEFINE(HAVE_BRK_PROTO)
+fi
+
+AC_CACHE_CHECK(for sbrk() prototype in <unistd.h>,
+zsh_cv_header_unistd_h_sbrk_proto,
+[AC_TRY_COMPILE([#include <unistd.h>
+double sbrk();], [int i;],
+zsh_cv_header_unistd_h_sbrk_proto=no, zsh_cv_header_unistd_h_sbrk_proto=yes)])
+AH_TEMPLATE([HAVE_SBRK_PROTO],
+[Define to 1 if there is a prototype defined for sbrk() on your system.])
+if test x$zsh_cv_header_unistd_h_sbrk_proto = xyes; then
+  AC_DEFINE(HAVE_SBRK_PROTO)
+fi
+
+dnl -----------------------
+dnl mknod prototype for OSF
+dnl -----------------------
+AH_TEMPLATE([HAVE_MKNOD_PROTO],
+[Define to 1 if there is a prototype defined for mknod() on your system.])
+if test "$ac_cv_prog_cc_stdc" != no; then
+  AC_CACHE_CHECK(for mknod prototype in <sys/stat.h>,
+  zsh_cv_header_sys_stat_h_mknod_proto,
+  [AC_TRY_COMPILE([#include <sys/stat.h>
+   int mknod(double x);], [int i;],
+  zsh_cv_header_sys_stat_h_mknod_proto=no,
+  zsh_cv_header_sys_stat_h_mknod_proto=yes)])
+  if test x$zsh_cv_header_sys_stat_h_mknod_proto = xyes; then
+    AC_DEFINE(HAVE_MKNOD_PROTO)
+  fi
+fi
+
+dnl ----------------------------------------
+dnl presence and location of ioctl prototype
+dnl ----------------------------------------
+AC_CACHE_CHECK(for ioctl prototype in <unistd.h> or <termios.h>,
+zsh_cv_header_unistd_h_termios_h_ioctl_proto,
+[AC_TRY_COMPILE([
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+double ioctl();], [int i;],
+zsh_cv_header_unistd_h_termios_h_ioctl_proto=no,
+zsh_cv_header_unistd_h_termios_h_ioctl_proto=yes)])
+
+if test x$zsh_cv_header_unistd_h_termios_h_ioctl_proto = xno; then
+  AC_CACHE_CHECK(for ioctl prototype in <sys/ioctl.h>,
+  zsh_cv_header_sys_ioctl_h_ioctl_proto,
+  [AC_TRY_COMPILE([#include <sys/ioctl.h>
+  double ioctl();], [int i;],
+  zsh_cv_header_sys_ioctl_h_ioctl_proto=no,
+  zsh_cv_header_sys_ioctl_h_ioctl_proto=yes)])
+else
+  zsh_cv_header_sys_ioctl_h_ioctl_proto=no
+fi
+
+AH_TEMPLATE([HAVE_IOCTL_PROTO],
+[Define to 1 if there is a prototype defined for ioctl() on your system.])
+if test x$zsh_cv_header_unistd_h_termios_h_ioctl_proto = xyes || \
+   test x$zsh_cv_header_sys_ioctl_h_ioctl_proto = xyes; then
+  AC_DEFINE(HAVE_IOCTL_PROTO)
+fi
+AH_TEMPLATE([IOCTL_IN_SYS_IOCTL],
+[Define to 1 if we must include <sys/ioctl.h> to get a prototype for ioctl().])
+if test x$zsh_cv_header_sys_ioctl_h_ioctl_proto = xyes; then
+  AC_DEFINE(IOCTL_IN_SYS_IOCTL)
+fi
+
+dnl -------------------
+dnl select() defined in <sys/socket.h>, ie BeOS R4.51
+dnl -------------------
+AH_TEMPLATE([SELECT_IN_SYS_SOCKET_H],
+[Define to 1 if select() is defined in <sys/socket.h>, ie BeOS R4.51])
+if test x$ac_cv_header_sys_select_h != xyes; then
+  AC_CACHE_CHECK(for select() in <sys/socket.h>,
+  zsh_cv_header_socket_h_select_proto,
+  [AC_TRY_COMPILE([#include <sys/socket.h>], [fd_set fd;],
+  zsh_cv_header_socket_h_select_proto=yes, 
+  zsh_cv_header_socket_h_select_proto=no)])
+  if test x$zsh_cv_header_socket_h_select_proto = xyes; then
+    AC_DEFINE(SELECT_IN_SYS_SOCKET_H)
+  fi
+fi
+
+dnl -----------
+dnl named FIFOs
+dnl -----------
+AC_CACHE_CHECK(if named FIFOs work,
+zsh_cv_sys_fifo,
+[if test "$host_os" = cygwin; then
+zsh_cv_sys_fifo=no
+else
+AC_TRY_RUN([
+#include <fcntl.h>
+#include <signal.h>
+main()
+{
+    char c;
+    int fd;
+    int pid, ret;
+    unlink("/tmp/fifo$$");
+#ifdef HAVE_MKFIFO
+    if(mkfifo("/tmp/fifo$$", 0600) < 0)
+#else
+    if(mknod("/tmp/fifo$$", 0010600, 0) < 0)
+#endif
+	exit(1);
+    pid = fork();
+    if(pid < 0)
+	exit(1);
+    if(pid) {
+	fd = open("/tmp/fifo$$", O_RDONLY);
+	exit(fd < 0 || read(fd, &c, 1) != 1 || c != 'x');
+    }
+    fd = open("/tmp/fifo$$", O_WRONLY);
+    ret = (fd < 0 || write(fd, "x", 1) < 1);
+    unlink("/tmp/fifo$$");
+    exit(ret);
+}
+],
+  zsh_cv_sys_fifo=yes,
+  zsh_cv_sys_fifo=no,
+  zsh_cv_sys_fifo=yes)
+fi])
+AH_TEMPLATE([HAVE_FIFOS],
+[Define to 1 if system has working FIFOs.])
+if test x$zsh_cv_sys_fifo = xyes; then
+  AC_DEFINE(HAVE_FIFOS)
+fi
+dnl ---------------------
+dnl echo style of /bin/sh
+dnl ---------------------
+AC_CACHE_CHECK(if echo in /bin/sh interprets escape sequences,
+zsh_cv_prog_sh_echo_escape,
+[if test "`/bin/sh -c \"echo '\\n'\"`" = "\\n"; then
+  zsh_cv_prog_sh_echo_escape=no
+else
+  zsh_cv_prog_sh_echo_escape=yes
+fi])
+AH_TEMPLATE([SH_USE_BSD_ECHO],
+[Define to 1 if /bin/sh does not interpret \ escape sequences.])
+if test x$zsh_cv_prog_sh_echo_escape = xno; then
+  AC_DEFINE(SH_USE_BSD_ECHO)
+fi
+
+dnl -----------
+dnl test for whether link() works
+dnl for instance, BeOS R4.51 doesn't support hard links yet
+dnl -----------
+AC_CACHE_CHECK(if link() works,
+zsh_cv_sys_link,
+[AC_TRY_RUN([
+#include <unistd.h>
+#include <fcntl.h>
+main()
+{
+    int ret;
+    char *tmpfile, *newfile;
+    tmpfile="/tmp/zsh.linktest$$";
+    newfile="/tmp/zsh.linktest2$$";
+    unlink(tmpfile);
+    unlink(newfile);
+    if(creat(tmpfile, 0644) < 0)
+	exit(1);
+    ret = link(tmpfile, newfile);
+    unlink(tmpfile);
+    unlink(newfile);
+    exit(ret<0);
+}
+],
+  zsh_cv_sys_link=yes,
+  zsh_cv_sys_link=no,
+  zsh_cv_sys_link=yes)])
+AH_TEMPLATE([HAVE_LINK],
+[Define to 1 if system has working link().])
+if test x$zsh_cv_sys_link = xyes; then
+  AC_DEFINE(HAVE_LINK)
+fi
+
+dnl -----------
+dnl test for whether kill(pid, 0) where pid doesn't exit
+dnl should set errno to ESRCH, but some like BeOS R4.51 set to EINVAL
+dnl -----------
+AC_CACHE_CHECK(if kill(pid, 0) returns ESRCH correctly,
+zsh_cv_sys_killesrch,
+[AC_TRY_RUN([
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+main()
+{
+    int pid = (getpid() + 10000) & 0xffffff;
+    while (pid && (kill(pid, 0) == 0 || errno != ESRCH)) pid >>= 1;
+    exit(errno!=ESRCH);
+}
+],
+  zsh_cv_sys_killesrch=yes,
+  zsh_cv_sys_killesrch=no,
+  zsh_cv_sys_killesrch=yes)])
+AH_TEMPLATE([BROKEN_KILL_ESRCH],
+[Define to 1 if kill(pid, 0) doesn't return ESRCH, ie BeOS R4.51.])
+if test x$zsh_cv_sys_killesrch = xno; then
+  AC_DEFINE(BROKEN_KILL_ESRCH)
+fi
+
+dnl -----------
+dnl if POSIX, test for working sigsuspend().
+dnl for instance, BeOS R4.51 is broken.
+dnl -----------
+AH_TEMPLATE([BROKEN_POSIX_SIGSUSPEND],
+Define to 1 if sigsuspend() is broken, ie BeOS R4.51.])
+if test x$signals_style = xPOSIX_SIGNALS; then
+    AC_CACHE_CHECK(if POSIX sigsuspend() works,
+    zsh_cv_sys_sigsuspend,
+    [AC_TRY_RUN([
+#include <signal.h>
+#include <unistd.h>
+int child=0;
+void handler(sig)
+    int sig;
+{if(sig==SIGCHLD) child=1;}
+main() {
+    struct sigaction act;
+    sigset_t set;
+    int pid, ret;
+    act.sa_handler = &handler;
+    sigfillset(&act.sa_mask);
+    act.sa_flags = 0;
+    sigaction(SIGCHLD, &act, 0);
+    sigfillset(&set);
+    sigprocmask(SIG_SETMASK, &set, 0);
+    pid=fork();
+    if(pid==0) return 0;
+    if(pid>0) {
+    sigemptyset(&set);
+        ret=sigsuspend(&set);
+        exit(child==0);
+    }
+}
+],
+      zsh_cv_sys_sigsuspend=yes,
+      zsh_cv_sys_sigsuspend=no,
+      zsh_cv_sys_sigsuspend=yes)])
+    if test x$zsh_cv_sys_sigsuspend = xno; then
+      AC_DEFINE(BROKEN_POSIX_SIGSUSPEND)
+    fi
+fi
+
+dnl -----------
+dnl if found tcsetpgrp, test to see if it actually works
+dnl for instance, BeOS R4.51 does not support it yet
+dnl -----------
+AH_TEMPLATE([BROKEN_TCSETPGRP],
+[Define to 1 if tcsetpgrp() doesn't work, ie BeOS R4.51.])
+AC_ARG_WITH(tcsetpgrp,
+AC_HELP_STRING([--with-tcsetpgrp], [assumes that tcsetpgrp() exists and works correctly]),[
+case "x$withval" in
+    xyes) zsh_working_tcsetpgrp=yes;;
+    xno)  zsh_working_tcsetpgrp=no;;
+    *)    AC_ERROR([please use --with-tcsetpgrp=yes or --with-tcsetpgrp=no]);;
+esac],[zsh_working_tcsetpgrp=check])
+if test "x$ac_cv_func_tcsetpgrp" = xyes; then
+case "x$zsh_working_tcsetpgrp" in
+  xcheck)
+    trap "" TTOU > /dev/null 2>&1 || :
+    AC_CACHE_CHECK(if tcsetpgrp() actually works,
+    zsh_cv_sys_tcsetpgrp,
+    [AC_TRY_RUN([
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+main() {
+    int fd;
+    int ret;
+    fd=open("/dev/tty", O_RDWR);
+    if (fd < 0) exit(2);
+    ret=tcsetpgrp(fd, tcgetpgrp(fd));
+    if (ret < 0) exit(1);
+    exit(0);
+}
+],
+      zsh_cv_sys_tcsetpgrp=yes, [
+case $? in
+    1) zsh_cv_sys_tcsetpgrp=no;;
+    2) zsh_cv_sys_tcsetpgrp=notty;;
+    *) zsh_cv_sys_tcsetpgrp=error;;
+esac
+      ], zsh_cv_sys_tcsetpgrp=yes)])
+    case "x$zsh_cv_sys_tcsetpgrp" in
+      xno)    AC_DEFINE(BROKEN_TCSETPGRP);;
+      xyes)   :;;
+      xnotty) AC_MSG_ERROR([no controlling tty
+Try running configure with --with-tcsetpgrp or --without-tcsetpgrp]);;
+      *)      AC_MSG_ERROR([unexpected return status]);;
+    esac
+    trap - TTOU > /dev/null 2>&1 || :
+    ;;
+  xyes) :;;
+  xno)  AC_DEFINE(BROKEN_TCSETPGRP);;
+  *)    AC_MSG_ERROR([unexpected value zsh_working_tcsetpgrp=$zsh_working_tcsetpgrp]);;
+esac
+fi
+
+dnl -----------
+dnl test for faked getpwnam() entry, ie a single entry returned for any username
+dnl for instance, BeOS R4.51 is not multiuser yet, and fakes getpwnam()
+dnl test by looking up two usernames that shouldn't succeed, and compare entry
+dnl -----------
+AH_TEMPLATE([GETPWNAM_FAKED],
+[Define to 1 if getpwnam() is faked, ie BeOS R4.51.])
+if test x$ac_cv_func_getpwnam = xyes; then
+    AC_CACHE_CHECK(if getpwnam() is faked,
+    zsh_cv_sys_getpwnam_faked,
+    [AC_TRY_RUN([
+#include <pwd.h>
+main() {
+    struct passwd *pw1, *pw2;
+    char buf[1024], name[1024];
+    sprintf(buf, "%d:%d", getpid(), rand());
+    pw1=getpwnam(buf);
+    if (pw1) strcpy(name, pw1->pw_name);
+    sprintf(buf, "%d:%d", rand(), getpid());
+    pw2=getpwnam(buf);
+    exit(pw1!=0 && pw2!=0 && !strcmp(name, pw2->pw_name));
+}
+],
+      zsh_cv_sys_getpwnam_faked=no,
+      zsh_cv_sys_getpwnam_faked=yes,
+      zsh_cv_sys_getpwnam_faked=no)])
+    if test x$zsh_cv_sys_getpwnam_faked = xyes; then
+      AC_DEFINE(GETPWNAM_FAKED)
+    fi
+fi
+
+
+dnl ---------------
+dnl check for the type of third argument of accept
+dnl ---------------
+
+zsh_CHECK_SOCKLEN_T
+
+dnl ---------------
+dnl Check for pty multiplexer for use in pty module.
+dnl We need to open it read/write, so make sure it is writeable.
+dnl Yet another test which won't work when cross-compiling.
+dnl ---------------
+AC_CACHE_CHECK(if your system has /dev/ptmx,
+ac_cv_have_dev_ptmx,
+[if test -w /dev/ptmx; then
+  ac_cv_have_dev_ptmx=yes
+else
+  ac_cv_have_dev_ptmx=no
+fi])
+
+dnl --------
+dnl Check if the ptmx functions are usable.
+dnl We need to be able to find the prototypes, which may
+dnl require non-POSIX source definitions.  So test to see
+dnl if ptsname is correctly recognised as returning a char *.
+dnl We do this by making sure a program where ptsname() is declared
+dnl as returning int does *not* compile.
+dnl On Linux we need the XOPEN extensions.  The easiest way to get
+dnl these is by defining _GNU_SOURCE.
+dnl -------
+AH_TEMPLATE([USE_DEV_PTMX],
+[Define to 1 if all the kit for using /dev/ptmx for ptys is available.])
+if test x$ac_cv_have_dev_ptmx = xyes && \
+   test x$ac_cv_func_grantpt = xyes && \
+   test x$ac_cv_func_unlockpt = xyes && \
+   test x$ac_cv_func_ptsname = xyes; then
+   AC_CACHE_CHECK([if /dev/ptmx is usable],
+   ac_cv_use_dev_ptmx,
+   [AC_TRY_COMPILE([#ifdef __linux
+#define _GNU_SOURCE 1
+#endif
+#include <stdlib.h>
+int ptsname();], ,
+   ac_cv_use_dev_ptmx=no,
+   ac_cv_use_dev_ptmx=yes)])
+   if test x$ac_cv_use_dev_ptmx = xyes; then
+     AC_DEFINE(USE_DEV_PTMX)
+   fi
+fi
+
+dnl -----------------
+dnl multibyte support
+dnl -----------------
+AC_ARG_ENABLE(multibyte,
+AC_HELP_STRING([--enable-multibyte], [support multibyte characters]),
+[zsh_cv_c_unicode_support=$enableval],
+[AC_CACHE_VAL(zsh_cv_c_unicode_support,
+  AC_MSG_NOTICE([checking for functions supporting multibyte characters])
+  [zfuncs_absent=
+   for zfunc in iswalnum iswcntrl iswdigit iswgraph iswlower iswprint \
+iswpunct iswspace iswupper iswxdigit mbrlen mbrtowc towupper towlower \
+wcschr wcscpy wcslen wcsncmp wcsncpy wcrtomb wcwidth wmemchr wmemcmp \
+wmemcpy wmemmove wmemset; do
+     AC_CHECK_FUNC($zfunc,
+     [:], [zfuncs_absent="$zfuncs_absent $zfunc"])
+    done
+    if test x"$zfuncs_absent" = x; then
+      AC_MSG_NOTICE([all functions found, multibyte support enabled])
+      zsh_cv_c_unicode_support=yes
+    else
+      AC_MSG_NOTICE([missing functions, multibyte support disabled])
+      zsh_cv_c_unicode_support=no
+    fi
+  ])
+])
+AH_TEMPLATE([MULTIBYTE_SUPPORT],
+[Define to 1 if you want support for multibyte character sets.])
+if test x$zsh_cv_c_unicode_support = xyes; then
+  AC_DEFINE(MULTIBYTE_SUPPORT)
+fi
+
+dnl
+dnl static user lookup
+dnl
+AC_ARG_ENABLE(dynamic-nss,
+	      AC_HELP_STRING([--disable-dynamic-nss], [do not call
+			      functions that will require dynamic NSS
+			      modules]),
+[zsh_cv_c_dynamic_nss=$enableval],
+[])
+
+AH_TEMPLATE([DISABLE_DYNAMIC_NSS],
+[Define to 1 if you want to avoid calling functions that will require
+ dynamic NSS modules.])
+if test x$zsh_cv_c_dynamic_nss = xno; then
+  AC_DEFINE(DISABLE_DYNAMIC_NSS)
+fi
+
+dnl ---------------
+dnl dynamic loading
+dnl ---------------
+AH_TEMPLATE([HPUXDYNAMIC],
+[Define to 1 if you want to use dynamically loaded modules on HPUX 10.])
+L=N
+INSTLIB="install.bin-\$(L)"
+UNINSTLIB="uninstall.bin-\$(L)"
+LINKMODS=NOLINKMODS
+MOD_EXPORT=
+MOD_IMPORT_VARIABLE=
+MOD_IMPORT_FUNCTION=
+aixdynamic=no
+hpuxdynamic=no
+if test "$ac_cv_func_load"      = yes &&
+   test "$ac_cv_func_unload"    = yes &&
+   test "$ac_cv_func_loadbind"  = yes &&
+   test "$ac_cv_func_loadquery" = yes; then
+  dnl Force AIXDYNAMIC even on newer versions that have dl family
+  if test "x$dynamic" = xyes; then
+    aixdynamic=yes
+  fi
+elif test "$ac_cv_func_dlopen"  != yes ||
+     test "$ac_cv_func_dlsym"   != yes ||
+     test "$ac_cv_func_dlerror" != yes; then
+  if test "$ac_cv_func_shl_load" != yes ||
+     test "$ac_cv_func_shl_unload" != yes ||
+     test "$ac_cv_func_shl_findsym" != yes; then
+    dynamic=no
+  elif test "x$dynamic" = xyes; then
+    hpuxdynamic=yes
+    DL_EXT="${DL_EXT=sl}"
+    dnl autoheader won't allow us to define anything which isn't
+    dnl going into a header, and we can't undefine anything, so
+    dnl just define this anyway and rely on the later tests to
+    dnl define DYNAMIC or not.
+    AC_DEFINE(HPUXDYNAMIC)dnl
+  fi
+fi
+
+test -n "$GCC" && LDARG=-Wl,
+
+AH_TEMPLATE([DLSYM_NEEDS_UNDERSCORE],
+[Define to 1 if an underscore has to be prepended to dlsym() argument.])
+AH_TEMPLATE([DYNAMIC_NAME_CLASH_OK],
+[Define to 1 if multiple modules defining the same symbol are OK.])
+if test "x$aixdynamic" = xyes; then
+  DL_EXT="${DL_EXT=so}"
+  DLLD="${DLLD=$CC}"
+  zsh_cv_func_dlsym_needs_underscore=no
+  if test -n "$GCC"; then
+    DLLDFLAGS=${DLLDFLAGS=-shared}
+  else
+    DLLDFLAGS=${DLLDFLAGS=-bM:SRE}
+  fi
+  DLLDFLAGS=${DLLDFLAGS=}
+  EXTRA_LDFLAGS=${EXTRA_LDFLAGS=}
+  EXPOPT=${LDARG}-bE:
+  IMPOPT=${LDARG}-bI:
+  zsh_cv_sys_dynamic_clash_ok="${zsh_cv_sys_dynamic_clash_ok=yes}"
+  zsh_cv_sys_dynamic_rtld_global="${zsh_cv_sys_dynamic_rtld_global=yes}"
+  zsh_cv_sys_dynamic_execsyms="${zsh_cv_sys_dynamic_execsyms=yes}"
+  zsh_cv_sys_dynamic_strip_exe="${zsh_cv_sys_dynamic_strip_exe=yes}"
+  zsh_cv_sys_dynamic_strip_lib="${zsh_cv_sys_dynamic_strip_lib=yes}"
+  zsh_cv_shared_environ="${zsh_cv_shared_environ=yes}"
+elif test "$host_os" = cygwin; then
+  DL_EXT="${DL_EXT=dll}"
+##DLLD="${DLLD=dllwrap}"
+  DLLD="${DLLD=$CC}"
+##DLLDFLAGS="${DLLDFLAGS=--export-all-symbols}"
+  DLLDFLAGS=${DLLDFLAGS=-shared -Wl,--export-all-symbols}
+  zsh_cv_func_dlsym_needs_underscore=no
+  DLLDFLAGS=${DLLDFLAGS=}
+  EXTRA_LDFLAGS=${EXTRA_LDFLAGS=}
+  zsh_cv_sys_dynamic_clash_ok="${zsh_cv_sys_dynamic_clash_ok=no}"
+  zsh_cv_sys_dynamic_rtld_global="${zsh_cv_sys_dynamic_rtld_global=yes}"
+  zsh_cv_sys_dynamic_execsyms="${zsh_cv_sys_dynamic_execsyms=no}"
+  zsh_cv_sys_dynamic_strip_exe="${zsh_cv_sys_dynamic_strip_exe=yes}"
+  zsh_cv_sys_dynamic_strip_lib="${zsh_cv_sys_dynamic_strip_lib=yes}"
+  #
+  # THAT SUCKS! and must be changed
+  #
+  zsh_cv_shared_environ="${zsh_cv_shared_environ=yes}"
+  LINKMODS=LINKMODS
+  MOD_EXPORT="__attribute__((__dllexport__))"
+  MOD_IMPORT_VARIABLE="__attribute__((__dllimport__))"
+  MOD_IMPORT_FUNCTION=
+elif test "x$dynamic" = xyes; then
+  AC_CACHE_CHECK(if your system uses ELF binaries,
+   zsh_cv_sys_elf,
+   [AC_TRY_RUN([/* Test for whether ELF binaries are produced */
+#include <fcntl.h>
+#include <stdlib.h>
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	char b[4];
+	int i = open(argv[0],O_RDONLY);
+	if(i == -1) 
+		exit(1); /* fail */
+	if(read(i,b,4)==4 && b[0]==127 && b[1]=='E' && b[2]=='L' && b[3]=='F')
+		exit(0); /* succeed (yes, it's ELF) */
+	else
+		exit(1); /* fail */
+}],
+  zsh_cv_sys_elf=yes,
+  zsh_cv_sys_elf=no,
+  zsh_cv_sys_elf=yes)])
+
+  # We use [0-9]* in case statements, so need to change quoting
+  changequote(, )
+
+  DL_EXT="${DL_EXT=so}"
+  if test x$zsh_cv_sys_elf = xyes; then
+    case "$host" in
+      mips-sni-sysv4*)
+        # Forcibly set ld to native compiler to avoid obscure GCC problems
+	DLLD="${DLLD=/usr/ccs/bin/cc}"
+	DLLDARG="${LDARG}"
+      ;;
+      * )
+	DLLD="${DLLD=$CC}"
+	DLLDARG="${LDARG}"
+      ;;
+    esac
+  else
+    case "$host" in
+      *openbsd*)
+	case "$host_os" in
+	  openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	    DLLD="${DLLD=ld}"
+	  ;;
+	  *)
+	    DLLD="${DLLD=$CC}"
+	  ;;
+	esac
+	DLLDARG="${LDARG}"
+      ;;
+      *darwin*)
+        DLLD="${DLLD=$CC}"
+        DLLDARG=""
+      ;;
+      * )
+	DLLD="${DLLD=ld}"
+	DLLDARG=""
+      ;;
+    esac
+  fi
+  if test -n "$GCC"; then
+    case "$host_os" in
+      hpux*)   DLLDFLAGS="${DLLDFLAGS=-shared}" ;;
+      darwin*) DLCFLAGS="${DLCFLAGS=-fno-common}" ;;
+      *)       DLCFLAGS="${DLCFLAGS=-fPIC}" ;;
+    esac
+  else
+    case "$host_os" in
+      hpux*)
+        DLCFLAGS="${DLCFLAGS=+z}"
+        DLLDFLAGS="${DLLDFLAGS=-b}"
+      ;;
+      sunos*)                DLCFLAGS="${DLCFLAGS=-pic}" ;;
+      solaris*|sysv4*|esix*) DLCFLAGS="${DLCFLAGS=-KPIC}" ;;
+    esac
+  fi
+  case "$host_os" in
+    osf*) DLLDFLAGS="${DLLDFLAGS=-shared -expect_unresolved '*'}" ;;
+    *freebsd*|linux*|irix*|gnu*|dragonfly*) DLLDFLAGS="${DLLDFLAGS=-shared}" ;;
+    sunos*)       DLLDFLAGS="${DLLDFLAGS=-assert nodefinitions}" ;;
+    sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G $ldflags}" ;;
+    netbsd*)      DLLDFLAGS="${DLLDFLAGS=${DLLDARG}-x -shared --whole-archive}" ;;
+    aix*)         DLLDFLAGS="${DLLDFLAGS=-G -bexpall -lc}" ;;
+    solaris*|sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G}" ;;
+    darwin*)      DLLDFLAGS="${DLLDFLAGS=-bundle -flat_namespace -undefined suppress}" ;;
+    openbsd*)
+      if test x$zsh_cv_sys_elf = xyes; then
+	DLLDFLAGS="${DLLDFLAGS=-shared -fPIC}"
+      else
+	case "$host_os" in
+	  openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+	   DLLDFLAGS="${DLLDFLAGS=-Bshareable}"
+	  ;;
+	  *)
+	    DLLDFLAGS="${DLLDFLAGS=-shared -fPIC}"
+	  ;;
+	esac
+      fi
+    ;;
+  esac
+  case "$host" in
+    *-hpux*)  EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-E}" ;;
+    *openbsd*)
+       if test x$zsh_cv_sys_elf = xyes; then
+	 EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-E}"
+       fi
+    ;;
+    mips-sni-sysv4)
+      #
+      # unfortunately, we have different compilers
+      # that need different flags
+      #
+      if test -n "$GCC"; then
+        sni_cc_version=GCC
+      else
+        sni_cc_version=`$CC -V 2>&1 | head -1`
+      fi
+      case "$sni_cc_version" in
+        *CDS*|GCC )
+         EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-Blargedynsym}"
+       ;;
+       * )
+         EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-LD-Blargedynsym}"
+       ;;
+      esac
+    ;;
+  esac
+
+  # Done with our shell code, so restore autotools quoting
+  changequote([, ])
+
+AC_CACHE_CHECK(if we can use -rdynamic, zsh_cv_rdynamic_available,
+old_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -rdynamic"
+AC_TRY_LINK([], [], [zsh_cv_rdynamic_available=yes
+EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-rdynamic}"],
+[zsh_cvs_rdynamic_available=no])
+LDFLAGS="$old_LDFLAGS")
+  AC_CACHE_CHECK(if your dlsym() needs a leading underscore,
+   zsh_cv_func_dlsym_needs_underscore,
+   [echo failed >conftestval && cat >conftest.c <<EOM
+fred () { }
+EOM
+    AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest.c 1>&AC_FD_CC) &&
+    AC_TRY_COMMAND($DLLD $LDFLAGS $DLLDFLAGS -o conftest.$DL_EXT conftest.o 1>&AC_FD_CC) &&
+    AC_TRY_RUN([
+#include <stdio.h>
+#ifdef HPUXDYNAMIC
+#include <dl.h>
+#define RTLD_LAZY BIND_DEFERRED
+#define RTLD_GLOBAL DYNAMIC_PATH
+
+char *zsh_gl_sym_addr ;
+
+#define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
+#define dlclose(handle) shl_unload((shl_t)(handle))
+#define dlsym(handle,name) (zsh_gl_sym_addr=0,shl_findsym((shl_t *)&(handle),name,TYPE_UNDEFINED,&zsh_gl_sym_addr), (void *)zsh_gl_sym_addr)
+#define dlerror() 0
+#else
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+#include <sys/types.h>
+#include <nlist.h>
+#include <link.h>
+#endif
+#endif
+#ifndef RTLD_LAZY
+#define RTLD_LAZY 1
+#endif
+
+extern int fred() ;
+
+main()
+{
+    void * handle ;
+    void * symbol ;
+    FILE *f=fopen("conftestval", "w");
+    if (!f) exit(1);
+    handle = dlopen("./conftest.$DL_EXT", RTLD_LAZY) ;
+    if (handle == NULL) {
+        fprintf (f, "dlopen failed") ;
+            exit(1);
+    }
+    symbol = dlsym(handle, "fred") ;
+    if (symbol == NULL) {
+                /* try putting a leading underscore */
+        symbol = dlsym(handle, "_fred") ;
+        if (symbol == NULL) {
+            fprintf (f, "dlsym failed") ;
+                exit(1);
+                }
+        fprintf (f, "yes") ;
+    }
+    else
+        fprintf (f, "no") ;
+    exit(0);
+}], zsh_cv_func_dlsym_needs_underscore=`cat conftestval`,
+    zsh_cv_func_dlsym_needs_underscore=failed
+    dynamic=no,
+    zsh_cv_func_dlsym_needs_underscore=no)])
+  if test "x$zsh_cv_func_dlsym_needs_underscore" = xyes; then
+    AC_DEFINE(DLSYM_NEEDS_UNDERSCORE)
+  elif test "x$zsh_cv_func_dlsym_needs_underscore" != xno; then
+    dnl Do not cache failed value
+    unset zsh_cv_func_dlsym_needs_underscore
+  fi
+fi
+
+if test "x$dynamic" = xyes; then
+  zsh_SHARED_VARIABLE([environ], [char **])
+  test "$zsh_cv_shared_environ" = yes || dynamic=no
+  if test "$ac_cv_func_tgetent" = yes; then
+    zsh_SHARED_FUNCTION([tgetent])
+  fi
+  if test "$ac_cv_func_tigetstr" = yes; then
+    zsh_SHARED_FUNCTION([tigetstr])
+  fi
+fi
+
+if test "x$dynamic" = xyes; then
+  zsh_SYS_DYNAMIC_CLASH
+  zsh_SYS_DYNAMIC_GLOBAL
+  RTLD_GLOBAL_OK=$zsh_cv_sys_dynamic_rtld_global
+  zsh_SYS_DYNAMIC_EXECSYMS
+  if test "$zsh_cv_sys_dynamic_execsyms" != yes; then
+    L=L
+  fi
+  zsh_SYS_DYNAMIC_STRIP_EXE
+  zsh_SYS_DYNAMIC_STRIP_LIB
+  if $strip_exeldflags && test "$zsh_cv_sys_dynamic_strip_exe" = yes; then
+    EXELDFLAGS="$EXELDFLAGS -s"
+  fi
+  if $strip_libldflags && test "$zsh_cv_sys_dynamic_strip_lib" = yes; then
+    LIBLDFLAGS="$LIBLDFLAGS -s"
+  fi
+  if test "$host_os" = cygwin; then
+    INSTLIB="install.cygwin-lib"
+    UNINSTLIB="uninstall.cygwin-lib"
+  fi
+else
+  $strip_exeldflags && EXELDFLAGS="$EXELDFLAGS -s"
+  $strip_libldflags && LIBLDFLAGS="$LIBLDFLAGS -s"
+  RTLD_GLOBAL_OK=no
+fi
+
+AH_TEMPLATE([DYNAMIC],
+[Define to 1 if you want to use dynamically loaded modules.])
+if test "x$dynamic" = xyes; then
+  D=D
+  AC_DEFINE(DYNAMIC)dnl
+else
+  D=N
+fi
+
+AH_TEMPLATE([AIXDYNAMIC],
+[Define to 1 if you want to use dynamically loaded modules on AIX.])
+if test "x$aixdynamic" = xyes; then
+  E=E
+  AC_DEFINE(AIXDYNAMIC)dnl
+else
+  E=N
+fi
+
+if test "x$zsh_cv_sys_dynamic_clash_ok" = xyes; then
+  SHORTBOOTNAMES=yes
+else
+  SHORTBOOTNAMES=no
+fi
+AC_SUBST(SHORTBOOTNAMES)
+
+AC_SUBST(INSTLIB)dnl
+AC_SUBST(UNINSTLIB)dnl
+
+if test "$host_os" = cygwin; then
+  EXTRAZSHOBJS="$EXTRAZSHOBJS zsh.res.o"
+fi
+
+AC_DEFINE_UNQUOTED(DL_EXT, "$DL_EXT",
+[The extension used for dynamically loaded modules.])dnl
+AC_SUBST(D)dnl
+AC_SUBST(DL_EXT)dnl
+AC_SUBST(DLLD)dnl
+AC_SUBST(DLCFLAGS)dnl
+AC_SUBST(DLLDFLAGS)dnl
+AC_SUBST(E)dnl
+AC_SUBST(EXTRA_LDFLAGS)dnl
+AC_SUBST(EXPOPT)dnl
+AC_SUBST(IMPOPT)dnl
+AC_SUBST(L)dnl
+AC_SUBST(LINKMODS)dnl
+AC_SUBST(MOD_EXPORT)dnl
+AC_SUBST(MOD_IMPORT_VARIABLE)dnl
+AC_SUBST(MOD_IMPORT_FUNCTION)dnl
+AC_SUBST(EXTRAZSHOBJS)dnl
+
+# Generate config.modules.  We look for *.mdd files in first and second
+# level subdirectories.  Any existing line not containing 'auto=y' will be
+# retained, provided the .mdd file itself was found.
+CONFIG_MODULES=./config.modules
+cat <<EOM > ${CONFIG_MODULES}.sh
+srcdir="$srcdir"
+dynamic="$dynamic"
+CONFIG_MODULES="${CONFIG_MODULES}"
+EOM
+cat <<\EOM >> ${CONFIG_MODULES}.sh
+echo "creating ${CONFIG_MODULES}"
+userlist=" "
+if test -f ${CONFIG_MODULES}; then
+  userlist="`sed -e '/^#/d' -e '/auto=y/d' -e 's/ .*/ /' -e 's/^name=/ /' \
+        ${CONFIG_MODULES}`"
+  mv ${CONFIG_MODULES} ${CONFIG_MODULES}.old
+else
+  # Save testing for existence each time.
+  echo > ${CONFIG_MODULES}.old
+fi
+(echo "# Edit this file to change the way modules are loaded."
+echo "# The format is strict; do not break lines or add extra spaces."
+echo "# Run \`make prep' if you change anything here after compiling"
+echo "# (there is no need if you change this just after the first time"
+echo "# you run \`configure')."
+echo "#"
+echo "# Values of \`link' are \`static', \`dynamic' or \`no' to compile the"
+echo "# module into the shell, link it in at run time, or not use it at all."
+echo "# In the final case, no attempt will be made to compile it."
+echo "# Use \`static' or \`no' if you do not have dynamic loading."
+echo "#"
+echo "# Values of \`load' are \`yes' or \`no'; if yes, any builtins etc."
+echo "# provided by the module will be autoloaded by the main shell"
+echo "# (so long as \`link' is not set to \`no')."
+echo "#"
+echo "# Values of \`auto' are \`yes' or \`no'. configure sets the value to"
+echo "# \`yes'.  If you set it by hand to \`no', the line will be retained"
+echo "# when the file is regenerated in future."
+echo "#"
+echo "# Note that the \`functions' entry extends to the end of the line."
+echo "# It should not be quoted; it is used verbatim to find files to install."
+echo "#"
+echo "# You will need to run \`config.status --recheck' if you add a new"
+echo "# module."
+echo "#"
+echo "# You should not change the values for the pseudo-module zsh/main,"
+echo "# which is the main shell (apart from the functions entry)."
+EOM
+dnl The autoconf macros are only available in configure, not
+dnl config.status, and only change when configure is rerun.
+dnl So we need to run the autoconf tests here and store the results.
+dnl We then generate config.modules, preserving any user-generated
+dnl information, from config.status.
+for modfile in `cd ${srcdir}; echo */*.mdd */*/*.mdd`; do
+  name=
+  link=
+  load=
+  functions=
+  result=
+  . ${srcdir}/$modfile
+  if test x$name != x && test x"$link" != x; then
+    case "$link" in
+      *\ *) eval "link=\`$link\`"
+	    ;;
+    esac
+    case "${load}" in
+      y*) load=" load=yes"
+	  ;;
+      *) load=" load=no"
+	 ;;
+    esac
+    if test "x$functions" != x; then
+      # N.B. no additional quotes
+      f=" functions=$functions"
+    else
+      f=
+    fi
+    case "$link" in
+      static) result="name=$name modfile=$modfile link=static auto=yes${load}$f"
+	      ;;
+      dynamic) if test x$dynamic != xno; then
+		  result="name=$name modfile=$modfile link=dynamic\
+ auto=yes${load}$f"
+	       else
+		 result="name=$name modfile=$modfile link=no\
+ auto=yes load=no$f"
+	       fi
+	       ;;
+      either) if test x$dynamic != xno; then
+		result="name=$name modfile=$modfile link=dynamic\
+ auto=yes${load}$f"
+	      else
+		result="name=$name modfile=$modfile link=static\
+ auto=yes${load}$f"
+	      fi
+	      ;;
+       *) result="name=$name modfile=$modfile link=no auto=yes load=no$f"
+	  ;;
+    esac
+dnl $result is the default output for config.modules.  We generate
+dnl code to check if we should use this.
+cat <<EOM >> ${CONFIG_MODULES}.sh
+case "\$userlist" in
+  *" $name "*) grep "^name=$name " \${CONFIG_MODULES}.old;;
+  *) echo "$result";;
+esac
+EOM
+  fi
+done
+cat <<\EOM >> ${CONFIG_MODULES}.sh
+) >${CONFIG_MODULES}
+rm -f ${CONFIG_MODULES}.old
+EOM
+
+dnl AH_TOP replaces the code which used to appear at the top
+dnl of acconfig.h.
+AH_TOP([/***** begin user configuration section *****/
+
+/* Define this to be the location of your password file */
+#define PASSWD_FILE "/etc/passwd"
+
+/* Define this to be the name of your NIS/YP password *
+ * map (if applicable)                                */
+#define PASSWD_MAP "passwd.byname"
+
+/* Define to 1 if you want user names to be cached */
+#define CACHE_USERNAMES 1
+
+/* Define to 1 if system supports job control */
+#define JOB_CONTROL 1
+
+/* Define this if you use "suspended" instead of "stopped" */
+#define USE_SUSPENDED 1
+ 
+/* The default history buffer size in lines */
+#define DEFAULT_HISTSIZE 30
+
+/* The default editor for the fc builtin */
+#define DEFAULT_FCEDIT "vi"
+
+/* The default prefix for temporary files */
+#define DEFAULT_TMPPREFIX "/tmp/zsh"
+
+/***** end of user configuration section            *****/
+/***** shouldn't have to change anything below here *****/
+
+])
+
+CLEAN_MK="${srcdir}/Config/clean.mk"
+CONFIG_MK="${srcdir}/Config/config.mk"
+dnl defs.mk is in the build tree, not the source tree
+DEFS_MK="Config/defs.mk"
+VERSION_MK="${srcdir}/Config/version.mk"
+
+AC_SUBST_FILE(CLEAN_MK)dnl
+AC_SUBST_FILE(CONFIG_MK)dnl
+AC_SUBST_FILE(DEFS_MK)dnl
+AC_SUBST_FILE(VERSION_MK)dnl
+
+AC_CONFIG_FILES(Config/defs.mk Makefile Doc/Makefile Etc/Makefile \
+Src/Makefile Test/Makefile)
+AC_CONFIG_COMMANDS([config.modules], [. ./config.modules.sh])
+AC_CONFIG_COMMANDS([stamp-h], [echo >stamp-h])
+
+AC_OUTPUT
+
+eval "zshbin1=${bindir}"
+eval "zshbin2=${zshbin1}"
+eval "zshman=${mandir}"
+eval "zshinfo=${infodir}"
+eval "zshfndir=${fndir}"
+
+echo "
+zsh configuration
+-----------------
+zsh version               : ${VERSION}
+host operating system     : ${host_cpu}-${host_vendor}-${host_os}
+source code location      : ${srcdir}
+compiler                  : ${CC}
+preprocessor flags        : ${CPPFLAGS}
+executable compiler flags : ${CFLAGS}"
+if test "$dynamic" = yes; then
+  echo "\
+module compiler flags     : ${CFLAGS} ${DLCFLAGS}"
+fi
+echo "\
+executable linker flags   : ${LDFLAGS} ${EXELDFLAGS} ${EXTRA_LDFLAGS}"
+if test "$dynamic" = yes; then
+  echo "\
+module linker flags       : ${LDFLAGS} ${LIBLDFLAGS} ${DLLDFLAGS}"
+fi
+echo "\
+library flags             : ${LIBS}
+installation basename     : ${tzsh_name}
+binary install path       : ${zshbin2}
+man page install path     : ${zshman}
+info install path         : ${zshinfo}"
+if test "$zshfndir" != no; then
+  echo "functions install path    : ${zshfndir}"
+fi
+echo "See config.modules for installed modules and functions.
+"
+
+
diff --color -Naur zsh-4.3.6.ori/Src/init.c.orig zsh-4.3.6.new/Src/init.c.orig
--- zsh-4.3.6.ori/Src/init.c.orig	2007-12-11 15:42:44.000000000 +0100
+++ zsh-4.3.6.new/Src/init.c.orig	1970-01-01 01:00:00.000000000 +0100
@@ -1,1383 +0,0 @@
-/*
- * init.c - main loop and initialization routines
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose.  The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#include "zsh.mdh"
-
-#include "zshpaths.h"
-#include "zshxmods.h"
-
-#include "init.pro"
-
-#include "version.h"
-
-/**/
-int noexitct = 0;
-
-/* buffer for $_ and its length */
-
-/**/
-char *underscore;
-
-/**/
-int underscorelen, underscoreused;
-
-/* what level of sourcing we are at */
- 
-/**/
-int sourcelevel;
-
-/* the shell tty fd */
-
-/**/
-mod_export int SHTTY;
-
-/* the FILE attached to the shell tty */
-
-/**/
-mod_export FILE *shout;
-
-/* termcap strings */
- 
-/**/
-mod_export char *tcstr[TC_COUNT];
-
-/* lengths of each termcap string */
- 
-/**/
-mod_export int tclen[TC_COUNT];
-
-/* Values of the li, co and am entries */
-
-/**/
-int tclines, tccolumns;
-/**/
-mod_export int hasam, hasxn;
-
-/* Pointer to read-key function from zle */
-
-/**/
-mod_export int (*getkeyptr) _((int, int *));
-
-/* SIGCHLD mask */
-
-/**/
-mod_export sigset_t sigchld_mask;
-
-/**/
-mod_export struct hookdef zshhooks[] = {
-    HOOKDEF("exit", NULL, HOOKF_ALL),
-    HOOKDEF("before_trap", NULL, HOOKF_ALL),
-    HOOKDEF("after_trap", NULL, HOOKF_ALL),
-};
-
-/* keep executing lists until EOF found */
-
-/**/
-void
-loop(int toplevel, int justonce)
-{
-    Eprog prog;
-
-    pushheap();
-    for (;;) {
-	freeheap();
-	if (stophist == 3)	/* re-entry via preprompt() */
-	    hend(NULL);
-	hbegin(1);		/* init history mech        */
-	if (isset(SHINSTDIN)) {
-	    setblock_stdin();
-	    if (interact && toplevel) {
-	        int hstop = stophist;
-		stophist = 3;
-		preprompt();
-		if (stophist != 3)
-		    hbegin(1);
-		else
-		    stophist = hstop;
-		errflag = 0;
-	    }
-	}
-	use_exit_printed = 0;
-	intr();			/* interrupts on            */
-	lexinit();              /* initialize lexical state */
-	if (!(prog = parse_event())) {	/* if we couldn't parse a list */
-	    hend(NULL);
-	    if ((tok == ENDINPUT && !errflag) ||
-		(tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
-		justonce)
-		break;
-	    if (exit_pending) {
-		/*
-		 * Something down there (a ZLE function?) decided
-		 * to exit when there was stuff to clear up.
-		 * Handle that now.
-		 */
-		stopmsg = 1;
-		zexit(exit_pending >> 1, 0);
-	    }
-	    if (tok == LEXERR && !lastval)
-		lastval = 1;
-	    continue;
-	}
-	if (hend(prog)) {
-	    int toksav = tok;
-
-	    if (toplevel &&
-		(getshfunc("preexec") != &dummy_eprog ||
-		 paramtab->getnode(paramtab, "preexec_functions"))) {
-		LinkList args;
-		char *cmdstr;
-
-		/*
-		 * As we're about to freeheap() or popheap()
-		 * anyway, there's no gain in using permanent
-		 * storage here.
-		 */
-		args = newlinklist();
-		addlinknode(args, "preexec");
-		/* If curline got dumped from the history, we don't know
-		 * what the user typed. */
-		if (hist_ring && curline.histnum == curhist)
-		    addlinknode(args, hist_ring->node.nam);
-		else
-		    addlinknode(args, "");
-		addlinknode(args, dupstring(getjobtext(prog, NULL)));
-		addlinknode(args, cmdstr = getpermtext(prog, NULL));
-
-		callhookfunc("preexec", args, 1);
-
-		/* The only permanent storage is from getpermtext() */
-		zsfree(cmdstr);
-		errflag = 0;
-	    }
-	    if (stopmsg)	/* unset 'you have stopped jobs' flag */
-		stopmsg--;
-	    execode(prog, 0, 0);
-	    tok = toksav;
-	    if (toplevel)
-		noexitct = 0;
-	}
-	if (ferror(stderr)) {
-	    zerr("write error");
-	    clearerr(stderr);
-	}
-	if (subsh)		/* how'd we get this far in a subshell? */
-	    exit(lastval);
-	if (((!interact || sourcelevel) && errflag) || retflag)
-	    break;
-	if (trapreturn) {
-	    lastval = trapreturn;
-	    trapreturn = 0;
-	}
-	if (isset(SINGLECOMMAND) && toplevel) {
-	    if (sigtrapped[SIGEXIT])
-		dotrap(SIGEXIT);
-	    exit(lastval);
-	}
-	if (justonce)
-	    break;
-    }
-    popheap();
-}
-
-static char *cmd;
-static int restricted;
-
-/**/
-void
-parseargs(char **argv)
-{
-    int optionbreak = 0;
-    char **x;
-    int action, optno;
-    LinkList paramlist;
-
-    argzero = *argv++;
-    SHIN = 0;
-
-    /* There's a bit of trickery with opts[INTERACTIVE] here.  It starts *
-     * at a value of 2 (instead of 1) or 0.  If it is explicitly set on  *
-     * the command line, it goes to 1 or 0.  If input is coming from     *
-     * somewhere that normally makes the shell non-interactive, we do    *
-     * "opts[INTERACTIVE] &= 1", so that only a *default* on state will  *
-     * be changed.  At the end of the function, a value of 2 gets        *
-     * changed to 1.                                                     */
-    opts[INTERACTIVE] = isatty(0) ? 2 : 0;
-    opts[SHINSTDIN] = 0;
-    opts[SINGLECOMMAND] = 0;
-
-    /* loop through command line options (begins with "-" or "+") */
-    while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) {
-	char *args = *argv;
-	action = (**argv == '-');
-	if (!argv[0][1])
-	    *argv = "--";
-	while (*++*argv) {
-	    if (**argv == '-') {
-		if(!argv[0][1]) {
-		    /* The pseudo-option `--' signifies the end of options. */
-		    argv++;
-		    goto doneoptions;
-		}
-		if(*argv != args+1 || **argv != '-')
-		    goto badoptionstring;
-		/* GNU-style long options */
-		++*argv;
-		if (!strcmp(*argv, "version")) {
-		    printf("zsh %s (%s-%s-%s)\n",
-			    ZSH_VERSION, MACHTYPE, VENDOR, OSTYPE);
-		    exit(0);
-		}
-		if (!strcmp(*argv, "help")) {
-		    printhelp();
-		    exit(0);
-		}
-		/* `-' characters are allowed in long options */
-		for(args = *argv; *args; args++)
-		    if(*args == '-')
-			*args = '_';
-		goto longoptions;
-	    }
-
-	    if (unset(SHOPTIONLETTERS) && **argv == 'b') {
-		/* -b ends options at the end of this argument */
-		optionbreak = 1;
-	    } else if (**argv == 'c') {
-		/* -c command */
-		cmd = *argv;
-		opts[INTERACTIVE] &= 1;
-		scriptname = ztrdup("zsh");
-	    } else if (**argv == 'o') {
-		if (!*++*argv)
-		    argv++;
-		if (!*argv) {
-		    zerr("string expected after -o");
-		    exit(1);
-		}
-	    longoptions:
-		if (!(optno = optlookup(*argv))) {
-		    zerr("no such option: %s", *argv);
-		    exit(1);
-		} else if (optno == RESTRICTED)
-		    restricted = action;
-		else
-		    dosetopt(optno, action, 1);
-              break;
-	    } else if (isspace(STOUC(**argv))) {
-		/* zsh's typtab not yet set, have to use ctype */
-		while (*++*argv)
-		    if (!isspace(STOUC(**argv))) {
-		    badoptionstring:
-			zerr("bad option string: `%s'", args);
-			exit(1);
-		    }
-		break;
-	    } else {
-	    	if (!(optno = optlookupc(**argv))) {
-		    zerr("bad option: -%c", **argv);
-		    exit(1);
-		} else if (optno == RESTRICTED)
-		    restricted = action;
-		else
-		    dosetopt(optno, action, 1);
-	    }
-	}
-	argv++;
-    }
-    doneoptions:
-    paramlist = znewlinklist();
-    if (cmd) {
-	if (!*argv) {
-	    zerr("string expected after -%s", cmd);
-	    exit(1);
-	}
-	cmd = *argv++;
-    }
-    if (*argv) {
-	if (unset(SHINSTDIN)) {
-	    if (!cmd)
-		SHIN = movefd(open(unmeta(*argv), O_RDONLY | O_NOCTTY));
-	    if (SHIN == -1) {
-		zerr("can't open input file: %s", *argv);
-		exit(127);
-	    }
-	    opts[INTERACTIVE] &= 1;
-	    argzero = *argv;
-	    argv++;
-	}
-	while (*argv)
-	    zaddlinknode(paramlist, ztrdup(*argv++));
-    } else if (!cmd)
-	opts[SHINSTDIN] = 1;
-    if(isset(SINGLECOMMAND))
-	opts[INTERACTIVE] &= 1;
-    opts[INTERACTIVE] = !!opts[INTERACTIVE];
-    pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *));
-
-    while ((*x++ = (char *)getlinknode(paramlist)));
-    free(paramlist);
-    argzero = ztrdup(argzero);
-}
-
-/**/
-static void
-printhelp(void)
-{
-    printf("Usage: %s [<options>] [<argument> ...]\n", argzero);
-    printf("\nSpecial options:\n");
-    printf("  --help     show this message, then exit\n");
-    printf("  --version  show zsh version number, then exit\n");
-    if(unset(SHOPTIONLETTERS))
-	printf("  -b         end option processing, like --\n");
-    printf("  -c         take first argument as a command to execute\n");
-    printf("  -o OPTION  set an option by name (see below)\n");
-    printf("\nNormal options are named.  An option may be turned on by\n");
-    printf("`-o OPTION', `--OPTION', `+o no_OPTION' or `+-no-OPTION'.  An\n");
-    printf("option may be turned off by `-o no_OPTION', `--no-OPTION',\n");
-    printf("`+o OPTION' or `+-OPTION'.  Options are listed below only in\n");
-    printf("`--OPTION' or `--no-OPTION' form.\n");
-    printoptionlist();
-}
-
-/**/
-mod_export void
-init_io(void)
-{
-    static char outbuf[BUFSIZ], errbuf[BUFSIZ];
-
-#ifdef RSH_BUG_WORKAROUND
-    int i;
-#endif
-
-/* stdout, stderr fully buffered */
-#ifdef _IOFBF
-    setvbuf(stdout, outbuf, _IOFBF, BUFSIZ);
-    setvbuf(stderr, errbuf, _IOFBF, BUFSIZ);
-#else
-    setbuffer(stdout, outbuf, BUFSIZ);
-    setbuffer(stderr, errbuf, BUFSIZ);
-#endif
-
-/* This works around a bug in some versions of in.rshd. *
- * Currently this is not defined by default.            */
-#ifdef RSH_BUG_WORKAROUND
-    if (cmd) {
-	for (i = 3; i < 10; i++)
-	    close(i);
-    }
-#endif
-
-    if (shout) {
-	/*
-	 * Check if shout was set to stderr, if so don't close it.
-	 * We do this if we are interactive but don't have a
-	 * terminal.
-	 */
-	if (shout != stderr)
-	    fclose(shout);
-	shout = 0;
-    }
-    if (SHTTY != -1) {
-	zclose(SHTTY);
-	SHTTY = -1;
-    }
-
-    /* Send xtrace output to stderr -- see execcmd() */
-    xtrerr = stderr;
-
-    /* Make sure the tty is opened read/write. */
-    if (isatty(0)) {
-	zsfree(ttystrname);
-	if ((ttystrname = ztrdup(ttyname(0)))) {
-	    SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY));
-#ifdef TIOCNXCL
-	    /*
-	     * See if the terminal claims to be busy.  If so, and fd 0
-	     * is a terminal, try and set non-exclusive use for that.
-	     * This is something to do with Solaris over-cleverness.
-	     */
-	    if (SHTTY == -1 && errno == EBUSY)
-		ioctl(0, TIOCNXCL, 0);
-#endif
-	}
-	/*
-	 * xterm, rxvt and probably all terminal emulators except
-	 * dtterm on Solaris 2.6 & 7 have a bug. Applications are
-	 * unable to open /dev/tty or /dev/pts/<terminal number here>
-	 * because something in Sun's STREAMS modules doesn't like
-	 * it. The open() call fails with EBUSY which is not even
-	 * listed as a possibility in the open(2) man page.  So we'll
-	 * try to outsmart The Company.  -- <dave@srce.hr>
-	 *
-	 * Presumably there's no harm trying this on any OS, given that
-	 * isatty(0) worked but opening the tty didn't.  Possibly we won't
-	 * get the tty read/write, but it's the best we can do -- pws
-	 *
-	 * Try both stdin and stdout before trying /dev/tty. -- Bart
-	 */
-#if defined(HAVE_FCNTL_H) && defined(F_GETFL)
-#define rdwrtty(fd)	((fcntl(fd, F_GETFL, 0) & O_RDWR) == O_RDWR)
-#else
-#define rdwrtty(fd)	1
-#endif
-	if (SHTTY == -1 && rdwrtty(0)) {
-	    SHTTY = movefd(dup(0));
-	}
-    }
-    if (SHTTY == -1 && isatty(1) && rdwrtty(1) &&
-	(SHTTY = movefd(dup(1))) != -1) {
-	zsfree(ttystrname);
-	ttystrname = ztrdup(ttyname(1));
-    }
-    if (SHTTY == -1 &&
-	(SHTTY = movefd(open("/dev/tty", O_RDWR | O_NOCTTY))) != -1) {
-	zsfree(ttystrname);
-	ttystrname = ztrdup(ttyname(SHTTY));
-    }
-    if (SHTTY == -1) {
-	zsfree(ttystrname);
-	ttystrname = ztrdup("");
-    } else if (!ttystrname) {
-	ttystrname = ztrdup("/dev/tty");
-    }
-
-    /* We will only use zle if shell is interactive, *
-     * SHTTY != -1, and shout != 0                   */
-    if (interact) {
-	init_shout();
-	if(!SHTTY || !shout)
-	    opts[USEZLE] = 0;
-    } else
-	opts[USEZLE] = 0;
-
-#ifdef JOB_CONTROL
-    /* If interactive, make sure the shell is in the foreground and is the
-     * process group leader.
-     */
-    mypid = (zlong)getpid();
-    if (opts[MONITOR] && interact && (SHTTY != -1)) {
-	origpgrp = GETPGRP();
-        acquire_pgrp(); /* might also clear opts[MONITOR] */
-    } else
-	opts[MONITOR] = 0;
-#else
-    opts[MONITOR] = 0;
-#endif
-}
-
-/**/
-mod_export void
-init_shout(void)
-{
-    static char shoutbuf[BUFSIZ];
-#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC)
-    int ldisc;
-#endif
-
-    if (SHTTY == -1)
-    {
-	/* Since we're interative, it's nice to have somewhere to write. */
-	shout = stderr;
-	return;
-    }
-
-#if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC)
-    ldisc = NTTYDISC;
-    ioctl(SHTTY, TIOCSETD, (char *)&ldisc);
-#endif
-
-    /* Associate terminal file descriptor with a FILE pointer */
-    shout = fdopen(SHTTY, "w");
-#ifdef _IOFBF
-    setvbuf(shout, shoutbuf, _IOFBF, BUFSIZ);
-#endif
-  
-    gettyinfo(&shttyinfo);	/* get tty state */
-#if defined(__sgi)
-    if (shttyinfo.tio.c_cc[VSWTCH] <= 0)	/* hack for irises */
-	shttyinfo.tio.c_cc[VSWTCH] = CSWTCH;
-#endif
-}
-
-/* names of the termcap strings we want */
-
-static char *tccapnams[TC_COUNT] = {
-    "cl", "le", "LE", "nd", "RI", "up", "UP", "do",
-    "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta",
-    "md", "so", "us", "me", "se", "ue", "ch",
-    "ku", "kd", "kl", "kr", "sc", "rc", "bc"
-};
-
-/* Initialise termcap */
-
-/**/
-mod_export int
-init_term(void)
-{
-#ifndef TGETENT_ACCEPTS_NULL
-    static char termbuf[2048];	/* the termcap buffer */
-#endif
-
-    if (!*term) {
-	termflags |= TERM_UNKNOWN;
-	return 0;
-    }
-
-    /* unset zle if using zsh under emacs */
-    if (!strcmp(term, "emacs"))
-	opts[USEZLE] = 0;
-
-#ifdef TGETENT_ACCEPTS_NULL
-    /* If possible, we let tgetent allocate its own termcap buffer */
-    if (tgetent(NULL, term) != TGETENT_SUCCESS)
-#else
-    if (tgetent(termbuf, term) != TGETENT_SUCCESS)
-#endif
-    {
-	if (isset(INTERACTIVE))
-	    zerr("can't find terminal definition for %s", term);
-	errflag = 0;
-	termflags |= TERM_BAD;
-	return 0;
-    } else {
-	char tbuf[1024], *pp;
-	int t0;
-
-	termflags &= ~TERM_BAD;
-	termflags &= ~TERM_UNKNOWN;
-	for (t0 = 0; t0 != TC_COUNT; t0++) {
-	    pp = tbuf;
-	    zsfree(tcstr[t0]);
-	/* AIX tgetstr() ignores second argument */
-	    if (!(pp = tgetstr(tccapnams[t0], &pp)))
-		tcstr[t0] = NULL, tclen[t0] = 0;
-	    else {
-		tclen[t0] = strlen(pp);
-		tcstr[t0] = (char *) zalloc(tclen[t0] + 1);
-		memcpy(tcstr[t0], pp, tclen[t0] + 1);
-	    }
-	}
-
-	/* check whether terminal has automargin (wraparound) capability */
-	hasam = tgetflag("am");
-	hasxn = tgetflag("xn"); /* also check for newline wraparound glitch */
-
-	tclines = tgetnum("li");
-	tccolumns = tgetnum("co");
-
-	/* if there's no termcap entry for cursor up, use single line mode: *
-	 * this is flagged by termflags which is examined in zle_refresh.c  *
-	 */
-	if (tccan(TCUP))
-	    termflags &= ~TERM_NOUP;
-	else {
-	    zsfree(tcstr[TCUP]);
-	    tcstr[TCUP] = NULL;
-	    termflags |= TERM_NOUP;
-	}
-
-	/* most termcaps don't define "bc" because they use \b. */
-	if (!tccan(TCBACKSPACE)) {
-	    zsfree(tcstr[TCBACKSPACE]);
-	    tcstr[TCBACKSPACE] = ztrdup("\b");
-	    tclen[TCBACKSPACE] = 1;
-	}
-
-	/* if there's no termcap entry for cursor left, use backspace. */
-	if (!tccan(TCLEFT)) {
-	    zsfree(tcstr[TCLEFT]);
-	    tcstr[TCLEFT] = ztrdup(tcstr[TCBACKSPACE]);
-	    tclen[TCLEFT] = tclen[TCBACKSPACE];
-	}
-
-	if (tccan(TCSAVECURSOR) && !tccan(TCRESTRCURSOR)) {
-	    tclen[TCSAVECURSOR] = 0;
-	    zsfree(tcstr[TCSAVECURSOR]);
-	    tcstr[TCSAVECURSOR] = NULL;
-	}
-
-	/* if the termcap entry for down is \n, don't use it. */
-	if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n') {
-	    tclen[TCDOWN] = 0;
-	    zsfree(tcstr[TCDOWN]);
-	    tcstr[TCDOWN] = NULL;
-	}
-
-	/* if there's no termcap entry for clear, use ^L. */
-	if (!tccan(TCCLEARSCREEN)) {
-	    zsfree(tcstr[TCCLEARSCREEN]);
-	    tcstr[TCCLEARSCREEN] = ztrdup("\14");
-	    tclen[TCCLEARSCREEN] = 1;
-	}
-    }
-    return 1;
-}
-
-/* Initialize lots of global variables and hash tables */
-
-/**/
-void
-setupvals(void)
-{
-#ifdef USE_GETPWUID
-    struct passwd *pswd;
-#endif
-    struct timezone dummy_tz;
-    char *ptr;
-    int i, j;
-#if defined(SITEFPATH_DIR) || defined(FPATH_DIR)
-    char **fpathptr;
-# if defined(FPATH_DIR) && defined(FPATH_SUBDIRS)
-    char *fpath_subdirs[] = FPATH_SUBDIRS;
-# endif
-# ifdef SITEFPATH_DIR
-    int fpathlen = 1;
-# else
-    int fpathlen = 0;
-# endif
-#endif
-    int close_fds[10], tmppipe[2];
-
-    /*
-     * Workaround a problem with NIS (in one guise or another) which
-     * grabs file descriptors and keeps them for future reference.
-     * We don't want these to be in the range where the user can
-     * open fd's, i.e. 0 to 9 inclusive.  So we make sure all
-     * fd's in that range are in use.
-     */
-    memset(close_fds, 0, 10*sizeof(int));
-    if (pipe(tmppipe) == 0) {
-	/*
-	 * Strategy:  Make sure we have at least fd 0 open (hence
-	 * the pipe).  From then on, keep dup'ing until we are
-	 * up to 9.  If we go over the top, close immediately, else
-	 * mark for later closure.
-	 */
-	i = -1;			/* max fd we have checked */
-	while (i < 9) {
-	    /* j is current fd */
-	    if (i < tmppipe[0])
-		j = tmppipe[0];
-	    else if (i < tmppipe[1])
-		j = tmppipe[1];
-	    else {
-		j = dup(0);
-		if (j == -1)
-		    break;
-	    }
-	    if (j < 10)
-		close_fds[j] = 1;
-	    else
-		close(j);
-	    if (i < j)
-		i = j;
-	}
-	if (i < tmppipe[0])
-	    close(tmppipe[0]);
-	if (i < tmppipe[1])
-	    close(tmppipe[1]);
-    }
-
-    (void)addhookdefs(NULL, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks));
-
-    init_eprog();
-
-    zero_mnumber.type = MN_INTEGER;
-    zero_mnumber.u.l = 0;
-
-    getkeyptr = NULL;
-
-    lineno = 1;
-    noeval = 0;
-    curhist = 0;
-    histsiz = DEFAULT_HISTSIZE;
-    inithist();
-
-    cmdstack = (unsigned char *) zalloc(CMDSTACKSZ);
-    cmdsp = 0;
-
-    bangchar = '!';
-    hashchar = '#';
-    hatchar = '^';
-    termflags = TERM_UNKNOWN;
-    curjob = prevjob = coprocin = coprocout = -1;
-    gettimeofday(&shtimer, &dummy_tz);	/* init $SECONDS */
-    srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */
-
-    /* Set default path */
-    path    = (char **) zalloc(sizeof(*path) * 5);
-    path[0] = ztrdup("/bin");
-    path[1] = ztrdup("/usr/bin");
-    path[2] = ztrdup("/usr/ucb");
-    path[3] = ztrdup("/usr/local/bin");
-    path[4] = NULL;
-
-    cdpath   = mkarray(NULL);
-    manpath  = mkarray(NULL);
-    fignore  = mkarray(NULL);
-
-#if defined(SITEFPATH_DIR) || defined(FPATH_DIR)
-# ifdef FPATH_DIR
-#  ifdef FPATH_SUBDIRS
-    fpathlen += sizeof(fpath_subdirs)/sizeof(char *);
-#  else
-    fpathlen++;
-#  endif
-# endif
-    fpath = fpathptr = (char **)zalloc((fpathlen+1)*sizeof(char *));
-# ifdef SITEFPATH_DIR
-    *fpathptr++ = ztrdup(SITEFPATH_DIR);
-    fpathlen--;
-# endif
-# ifdef FPATH_DIR
-#  ifdef FPATH_SUBDIRS
-    for (j = 0; j < fpathlen; j++)
-	*fpathptr++ = tricat(FPATH_DIR, "/", fpath_subdirs[j]);
-#  else
-    *fpathptr++ = ztrdup(FPATH_DIR);
-#  endif
-# endif
-    *fpathptr = NULL;
-#else
-    fpath    = mkarray(NULL);
-#endif
-
-    mailpath = mkarray(NULL);
-    watch    = mkarray(NULL);
-    psvar    = mkarray(NULL);
-    module_path = mkarray(ztrdup(MODULE_DIR));
-    modulestab = newmoduletable(17, "modules");
-    linkedmodules = znewlinklist();
-
-    /* Set default prompts */
-    if(unset(INTERACTIVE)) {
-	prompt = ztrdup("");
-	prompt2 = ztrdup("");
-    } else if (emulation == EMULATE_KSH || emulation == EMULATE_SH) {
-	prompt  = ztrdup(privasserted() ? "# " : "$ ");
-	prompt2 = ztrdup("> ");
-    } else {
-	prompt  = ztrdup("%m%# ");
-	prompt2 = ztrdup("%_> ");
-    }
-    prompt3 = ztrdup("?# ");
-    prompt4 = (emulation == EMULATE_KSH || emulation == EMULATE_SH)
-	? ztrdup("+ ") : ztrdup("+%N:%i> ");
-    sprompt = ztrdup("zsh: correct '%R' to '%r' [nyae]? ");
-
-    ifs         = ztrdup(DEFAULT_IFS);
-    wordchars   = ztrdup(DEFAULT_WORDCHARS);
-    postedit    = ztrdup("");
-    underscore  = (char *) zalloc(underscorelen = 32);
-    underscoreused = 1;
-    *underscore = '\0';
-
-    zoptarg = ztrdup("");
-    zoptind = 1;
-
-    ppid  = (zlong) getppid();
-    mypid = (zlong) getpid();
-    term  = ztrdup("");
-
-    nullcmd     = ztrdup("cat");
-    readnullcmd = ztrdup("more");
-
-    /* We cache the uid so we know when to *
-     * recheck the info for `USERNAME'     */
-    cached_uid = getuid();
-
-    /* Get password entry and set info for `USERNAME' */
-#ifdef USE_GETPWUID
-    if ((pswd = getpwuid(cached_uid))) {
-	if (emulation == EMULATE_ZSH)
-	    home = metafy(pswd->pw_dir, -1, META_DUP);
-	cached_username = ztrdup(pswd->pw_name);
-    }
-    else
-#endif /* USE_GETPWUID */
-    {
-	if (emulation == EMULATE_ZSH)
-	    home = ztrdup("/");
-	cached_username = ztrdup("");
-    }
-
-    /*
-     * Try a cheap test to see if we can initialize `PWD' from `HOME'.
-     * In non-native emulations HOME must come from the environment;
-     * we're not allowed to set it locally.
-     */
-    if (emulation == EMULATE_ZSH)
-	ptr = home;
-    else
-	ptr = zgetenv("HOME");
-    if (ptr && ispwd(ptr))
-	pwd = ztrdup(ptr);
-    else if ((ptr = zgetenv("PWD")) && (strlen(ptr) < PATH_MAX) &&
-	     (ptr = metafy(ptr, -1, META_STATIC), ispwd(ptr)))
-	pwd = ztrdup(ptr);
-    else
-	pwd = metafy(zgetcwd(), -1, META_DUP);
-
-    oldpwd = ztrdup(pwd);  /* initialize `OLDPWD' = `PWD' */
-
-    inittyptab();     /* initialize the ztypes table */
-    initlextabs();    /* initialize lexing tables    */
-
-    createreswdtable();     /* create hash table for reserved words    */
-    createaliastables();    /* create hash tables for aliases           */
-    createcmdnamtable();    /* create hash table for external commands */
-    createshfunctable();    /* create hash table for shell functions   */
-    createbuiltintable();   /* create hash table for builtin commands  */
-    createnameddirtable();  /* create hash table for named directories */
-    createparamtable();     /* create parameter hash table             */
-
-    condtab = NULL;
-    wrappers = NULL;
-
-#ifdef TIOCGWINSZ
-    adjustwinsize(0);
-#else
-    /* columns and lines are normally zero, unless something different *
-     * was inhereted from the environment.  If either of them are zero *
-     * the setiparam calls below set them to the defaults from termcap */
-    setiparam("COLUMNS", columns);
-    setiparam("LINES", lines);
-#endif
-
-#ifdef HAVE_GETRLIMIT
-    for (i = 0; i != RLIM_NLIMITS; i++) {
-	getrlimit(i, current_limits + i);
-	limits[i] = current_limits[i];
-    }
-#endif
-
-    breaks = loops = 0;
-    lastmailcheck = time(NULL);
-    locallevel = sourcelevel = 0;
-    sfcontext = SFC_NONE;
-    trapreturn = 0;
-    noerrexit = -1;
-    nohistsave = 1;
-    dirstack = znewlinklist();
-    bufstack = znewlinklist();
-    hsubl = hsubr = NULL;
-    lastpid = 0;
-    bshin = SHIN ? fdopen(SHIN, "r") : stdin;
-    if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) {
-#ifdef _IONBF
-	setvbuf(stdin, NULL, _IONBF, 0);
-#else
-	setlinebuf(stdin);
-#endif
-    }
-
-    get_usage();
-
-    /* Close the file descriptors we opened to block off 0 to 9 */
-    for (i = 0; i < 10; i++)
-	if (close_fds[i])
-	    close(i);
-}
-
-/* Initialize signal handling */
-
-/**/
-void
-init_signals(void)
-{
-    if (interact) {
-	int i;
-	signal_setmask(signal_mask(0));
-	for (i=0; i<NSIG; ++i)
-	    signal_default(i);
-    }
-    sigchld_mask = signal_mask(SIGCHLD);
-
-    intr();
-
-#ifndef QDEBUG
-    signal_ignore(SIGQUIT);
-#endif
-
-    if (signal_ignore(SIGHUP) == SIG_IGN)
-	opts[HUP] = 0;
-    else
-	install_handler(SIGHUP);
-    install_handler(SIGCHLD);
-#ifdef SIGWINCH
-    install_handler(SIGWINCH);
-#endif
-    if (interact) {
-	install_handler(SIGALRM);
-	signal_ignore(SIGTERM);
-    }
-    if (jobbing) {
-	signal_ignore(SIGTTOU);
-	signal_ignore(SIGTSTP);
-	signal_ignore(SIGTTIN);
-    }
-}
-
-/* Source the init scripts.  If called as "ksh" or "sh"  *
- * then we source the standard sh/ksh scripts instead of *
- * the standard zsh scripts                              */
-
-/**/
-void
-run_init_scripts(void)
-{
-    noerrexit = -1;
-
-    if (emulation == EMULATE_KSH || emulation == EMULATE_SH) {
-	if (islogin)
-	    source("/etc/profile");
-	if (unset(PRIVILEGED)) {
-	    char *s = getsparam("ENV");
-	    if (islogin)
-		sourcehome(".profile");
-	    noerrs = 2;
-	    if (s && !parsestr(s)) {
-		singsub(&s);
-		noerrs = 0;
-		source(s);
-	    }
-	    noerrs = 0;
-	} else
-	    source("/etc/suid_profile");
-    } else {
-#ifdef GLOBAL_ZSHENV
-	source(GLOBAL_ZSHENV);
-#endif
-
-	if (isset(RCS) && unset(PRIVILEGED))
-	{
-	    if (isset(INTERACTIVE)) {
-		/*
-		 * Always attempt to load the newuser module to perform
-		 * checks for new zsh users.  Don't care if we can't load it.
-		 */
-		if (!load_module("zsh/newuser", NULL, 1)) {
-		    /* Unload it immediately. */
-		    unload_named_module("zsh/newuser", "zsh", 1);
-		}
-	    }
-
-	    sourcehome(".zshenv");
-	}
-	if (islogin) {
-#ifdef GLOBAL_ZPROFILE
-	    if (isset(RCS) && isset(GLOBALRCS))
-		    source(GLOBAL_ZPROFILE);
-#endif
-	    if (isset(RCS) && unset(PRIVILEGED))
-		sourcehome(".zprofile");
-	}
-	if (interact) {
-#ifdef GLOBAL_ZSHRC
-	    if (isset(RCS) && isset(GLOBALRCS))
-		source(GLOBAL_ZSHRC);
-#endif
-	    if (isset(RCS) && unset(PRIVILEGED))
-		sourcehome(".zshrc");
-	}
-	if (islogin) {
-#ifdef GLOBAL_ZLOGIN
-	    if (isset(RCS) && isset(GLOBALRCS))
-		source(GLOBAL_ZLOGIN);
-#endif
-	    if (isset(RCS) && unset(PRIVILEGED))
-		sourcehome(".zlogin");
-	}
-    }
-    noerrexit = 0;
-    nohistsave = 0;
-}
-
-/* Miscellaneous initializations that happen after init scripts are run */
-
-/**/
-void
-init_misc(void)
-{
-#ifndef RESTRICTED_R
-    if ( restricted )
-#else
-    if (*zsh_name == 'r' || restricted)
-#endif
-	dosetopt(RESTRICTED, 1, 0);
-    if (cmd) {
-	if (SHIN >= 10)
-	    fclose(bshin);
-	SHIN = movefd(open("/dev/null", O_RDONLY | O_NOCTTY));
-	bshin = fdopen(SHIN, "r");
-	execstring(cmd, 0, 1);
-	stopmsg = 1;
-	zexit(lastval, 0);
-    }
-
-    if (interact && isset(RCS))
-	readhistfile(NULL, 0, HFILE_USE_OPTIONS);
-}
-
-/* source a file */
-
-/**/
-mod_export int
-source(char *s)
-{
-    Eprog prog;
-    int tempfd = -1, fd, cj, oldlineno;
-    int oldshst, osubsh, oloops;
-    FILE *obshin;
-    char *old_scriptname = scriptname, *us;
-    unsigned char *ocs;
-    int ocsp;
-
-    if (!s || 
-	(!(prog = try_source_file((us = unmeta(s)))) &&
-	 (tempfd = movefd(open(us, O_RDONLY | O_NOCTTY))) == -1)) {
-	return 1;
-    }
-
-    /* save the current shell state */
-    fd        = SHIN;            /* store the shell input fd                  */
-    obshin    = bshin;          /* store file handle for buffered shell input */
-    osubsh    = subsh;           /* store whether we are in a subshell        */
-    cj        = thisjob;         /* store our current job number              */
-    oldlineno = lineno;          /* store our current lineno                  */
-    oloops    = loops;           /* stored the # of nested loops we are in    */
-    oldshst   = opts[SHINSTDIN]; /* store current value of this option        */
-    ocs = cmdstack;
-    ocsp = cmdsp;
-    cmdstack = (unsigned char *) zalloc(CMDSTACKSZ);
-    cmdsp = 0;
-
-    if (!prog) {
-	SHIN = tempfd;
-	bshin = fdopen(SHIN, "r");
-    }
-    subsh  = 0;
-    lineno = 1;
-    loops  = 0;
-    dosetopt(SHINSTDIN, 0, 1);
-    scriptname = s;
-
-    sourcelevel++;
-    if (prog) {
-	pushheap();
-	errflag = 0;
-	execode(prog, 1, 0);
-	popheap();
-    } else
-	loop(0, 0);		     /* loop through the file to be sourced  */
-    sourcelevel--;
-
-    /* restore the current shell state */
-    if (prog)
-	freeeprog(prog);
-    else {
-	fclose(bshin);
-	fdtable[SHIN] = FDT_UNUSED;
-	SHIN = fd;		     /* the shell input fd                   */
-	bshin = obshin;		     /* file handle for buffered shell input */
-    }
-    subsh = osubsh;                  /* whether we are in a subshell         */
-    thisjob = cj;                    /* current job number                   */
-    lineno = oldlineno;              /* our current lineno                   */
-    loops = oloops;                  /* the # of nested loops we are in      */
-    dosetopt(SHINSTDIN, oldshst, 1); /* SHINSTDIN option                     */
-    errflag = 0;
-    if (!exit_pending)
-	retflag = 0;
-    scriptname = old_scriptname;
-    free(cmdstack);
-    cmdstack = ocs;
-    cmdsp = ocsp;
-
-    return 0;
-}
-
-/* Try to source a file in the home directory */
-
-/**/
-void
-sourcehome(char *s)
-{
-    char *h;
-
-    queue_signals();
-    if (emulation == EMULATE_SH || emulation == EMULATE_KSH ||
-	!(h = getsparam("ZDOTDIR"))) {
-	h = home;
-	if (!h)
-	    return;
-    }
-
-    {
-	/* Let source() complain if path is too long */
-	VARARR(char, buf, strlen(h) + strlen(s) + 2);
-	sprintf(buf, "%s/%s", h, s);
-	unqueue_signals();
-	source(buf);
-    }
-}
-
-/**/
-void
-init_bltinmods(void)
-{
-
-#include "bltinmods.list"
-
-    (void)load_module("zsh/main", NULL, 0);
-}
-
-/**/
-mod_export void
-noop_function(void)
-{
-    /* do nothing */
-}
-
-/**/
-mod_export void
-noop_function_int(UNUSED(int nothing))
-{
-    /* do nothing */
-}
-
-/* ZLE entry point pointers.  They are defined here because the initial *
- * values depend on whether ZLE is linked in or not -- if it is, we     *
- * avoid wasting space with the fallback functions.  No other source    *
- * file needs to know which modules are linked in.                      */
-
-#ifdef LINKED_XMOD_zshQszle
-
-/**/
-mod_export ZleVoidFn trashzleptr = noop_function;
-/**/
-mod_export ZleVoidFn zle_resetpromptptr = noop_function;
-/**/
-mod_export ZleVoidFn zrefreshptr = noop_function;
-/**/
-mod_export ZleVoidIntFn zleaddtolineptr = noop_function_int;
-/**/
-mod_export ZleGetLineFn zlegetlineptr = NULL;
-/**/
-mod_export ZleReadFn zlereadptr = autoload_zleread;
-/**/
-mod_export ZleVoidIntFn zlesetkeymapptr = noop_function_int;
-
-#else /* !LINKED_XMOD_zshQszle */
-
-mod_export ZleVoidFn trashzleptr = noop_function;
-mod_export ZleVoidFn zle_resetpromptptr = noop_function;
-mod_export ZleVoidFn zrefreshptr = noop_function;
-mod_export ZleVoidIntFn zleaddtolineptr = noop_function_int;
-mod_export ZleGetLineFn zlegetlineptr = NULL;
-# ifdef UNLINKED_XMOD_zshQszle
-mod_export ZleReadFn zlereadptr = autoload_zleread;
-mod_export ZleVoidIntFn zlesetkeymapptr = autoload_zlesetkeymap;
-# else /* !UNLINKED_XMOD_zshQszle */
-mod_export ZleReadFn zlereadptr = fallback_zleread;
-mod_export ZleVoidIntFn zlesetkeymapptr = noop_function_int;
-# endif /* !UNLINKED_XMOD_zshQszle */
-
-#endif /* !LINKED_XMOD_zshQszle */
-
-/**/
-char *
-autoload_zleread(char **lp, char **rp, int ha, int con)
-{
-    zlereadptr = fallback_zleread;
-    if (load_module("zsh/zle", NULL, 0) != 1)
-	(void)load_module("zsh/compctl", NULL, 0);
-    return zlereadptr(lp, rp, ha, con);
-}
-
-/**/
-mod_export char *
-fallback_zleread(char **lp, UNUSED(char **rp), UNUSED(int ha), UNUSED(int con))
-{
-    char *pptbuf;
-    int pptlen;
-
-    pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL), &pptlen);
-    write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
-    free(pptbuf);
-
-    return shingetline();
-}
-
-/**/
-#ifdef UNLINKED_XMOD_zshQszle
-
-/**/
-static void
-autoload_zlesetkeymap(int mode)
-{
-    zlesetkeymapptr = noop_function_int;
-    (void)load_module("zsh/zle", NULL, 0);
-    (*zlesetkeymapptr)(mode);
-}
-
-/**/
-#endif
-
-/* compctl entry point pointers.  Similar to the ZLE ones. */
-
-/**/
-mod_export CompctlReadFn compctlreadptr = fallback_compctlread;
-
-/**/
-mod_export int
-fallback_compctlread(char *name, UNUSED(char **args), UNUSED(Options ops), UNUSED(char *reply))
-{
-    zwarnnam(name, "option valid only in functions called from completion");
-    return 1;
-}
-
-/*
- * Used by zle to indicate it has already printed a "use 'exit' to exit"
- * message.
- */
-/**/
-mod_export int use_exit_printed;
-
-/*
- * This is real main entry point. This has to be mod_export'ed
- * so zsh.exe can found it on Cygwin
- */
-
-/**/
-mod_export int
-zsh_main(UNUSED(int argc), char **argv)
-{
-    char **t;
-    int t0;
-#ifdef USE_LOCALE
-    setlocale(LC_ALL, "");
-#endif
-
-    init_jobs(argv, environ);
-
-    /*
-     * Provisionally set up the type table to allow metafication.
-     * This will be done properly when we have decided if we are
-     * interactive
-     */
-    typtab['\0'] |= IMETA;
-    typtab[STOUC(Meta)  ] |= IMETA;
-    typtab[STOUC(Marker)] |= IMETA;
-    for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
-	typtab[t0] |= ITOK | IMETA;
-
-    for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++);
-
-    zsh_name = argv[0];
-    do {
-      char *arg0 = zsh_name;
-      if (!(zsh_name = strrchr(arg0, '/')))
-	  zsh_name = arg0;
-      else
-	  zsh_name++;
-      if (*zsh_name == '-')
-	  zsh_name++;
-      if (strcmp(zsh_name, "su") == 0) {
-	  char *sh = zgetenv("SHELL");
-	  if (sh && *sh && arg0 != sh)
-	      zsh_name = sh;
-	  else
-	      break;
-      } else
-	  break;
-    } while (zsh_name);
-
-    fdtable_size = zopenmax();
-    fdtable = zshcalloc(fdtable_size*sizeof(*fdtable));
-
-    createoptiontable();
-    emulate(zsh_name, 1);   /* initialises most options */
-    opts[LOGINSHELL] = (**argv == '-');
-    opts[MONITOR] = 1;   /* may be unset in init_io() */
-    opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid());
-    opts[USEZLE] = 1;   /* may be unset in init_io() */
-    parseargs(argv);   /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */
-
-    SHTTY = -1;
-    init_io();
-    setupvals();
-    init_signals();
-    init_bltinmods();
-    run_init_scripts();
-    init_misc();
-
-    for (;;) {
-	/*
-	 * See if we can free up some of jobtab.
-	 * We only do this at top level, because if we are
-	 * executing stuff we may refer to them by job pointer.
-	 */
-	maybeshrinkjobtab();
-
-	do {
-	    /* Reset return from top level which gets us back here */
-	    retflag = 0;
-	    loop(1,0);
-	} while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN)));
-	if (tok == LEXERR) {
-	    /* Make sure a parse error exits with non-zero status */
-	    if (!lastval)
-		lastval = 1;
-	    stopmsg = 1;
-	    zexit(lastval, 0);
-	}
-	if (!(isset(IGNOREEOF) && interact)) {
-#if 0
-	    if (interact)
-		fputs(islogin ? "logout\n" : "exit\n", shout);
-#endif
-	    zexit(lastval, 0);
-	    continue;
-	}
-	noexitct++;
-	if (noexitct >= 10) {
-	    stopmsg = 1;
-	    zexit(lastval, 0);
-	}
-	/*
-	 * Don't print the message if it was already handled by
-	 * zle, since that makes special arrangements to keep
-	 * the display tidy.
-	 */
-	if (!use_exit_printed)
-	    zerrnam("zsh", (!islogin) ? "use 'exit' to exit."
-		    : "use 'logout' to logout.");
-    }
-}
diff --color -Naur zsh-4.3.6.ori/Src/openssh_bsd_setres_id.c zsh-4.3.6.new/Src/openssh_bsd_setres_id.c
--- zsh-4.3.6.ori/Src/openssh_bsd_setres_id.c	1970-01-01 01:00:00.000000000 +0100
+++ zsh-4.3.6.new/Src/openssh_bsd_setres_id.c	2022-03-02 12:31:34.134390590 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012 Darren Tucker (dtucker at zip com au).
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * openssh_bsd_setres_id.c - setresuid() and setresgid() wrappers
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * It is based on the file openbsd-compat/bsd-setres_id.c in OpenSSH 7.9p1,
+ * which is subject to the copyright notice above.  The zsh modifications are
+ * licensed as follows:
+ *
+ * Copyright (c) 2019 Daniel Shahaf
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Daniel Shahaf or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Daniel Shahaf and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Daniel Shahaf and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose.  The software
+ * provided hereunder is on an "as is" basis, and Daniel Shahaf and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "zsh.mdh"
+
+#if defined(ZSH_IMPLEMENT_SETRESGID) || defined(BROKEN_SETRESGID)
+int
+setresgid(gid_t rgid, gid_t egid, gid_t sgid)
+{
+	int ret = 0, saved_errno;
+
+	if (rgid != sgid) {
+		errno = ENOSYS;
+		return -1;
+	}
+#if defined(ZSH_HAVE_NATIVE_SETREGID) && !defined(BROKEN_SETREGID)
+	if (setregid(rgid, egid) < 0) {
+		saved_errno = errno;
+		zwarnnam("setregid", "to gid %L: %e", (long)rgid, errno);
+		errno = saved_errno;
+		ret = -1;
+	}
+#else
+	if (setegid(egid) < 0) {
+		saved_errno = errno;
+		zwarnnam("setegid", "to gid %L: %e", (long)(unsigned int)egid, errno);
+		errno = saved_errno;
+		ret = -1;
+	}
+	if (setgid(rgid) < 0) {
+		saved_errno = errno;
+		zwarnnam("setgid", "to gid %L: %e", (long)rgid, errno);
+		errno = saved_errno;
+		ret = -1;
+	}
+#endif
+	return ret;
+}
+#endif
+
+#if defined(ZSH_IMPLEMENT_SETRESUID) || defined(BROKEN_SETRESUID)
+int
+setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+	int ret = 0, saved_errno;
+
+	if (ruid != suid) {
+		errno = ENOSYS;
+		return -1;
+	}
+#if defined(ZSH_HAVE_NATIVE_SETREUID) && !defined(BROKEN_SETREUID)
+	if (setreuid(ruid, euid) < 0) {
+		saved_errno = errno;
+		zwarnnam("setreuid", "to uid %L: %e", (long)ruid, errno);
+		errno = saved_errno;
+		ret = -1;
+	}
+#else
+
+# ifndef SETEUID_BREAKS_SETUID
+	if (seteuid(euid) < 0) {
+		saved_errno = errno;
+		zwarnnam("seteuid", "to uid %L: %e", (long)euid, errno);
+		errno = saved_errno;
+		ret = -1;
+	}
+# endif
+	if (setuid(ruid) < 0) {
+		saved_errno = errno;
+		zwarnnam("setuid", "to uid %L: %e", (long)ruid, errno);
+		errno = saved_errno;
+		ret = -1;
+	}
+#endif
+	return ret;
+}
+#endif
diff --color -Naur zsh-4.3.6.ori/Src/options.c zsh-4.3.6.new/Src/options.c
--- zsh-4.3.6.ori/Src/options.c	2008-03-06 18:36:50.000000000 +0100
+++ zsh-4.3.6.new/Src/options.c	2022-03-02 16:13:13.430566549 +0100
@@ -34,17 +34,17 @@
 
 /**/
 mod_export int emulation;
- 
+
 /* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */
- 
+
 /**/
 mod_export char opts[OPT_SIZE];
- 
+
 /* Option name hash table */
 
 /**/
 mod_export HashTable optiontab;
- 
+
 /* The canonical option name table */
 
 #define OPT_CSH		EMULATE_CSH
@@ -507,6 +507,7 @@
 bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
 {
     int action, optno, match = 0;
+    int retval = 0;
 
     /* With no arguments or options, display options. */
     if (!*args) {
@@ -534,18 +535,25 @@
 		    inittyptab();
 		    return 1;
 		}
-		if(!(optno = optlookup(*args)))
+        if(!(optno = optlookup(*args))) {
 		    zwarnnam(nam, "no such option: %s", *args);
-		else if(dosetopt(optno, action, 0))
+		    retval |= 1;
+		} else if (dosetopt(optno, action, 0)) {
 		    zwarnnam(nam, "can't change option: %s", *args);
+		    retval |= 1;
+		}
 		break;
 	    } else if(**args == 'm') {
 		match = 1;
 	    } else {
-	    	if (!(optno = optlookupc(**args)))
+	    	if (!(optno = optlookupc(**args))) {
+
 		    zwarnnam(nam, "bad option: -%c", **args);
-		else if(dosetopt(optno, action, 0))
+		    retval |= 1;
+		} else if (dosetopt(optno, action, 0)) {
 		    zwarnnam(nam, "can't change option: -%c", **args);
+		    retval |= 1;
+		}
 	    }
 	}
 	args++;
@@ -555,10 +563,15 @@
     if (!match) {
 	/* Not globbing the arguments -- arguments are simply option names. */
 	while (*args) {
-	    if(!(optno = optlookup(*args++)))
+	    if(!(optno = optlookup(*args++))) {
+
 		zwarnnam(nam, "no such option: %s", args[-1]);
-	    else if(dosetopt(optno, !isun, 0))
+		retval |= 1;
+	    } else if (dosetopt(optno, !isun, 0)) {
 		zwarnnam(nam, "can't change option: %s", args[-1]);
+		retval |= 1;
+
+	    }
 	}
     } else {
 	/* Globbing option (-m) set. */
@@ -581,7 +594,8 @@
 	    tokenize(s);
 	    if (!(pprog = patcompile(s, PAT_STATIC, NULL))) {
 		zwarnnam(nam, "bad pattern: %s", *args);
-		continue;
+		retval |= 1;
+		break;
 	    }
 	    /* Loop over expansions. */
 	    scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS,
@@ -590,7 +604,7 @@
 	}
     }
     inittyptab();
-    return 0;
+    return retval;
 }
 
 /* Identify an option name */
@@ -699,10 +713,99 @@
 	    return -1;
     } else if(optno == PRIVILEGED && !value) {
 	/* unsetting PRIVILEGED causes the shell to make itself unprivileged */
-#ifdef HAVE_SETUID
-	setuid(getuid());
-	setgid(getgid());
-#endif /* HAVE_SETUID */
+
+#if !defined(HAVE_SETRESGID)
+	zwarnnam("unsetopt",
+	    "PRIVILEGED: can't drop privileges; setresgid() and friends not available");
+	return -1;
+#elif !defined(HAVE_SETRESUID)
+	zwarnnam("unsetopt",
+	    "PRIVILEGED: can't drop privileges; setresuid() and friends not available");
+	return -1;
+#else
+	/* If set, return -1 so lastval will be non-zero. */
+	int failed = 0;
+	const int orig_euid = geteuid();
+
+	const int orig_egid = getegid();
+
+	/*
+	 * Set the GID first as if we set the UID to non-privileged it
+	 * might be impossible to restore the GID.
+	 */
+	if (setresgid(getgid(), getgid(), getgid())) {
+	    zwarnnam("unsetopt",
+		"PRIVILEGED: can't drop privileges; failed to change group ID: %e",
+		errno);
+	    return -1;
+	}
+
+# ifdef HAVE_INITGROUPS
+	/* Set the supplementary groups list.
+	 *
+	 * Note that on macOS, FreeBSD, and possibly some other platforms,
+	 * initgroups() resets the EGID to its second argument (see setgroups(2) for
+	 * details). This has the potential to leave the EGID in an unexpected
+	 * state. However, it seems common in other projects that do this dance to
+	 * simply re-use the same GID that's going to become the EGID anyway, in
+	 * which case it doesn't matter. That's what we do here. It's therefore
+	 * possible, in some probably uncommon cases, that the shell ends up not
+	 * having the privileges of the RUID user's primary/passwd group. */
+	if (geteuid() == 0) {
+	    struct passwd *pw = getpwuid(getuid());
+	    if (pw == NULL) {
+		zwarnnam("unsetopt",
+                "can't drop privileges; failed to get user information for uid %L: %e",
+		    (long)getuid(), errno);
+		failed = 1;
+	    /* This may behave strangely in the unlikely event that the same user
+	     * name appears with multiple UIDs in the passwd database */
+	    } else if (initgroups(pw->pw_name, getgid())) {
+		zwarnnam("unsetopt",
+                "can't drop privileges; failed to set supplementary group list: %e",
+                errno);
+		return -1;
+	    }
+
+	} else if (getuid() != 0 &&
+	    (geteuid() != getuid() || orig_egid != getegid())) {
+	    zwarnnam("unsetopt",
+                "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L",
+		(long)geteuid());
+	    failed = 1;
+	}
+# else
+	/* initgroups() isn't in POSIX.  If it's not available on the system,
+	 * we silently skip it. */
+# endif
+
+	/* Set the UID second. */
+	if (setresuid(getuid(), getuid(), getuid())) {
+	    zwarnnam("unsetopt",
+                "PRIVILEGED: can't drop privileges; failed to change user ID: %e",
+                errno);
+	    return -1;
+}
+
+	if (getuid() != 0 && orig_egid != getegid() &&
+		(setgid(orig_egid) != -1 || setegid(orig_egid) != -1)) {
+	    zwarnnam("unsetopt",
+                "PRIVILEGED: can't drop privileges; was able to restore the egid");
+	    return -1;
+	}
+	if (getuid() != 0 && orig_euid != geteuid() &&
+		(setuid(orig_euid) != -1 || seteuid(orig_euid) != -1)) {
+	    zwarnnam("unsetopt",
+                "PRIVILEGED: can't drop privileges; was able to restore the euid");
+	    return -1;
+	}
+
+	if (failed) {
+	    /* A warning message has been printed. */
+	    return -1;
+	}
+#endif /* HAVE_SETRESGID && HAVE_SETRESUID */
+
 #ifdef JOB_CONTROL
     } else if (!force && optno == MONITOR && value) {
 	if (opts[optno] == value)
diff --color -Naur zsh-4.3.6.ori/Src/options.c.orig zsh-4.3.6.new/Src/options.c.orig
--- zsh-4.3.6.ori/Src/options.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ zsh-4.3.6.new/Src/options.c.orig	2008-03-06 18:36:50.000000000 +0100
@@ -0,0 +1,822 @@
+/*
+ * options.c - shell options
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1992-1997 Paul Falstad
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Paul Falstad or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Paul Falstad and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Paul Falstad and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose.  The software
+ * provided hereunder is on an "as is" basis, and Paul Falstad and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "zsh.mdh"
+#include "options.pro"
+
+/* current emulation (used to decide which set of option letters is used) */
+
+/**/
+mod_export int emulation;
+ 
+/* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */
+ 
+/**/
+mod_export char opts[OPT_SIZE];
+ 
+/* Option name hash table */
+
+/**/
+mod_export HashTable optiontab;
+ 
+/* The canonical option name table */
+
+#define OPT_CSH		EMULATE_CSH
+#define OPT_KSH		EMULATE_KSH
+#define OPT_SH		EMULATE_SH
+#define OPT_ZSH		EMULATE_ZSH
+
+#define OPT_ALL		(OPT_CSH|OPT_KSH|OPT_SH|OPT_ZSH)
+#define OPT_BOURNE	(OPT_KSH|OPT_SH)
+#define OPT_BSHELL	(OPT_KSH|OPT_SH|OPT_ZSH)
+#define OPT_NONBOURNE	(OPT_ALL & ~OPT_BOURNE)
+#define OPT_NONZSH	(OPT_ALL & ~OPT_ZSH)
+
+#define OPT_EMULATE	(1<<5)	/* option is relevant to emulation */
+#define OPT_SPECIAL	(1<<6)	/* option should never be set by emulate() */
+#define OPT_ALIAS	(1<<7)	/* option is an alias to an other option */
+
+#define defset(X) (!!((X)->node.flags & emulation))
+
+/*
+ * Note that option names should usually be fewer than 20 characters long
+ * to avoid formatting problems.
+ */
+static struct optname optns[] = {
+{{NULL, "aliases",	      OPT_EMULATE|OPT_ALL},	 ALIASESOPT},
+{{NULL, "allexport",	      OPT_EMULATE},		 ALLEXPORT},
+{{NULL, "alwayslastprompt",   OPT_ALL},			 ALWAYSLASTPROMPT},
+{{NULL, "alwaystoend",	      0},			 ALWAYSTOEND},
+{{NULL, "appendhistory",      OPT_ALL},			 APPENDHISTORY},
+{{NULL, "autocd",	      OPT_EMULATE},		 AUTOCD},
+{{NULL, "autocontinue",	      0},			 AUTOCONTINUE},
+{{NULL, "autolist",	      OPT_ALL},			 AUTOLIST},
+{{NULL, "automenu",	      OPT_ALL},			 AUTOMENU},
+{{NULL, "autonamedirs",	      0},			 AUTONAMEDIRS},
+{{NULL, "autoparamkeys",      OPT_ALL},			 AUTOPARAMKEYS},
+{{NULL, "autoparamslash",     OPT_ALL},			 AUTOPARAMSLASH},
+{{NULL, "autopushd",	      0},			 AUTOPUSHD},
+{{NULL, "autoremoveslash",    OPT_ALL},			 AUTOREMOVESLASH},
+{{NULL, "autoresume",	      0},			 AUTORESUME},
+{{NULL, "badpattern",	      OPT_EMULATE|OPT_NONBOURNE},BADPATTERN},
+{{NULL, "banghist",	      OPT_NONBOURNE},		 BANGHIST},
+{{NULL, "bareglobqual",       OPT_EMULATE|OPT_ZSH},      BAREGLOBQUAL},
+{{NULL, "bashautolist",	      0},                        BASHAUTOLIST},
+{{NULL, "bashrematch",	      0},			 BASHREMATCH},
+{{NULL, "beep",		      OPT_ALL},			 BEEP},
+{{NULL, "bgnice",	      OPT_EMULATE|OPT_NONBOURNE},BGNICE},
+{{NULL, "braceccl",	      OPT_EMULATE},		 BRACECCL},
+{{NULL, "bsdecho",	      OPT_EMULATE|OPT_SH},	 BSDECHO},
+{{NULL, "caseglob",	      OPT_ALL},			 CASEGLOB},
+{{NULL, "casematch",	      OPT_ALL},			 CASEMATCH},
+{{NULL, "cbases",	      0},			 CBASES},
+{{NULL, "cdablevars",	      OPT_EMULATE},		 CDABLEVARS},
+{{NULL, "chasedots",	      OPT_EMULATE},		 CHASEDOTS},
+{{NULL, "chaselinks",	      OPT_EMULATE},		 CHASELINKS},
+{{NULL, "checkjobs",	      OPT_EMULATE|OPT_ZSH},	 CHECKJOBS},
+{{NULL, "clobber",	      OPT_EMULATE|OPT_ALL},	 CLOBBER},
+{{NULL, "completealiases",    0},			 COMPLETEALIASES},
+{{NULL, "completeinword",     0},			 COMPLETEINWORD},
+{{NULL, "correct",	      0},			 CORRECT},
+{{NULL, "correctall",	      0},			 CORRECTALL},
+{{NULL, "cshjunkiehistory",   OPT_EMULATE|OPT_CSH},	 CSHJUNKIEHISTORY},
+{{NULL, "cshjunkieloops",     OPT_EMULATE|OPT_CSH},	 CSHJUNKIELOOPS},
+{{NULL, "cshjunkiequotes",    OPT_EMULATE|OPT_CSH},	 CSHJUNKIEQUOTES},
+{{NULL, "cshnullcmd",	      OPT_EMULATE|OPT_CSH},	 CSHNULLCMD},
+{{NULL, "cshnullglob",	      OPT_EMULATE|OPT_CSH},	 CSHNULLGLOB},
+{{NULL, "debugbeforecmd",     OPT_EMULATE},		 DEBUGBEFORECMD},
+{{NULL, "emacs",	      0},			 EMACSMODE},
+{{NULL, "equals",	      OPT_EMULATE|OPT_ZSH},	 EQUALS},
+{{NULL, "errexit",	      OPT_EMULATE},		 ERREXIT},
+{{NULL, "errreturn",	      OPT_EMULATE},		 ERRRETURN},
+{{NULL, "exec",		      OPT_ALL},			 EXECOPT},
+{{NULL, "extendedglob",	      OPT_EMULATE},		 EXTENDEDGLOB},
+{{NULL, "extendedhistory",    OPT_CSH},			 EXTENDEDHISTORY},
+{{NULL, "evallineno",	      OPT_EMULATE|OPT_ZSH},	 EVALLINENO},
+{{NULL, "flowcontrol",	      OPT_ALL},			 FLOWCONTROL},
+{{NULL, "functionargzero",    OPT_EMULATE|OPT_NONBOURNE},FUNCTIONARGZERO},
+{{NULL, "glob",		      OPT_EMULATE|OPT_ALL},	 GLOBOPT},
+{{NULL, "globalexport",       OPT_EMULATE|OPT_ZSH},	 GLOBALEXPORT},
+{{NULL, "globalrcs",          OPT_ALL},			 GLOBALRCS},
+{{NULL, "globassign",	      OPT_EMULATE|OPT_CSH},	 GLOBASSIGN},
+{{NULL, "globcomplete",	      0},			 GLOBCOMPLETE},
+{{NULL, "globdots",	      OPT_EMULATE},		 GLOBDOTS},
+{{NULL, "globsubst",	      OPT_EMULATE|OPT_NONZSH},	 GLOBSUBST},
+{{NULL, "hashcmds",	      OPT_ALL},			 HASHCMDS},
+{{NULL, "hashdirs",	      OPT_ALL},			 HASHDIRS},
+{{NULL, "hashlistall",	      OPT_ALL},			 HASHLISTALL},
+{{NULL, "histallowclobber",   0},			 HISTALLOWCLOBBER},
+{{NULL, "histbeep",	      OPT_ALL},			 HISTBEEP},
+{{NULL, "histexpiredupsfirst",0},			 HISTEXPIREDUPSFIRST},
+{{NULL, "histfindnodups",     0},			 HISTFINDNODUPS},
+{{NULL, "histignorealldups",  0},			 HISTIGNOREALLDUPS},
+{{NULL, "histignoredups",     0},			 HISTIGNOREDUPS},
+{{NULL, "histignorespace",    0},			 HISTIGNORESPACE},
+{{NULL, "histnofunctions",    0},			 HISTNOFUNCTIONS},
+{{NULL, "histnostore",	      0},			 HISTNOSTORE},
+{{NULL, "histsubstpattern",   OPT_EMULATE},              HISTSUBSTPATTERN},
+{{NULL, "histreduceblanks",   0},			 HISTREDUCEBLANKS},
+{{NULL, "histsavebycopy",     OPT_ALL},			 HISTSAVEBYCOPY},
+{{NULL, "histsavenodups",     0},			 HISTSAVENODUPS},
+{{NULL, "histverify",	      0},			 HISTVERIFY},
+{{NULL, "hup",		      OPT_EMULATE|OPT_ZSH},	 HUP},
+{{NULL, "ignorebraces",	      OPT_EMULATE|OPT_SH},	 IGNOREBRACES},
+{{NULL, "ignoreeof",	      0},			 IGNOREEOF},
+{{NULL, "incappendhistory",   0},			 INCAPPENDHISTORY},
+{{NULL, "interactive",	      OPT_SPECIAL},		 INTERACTIVE},
+{{NULL, "interactivecomments",OPT_BOURNE},		 INTERACTIVECOMMENTS},
+{{NULL, "ksharrays",	      OPT_EMULATE|OPT_BOURNE},	 KSHARRAYS},
+{{NULL, "kshautoload",	      OPT_EMULATE|OPT_BOURNE},	 KSHAUTOLOAD},
+{{NULL, "kshglob",	      OPT_EMULATE|OPT_KSH},	 KSHGLOB},
+{{NULL, "kshoptionprint",     OPT_EMULATE|OPT_KSH},	 KSHOPTIONPRINT},
+{{NULL, "kshtypeset",	      OPT_EMULATE|OPT_KSH},	 KSHTYPESET},
+{{NULL, "kshzerosubscript",   0},			 KSHZEROSUBSCRIPT},
+{{NULL, "listambiguous",      OPT_ALL},			 LISTAMBIGUOUS},
+{{NULL, "listbeep",	      OPT_ALL},			 LISTBEEP},
+{{NULL, "listpacked",	      0},			 LISTPACKED},
+{{NULL, "listrowsfirst",      0},			 LISTROWSFIRST},
+{{NULL, "listtypes",	      OPT_ALL},			 LISTTYPES},
+{{NULL, "localoptions",	      OPT_EMULATE|OPT_KSH},	 LOCALOPTIONS},
+{{NULL, "localtraps",	      OPT_EMULATE|OPT_KSH},	 LOCALTRAPS},
+{{NULL, "login",	      OPT_SPECIAL},		 LOGINSHELL},
+{{NULL, "longlistjobs",	      0},			 LONGLISTJOBS},
+{{NULL, "magicequalsubst",    OPT_EMULATE},		 MAGICEQUALSUBST},
+{{NULL, "mailwarning",	      0},			 MAILWARNING},
+{{NULL, "markdirs",	      0},			 MARKDIRS},
+{{NULL, "menucomplete",	      0},			 MENUCOMPLETE},
+{{NULL, "monitor",	      OPT_SPECIAL},		 MONITOR},
+{{NULL, "multibyte",
+#ifdef MULTIBYTE_SUPPORT
+			      OPT_EMULATE|OPT_ZSH|OPT_CSH|OPT_KSH
+#else
+			      0
+#endif
+			      },			 MULTIBYTE},
+{{NULL, "multios",	      OPT_EMULATE|OPT_ZSH},	 MULTIOS},
+{{NULL, "nomatch",	      OPT_EMULATE|OPT_NONBOURNE},NOMATCH},
+{{NULL, "notify",	      OPT_ZSH},			 NOTIFY},
+{{NULL, "nullglob",	      OPT_EMULATE},		 NULLGLOB},
+{{NULL, "numericglobsort",    OPT_EMULATE},		 NUMERICGLOBSORT},
+{{NULL, "octalzeroes",        OPT_EMULATE|OPT_SH},	 OCTALZEROES},
+{{NULL, "overstrike",	      0},			 OVERSTRIKE},
+{{NULL, "pathdirs",	      OPT_EMULATE},		 PATHDIRS},
+{{NULL, "posixbuiltins",      OPT_EMULATE|OPT_BOURNE},	 POSIXBUILTINS},
+{{NULL, "posixidentifiers",   OPT_EMULATE|OPT_BOURNE},	 POSIXIDENTIFIERS},
+{{NULL, "printeightbit",      0},                        PRINTEIGHTBIT},
+{{NULL, "printexitvalue",     0},			 PRINTEXITVALUE},
+{{NULL, "privileged",	      OPT_SPECIAL},		 PRIVILEGED},
+{{NULL, "promptbang",	      OPT_KSH},			 PROMPTBANG},
+{{NULL, "promptcr",	      OPT_ALL},			 PROMPTCR},
+{{NULL, "promptpercent",      OPT_NONBOURNE},		 PROMPTPERCENT},
+{{NULL, "promptsp",	      OPT_ALL},			 PROMPTSP},
+{{NULL, "promptsubst",	      OPT_KSH},			 PROMPTSUBST},
+{{NULL, "pushdignoredups",    OPT_EMULATE},		 PUSHDIGNOREDUPS},
+{{NULL, "pushdminus",	      OPT_EMULATE},		 PUSHDMINUS},
+{{NULL, "pushdsilent",	      0},			 PUSHDSILENT},
+{{NULL, "pushdtohome",	      OPT_EMULATE},		 PUSHDTOHOME},
+{{NULL, "rcexpandparam",      OPT_EMULATE},		 RCEXPANDPARAM},
+{{NULL, "rcquotes",	      OPT_EMULATE},		 RCQUOTES},
+{{NULL, "rcs",		      OPT_ALL},			 RCS},
+{{NULL, "recexact",	      0},			 RECEXACT},
+{{NULL, "rematchpcre",	      0},			 REMATCHPCRE},
+{{NULL, "restricted",	      OPT_SPECIAL},		 RESTRICTED},
+{{NULL, "rmstarsilent",	      OPT_BOURNE},		 RMSTARSILENT},
+{{NULL, "rmstarwait",	      0},			 RMSTARWAIT},
+{{NULL, "sharehistory",	      OPT_KSH},			 SHAREHISTORY},
+{{NULL, "shfileexpansion",    OPT_EMULATE|OPT_BOURNE},	 SHFILEEXPANSION},
+{{NULL, "shglob",	      OPT_EMULATE|OPT_BOURNE},	 SHGLOB},
+{{NULL, "shinstdin",	      OPT_SPECIAL},		 SHINSTDIN},
+{{NULL, "shnullcmd",          OPT_EMULATE|OPT_BOURNE},	 SHNULLCMD},
+{{NULL, "shoptionletters",    OPT_EMULATE|OPT_BOURNE},	 SHOPTIONLETTERS},
+{{NULL, "shortloops",	      OPT_EMULATE|OPT_NONBOURNE},SHORTLOOPS},
+{{NULL, "shwordsplit",	      OPT_EMULATE|OPT_BOURNE},	 SHWORDSPLIT},
+{{NULL, "singlecommand",      OPT_SPECIAL},		 SINGLECOMMAND},
+{{NULL, "singlelinezle",      OPT_KSH},			 SINGLELINEZLE},
+{{NULL, "sunkeyboardhack",    0},			 SUNKEYBOARDHACK},
+{{NULL, "transientrprompt",   0},			 TRANSIENTRPROMPT},
+{{NULL, "trapsasync",	      0},			 TRAPSASYNC},
+{{NULL, "typesetsilent",      OPT_EMULATE|OPT_BOURNE},	 TYPESETSILENT},
+{{NULL, "unset",	      OPT_EMULATE|OPT_BSHELL},	 UNSET},
+{{NULL, "verbose",	      0},			 VERBOSE},
+{{NULL, "vi",		      0},			 VIMODE},
+{{NULL, "warncreateglobal",   0},			 WARNCREATEGLOBAL},
+{{NULL, "xtrace",	      0},			 XTRACE},
+{{NULL, "zle",		      OPT_SPECIAL},		 USEZLE},
+{{NULL, "braceexpand",	      OPT_ALIAS}, /* ksh/bash */ -IGNOREBRACES},
+{{NULL, "dotglob",	      OPT_ALIAS}, /* bash */	 GLOBDOTS},
+{{NULL, "hashall",	      OPT_ALIAS}, /* bash */	 HASHCMDS},
+{{NULL, "histappend",	      OPT_ALIAS}, /* bash */	 APPENDHISTORY},
+{{NULL, "histexpand",	      OPT_ALIAS}, /* bash */	 BANGHIST},
+{{NULL, "log",		      OPT_ALIAS}, /* ksh */	 -HISTNOFUNCTIONS},
+{{NULL, "mailwarn",	      OPT_ALIAS}, /* bash */	 MAILWARNING},
+{{NULL, "onecmd",	      OPT_ALIAS}, /* bash */	 SINGLECOMMAND},
+{{NULL, "physical",	      OPT_ALIAS}, /* ksh/bash */ CHASELINKS},
+{{NULL, "promptvars",	      OPT_ALIAS}, /* bash */	 PROMPTSUBST},
+{{NULL, "stdin",	      OPT_ALIAS}, /* ksh */	 SHINSTDIN},
+{{NULL, "trackall",	      OPT_ALIAS}, /* ksh */	 HASHCMDS},
+{{NULL, "dvorak",	      0},			 DVORAK},
+{{NULL, NULL, 0}, 0}
+};
+
+/* Option letters */
+
+#define optletters (isset(SHOPTIONLETTERS) ? kshletters : zshletters)
+
+#define FIRST_OPT '0'
+#define LAST_OPT 'y'
+
+static short zshletters[LAST_OPT - FIRST_OPT + 1] = {
+    /* 0 */  CORRECT,
+    /* 1 */  PRINTEXITVALUE,
+    /* 2 */ -BADPATTERN,
+    /* 3 */ -NOMATCH,
+    /* 4 */  GLOBDOTS,
+    /* 5 */  NOTIFY,
+    /* 6 */  BGNICE,
+    /* 7 */  IGNOREEOF,
+    /* 8 */  MARKDIRS,
+    /* 9 */  AUTOLIST,
+    /* : */  0,
+    /* ; */  0,
+    /* < */  0,
+    /* = */  0,
+    /* > */  0,
+    /* ? */  0,
+    /* @ */  0,
+    /* A */  0,			/* use with set for arrays */
+    /* B */ -BEEP,
+    /* C */ -CLOBBER,
+    /* D */  PUSHDTOHOME,
+    /* E */  PUSHDSILENT,
+    /* F */ -GLOBOPT,
+    /* G */  NULLGLOB,
+    /* H */  RMSTARSILENT,
+    /* I */  IGNOREBRACES,
+    /* J */  AUTOCD,
+    /* K */ -BANGHIST,
+    /* L */  SUNKEYBOARDHACK,
+    /* M */  SINGLELINEZLE,
+    /* N */  AUTOPUSHD,
+    /* O */  CORRECTALL,
+    /* P */  RCEXPANDPARAM,
+    /* Q */  PATHDIRS,
+    /* R */  LONGLISTJOBS,
+    /* S */  RECEXACT,
+    /* T */  CDABLEVARS,
+    /* U */  MAILWARNING,
+    /* V */ -PROMPTCR,
+    /* W */  AUTORESUME,
+    /* X */  LISTTYPES,
+    /* Y */  MENUCOMPLETE,
+    /* Z */  USEZLE,
+    /* [ */  0,
+    /* \ */  0,
+    /* ] */  0,
+    /* ^ */  0,
+    /* _ */  0,
+    /* ` */  0,
+    /* a */  ALLEXPORT,
+    /* b */  0,			/* in non-Bourne shells, end of options */
+    /* c */  0,			/* command follows */
+    /* d */ -GLOBALRCS,
+    /* e */  ERREXIT,
+    /* f */ -RCS,
+    /* g */  HISTIGNORESPACE,
+    /* h */  HISTIGNOREDUPS,
+    /* i */  INTERACTIVE,
+    /* j */  0,
+    /* k */  INTERACTIVECOMMENTS,
+    /* l */  LOGINSHELL,
+    /* m */  MONITOR,
+    /* n */ -EXECOPT,
+    /* o */  0,			/* long option name follows */
+    /* p */  PRIVILEGED,
+    /* q */  0,
+    /* r */  RESTRICTED,
+    /* s */  SHINSTDIN,
+    /* t */  SINGLECOMMAND,
+    /* u */ -UNSET,
+    /* v */  VERBOSE,
+    /* w */  CHASELINKS,
+    /* x */  XTRACE,
+    /* y */  SHWORDSPLIT,
+};
+
+static short kshletters[LAST_OPT - FIRST_OPT + 1] = {
+    /* 0 */  0,
+    /* 1 */  0,
+    /* 2 */  0,
+    /* 3 */  0,
+    /* 4 */  0,
+    /* 5 */  0,
+    /* 6 */  0,
+    /* 7 */  0,
+    /* 8 */  0,
+    /* 9 */  0,
+    /* : */  0,
+    /* ; */  0,
+    /* < */  0,
+    /* = */  0,
+    /* > */  0,
+    /* ? */  0,
+    /* @ */  0,
+    /* A */  0,
+    /* B */  0,
+    /* C */ -CLOBBER,
+    /* D */  0,
+    /* E */  0,
+    /* F */  0,
+    /* G */  0,
+    /* H */  0,
+    /* I */  0,
+    /* J */  0,
+    /* K */  0,
+    /* L */  0,
+    /* M */  0,
+    /* N */  0,
+    /* O */  0,
+    /* P */  0,
+    /* Q */  0,
+    /* R */  0,
+    /* S */  0,
+    /* T */  TRAPSASYNC,
+    /* U */  0,
+    /* V */  0,
+    /* W */  0,
+    /* X */  MARKDIRS,
+    /* Y */  0,
+    /* Z */  0,
+    /* [ */  0,
+    /* \ */  0,
+    /* ] */  0,
+    /* ^ */  0,
+    /* _ */  0,
+    /* ` */  0,
+    /* a */  ALLEXPORT,
+    /* b */  NOTIFY,
+    /* c */  0,
+    /* d */  0,
+    /* e */  ERREXIT,
+    /* f */ -GLOBOPT,
+    /* g */  0,
+    /* h */  0,
+    /* i */  INTERACTIVE,
+    /* j */  0,
+    /* k */  0,
+    /* l */  LOGINSHELL,
+    /* m */  MONITOR,
+    /* n */ -EXECOPT,
+    /* o */  0,
+    /* p */  PRIVILEGED,
+    /* q */  0,
+    /* r */  RESTRICTED,
+    /* s */  SHINSTDIN,
+    /* t */  SINGLECOMMAND,
+    /* u */ -UNSET,
+    /* v */  VERBOSE,
+    /* w */  0,
+    /* x */  XTRACE,
+    /* y */  0,
+};
+
+/* Initialisation of the option name hash table */
+
+/**/
+static void
+printoptionnode(HashNode hn, int set)
+{
+    Optname on = (Optname) hn;
+    int optno = on->optno;
+
+    if (optno < 0)
+	optno = -optno;
+    if (isset(KSHOPTIONPRINT)) {
+	if (defset(on))
+	    printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
+	else
+	    printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
+    } else if (set == (isset(optno) ^ defset(on))) {
+	if (set ^ isset(optno))
+	    fputs("no", stdout);
+	puts(on->node.nam);
+    }
+}
+
+/**/
+void
+createoptiontable(void)
+{
+    Optname on;
+
+    optiontab = newhashtable(101, "optiontab", NULL);
+
+    optiontab->hash        = hasher;
+    optiontab->emptytable  = NULL;
+    optiontab->filltable   = NULL;
+    optiontab->cmpnodes    = strcmp;
+    optiontab->addnode     = addhashnode;
+    optiontab->getnode     = gethashnode;
+    optiontab->getnode2    = gethashnode2;
+    optiontab->removenode  = NULL;
+    optiontab->disablenode = disablehashnode;
+    optiontab->enablenode  = enablehashnode;
+    optiontab->freenode    = NULL;
+    optiontab->printnode   = printoptionnode;
+
+    for (on = optns; on->node.nam; on++)
+	optiontab->addnode(optiontab, on->node.nam, on);
+}
+
+/* Setting of default options */
+
+/**/
+static void
+setemulate(HashNode hn, int fully)
+{
+    Optname on = (Optname) hn;
+
+    /* Set options: each non-special option is set according to the *
+     * current emulation mode if either it is considered relevant   *
+     * to emulation or we are doing a full emulation (as indicated  *
+     * by the `fully' parameter).                                   */
+    if (!(on->node.flags & OPT_ALIAS) &&
+	((fully && !(on->node.flags & OPT_SPECIAL)) ||
+	 (on->node.flags & OPT_EMULATE)))
+	opts[on->optno] = defset(on);
+}
+
+/**/
+void
+emulate(const char *zsh_name, int fully)
+{
+    char ch = *zsh_name;
+
+    if (ch == 'r')
+	ch = zsh_name[1];
+
+    /* Work out the new emulation mode */
+    if (ch == 'c')
+	emulation = EMULATE_CSH;
+    else if (ch == 'k')
+	emulation = EMULATE_KSH;
+    else if (ch == 's' || ch == 'b')
+	emulation = EMULATE_SH;
+    else
+	emulation = EMULATE_ZSH;
+
+    scanhashtable(optiontab, 0, 0, 0, setemulate, fully);
+}
+
+/* setopt, unsetopt */
+
+/**/
+static void
+setoption(HashNode hn, int value)
+{
+    dosetopt(((Optname) hn)->optno, value, 0);
+}
+
+/**/
+int
+bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
+{
+    int action, optno, match = 0;
+
+    /* With no arguments or options, display options. */
+    if (!*args) {
+	scanhashtable(optiontab, 1, 0, OPT_ALIAS, optiontab->printnode, !isun);
+	return 0;
+    }
+
+    /* loop through command line options (begins with "-" or "+") */
+    while (*args && (**args == '-' || **args == '+')) {
+	action = (**args == '-') ^ isun;
+	if(!args[0][1])
+	    *args = "--";
+	while (*++*args) {
+	    if(**args == Meta)
+		*++*args ^= 32;
+	    /* The pseudo-option `--' signifies the end of options. */
+	    if (**args == '-') {
+		args++;
+		goto doneoptions;
+	    } else if (**args == 'o') {
+		if (!*++*args)
+		    args++;
+		if (!*args) {
+		    zwarnnam(nam, "string expected after -o");
+		    inittyptab();
+		    return 1;
+		}
+		if(!(optno = optlookup(*args)))
+		    zwarnnam(nam, "no such option: %s", *args);
+		else if(dosetopt(optno, action, 0))
+		    zwarnnam(nam, "can't change option: %s", *args);
+		break;
+	    } else if(**args == 'm') {
+		match = 1;
+	    } else {
+	    	if (!(optno = optlookupc(**args)))
+		    zwarnnam(nam, "bad option: -%c", **args);
+		else if(dosetopt(optno, action, 0))
+		    zwarnnam(nam, "can't change option: -%c", **args);
+	    }
+	}
+	args++;
+    }
+    doneoptions:
+
+    if (!match) {
+	/* Not globbing the arguments -- arguments are simply option names. */
+	while (*args) {
+	    if(!(optno = optlookup(*args++)))
+		zwarnnam(nam, "no such option: %s", args[-1]);
+	    else if(dosetopt(optno, !isun, 0))
+		zwarnnam(nam, "can't change option: %s", args[-1]);
+	}
+    } else {
+	/* Globbing option (-m) set. */
+	while (*args) {
+	    Patprog pprog;
+	    char *s, *t;
+
+	    t = s = dupstring(*args);
+	    while (*t)
+		if (*t == '_')
+		    chuck(t);
+		else {
+		    /* See comment in optlookup() */
+		    if (*t >= 'A' && *t <= 'Z')
+			*t = (*t - 'A') + 'a';
+		    t++;
+		}
+
+	    /* Expand the current arg. */
+	    tokenize(s);
+	    if (!(pprog = patcompile(s, PAT_STATIC, NULL))) {
+		zwarnnam(nam, "bad pattern: %s", *args);
+		continue;
+	    }
+	    /* Loop over expansions. */
+	    scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS,
+			   setoption, !isun);
+	    args++;
+	}
+    }
+    inittyptab();
+    return 0;
+}
+
+/* Identify an option name */
+
+/**/
+mod_export int
+optlookup(char const *name)
+{
+    char *s, *t;
+    Optname n;
+
+    s = t = dupstring(name);
+
+    /* exorcise underscores, and change to lowercase */
+    while (*t)
+	if (*t == '_')
+	    chuck(t);
+	else {
+	    /*
+	     * Some locales (in particular tr_TR.UTF-8) may
+	     * have non-standard mappings of ASCII characters,
+	     * so be careful.  Option names must be ASCII so
+	     * we don't need to be too clever.
+	     */
+	    if (*t >= 'A' && *t <= 'Z')
+		*t = (*t - 'A') + 'a';
+	    t++;
+	}
+
+    /* look up name in the table */
+    if (s[0] == 'n' && s[1] == 'o' &&
+	(n = (Optname) optiontab->getnode(optiontab, s + 2))) {
+	return -n->optno;
+    } else if ((n = (Optname) optiontab->getnode(optiontab, s)))
+	return n->optno;
+    else
+	return OPT_INVALID;
+}
+
+/* Identify an option letter */
+
+/**/
+int
+optlookupc(char c)
+{
+    if(c < FIRST_OPT || c > LAST_OPT)
+	return 0;
+
+    return optletters[c - FIRST_OPT];
+}
+
+/**/
+static void
+restrictparam(char *nam)
+{
+    Param pm = (Param) paramtab->getnode(paramtab, nam);
+
+    if (pm) {
+	pm->node.flags |= PM_SPECIAL | PM_RESTRICTED;
+	return;
+    }
+    createparam(nam, PM_SCALAR | PM_UNSET | PM_SPECIAL | PM_RESTRICTED);
+}
+
+/* list of restricted parameters which are not otherwise special */
+static char *rparams[] = {
+    "SHELL", "HISTFILE", "LD_LIBRARY_PATH", "LD_AOUT_LIBRARY_PATH",
+    "LD_PRELOAD", "LD_AOUT_PRELOAD", NULL
+};
+
+/* Set or unset an option, as a result of user request.  The option *
+ * number may be negative, indicating that the sense is reversed    *
+ * from the usual meaning of the option.                            */
+
+/**/
+mod_export int
+dosetopt(int optno, int value, int force)
+{
+    if(!optno)
+	return -1;
+    if(optno < 0) {
+	optno = -optno;
+	value = !value;
+    }
+    if (optno == RESTRICTED) {
+	if (isset(RESTRICTED))
+	    return value ? 0 : -1;
+	if (value) {
+	    char **s;
+
+	    for (s = rparams; *s; s++)
+		restrictparam(*s);
+	}
+    } else if(!force && optno == EXECOPT && !value && interact) {
+	/* cannot set noexec when interactive */
+	return -1;
+    } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
+	    optno == SINGLECOMMAND)) {
+	if (opts[optno] == value)
+	    return 0;
+	/* it is not permitted to change the value of these options */
+	return -1;
+    } else if(!force && optno == USEZLE && value) {
+	/* we require a terminal in order to use ZLE */
+	if(!interact || SHTTY == -1 || !shout)
+	    return -1;
+    } else if(optno == PRIVILEGED && !value) {
+	/* unsetting PRIVILEGED causes the shell to make itself unprivileged */
+#ifdef HAVE_SETUID
+	setuid(getuid());
+	setgid(getgid());
+#endif /* HAVE_SETUID */
+#ifdef JOB_CONTROL
+    } else if (!force && optno == MONITOR && value) {
+	if (opts[optno] == value)
+	    return 0;
+	if (interact && (SHTTY != -1)) {
+	    origpgrp = GETPGRP();
+	    acquire_pgrp();
+	} else
+	    return -1;
+#else
+    } else if(optno == MONITOR && value) {
+	    return -1;
+#endif /* not JOB_CONTROL */
+#ifdef GETPWNAM_FAKED
+    } else if(optno == CDABLEVARS && value) {
+	    return -1;
+#endif /* GETPWNAM_FAKED */
+    } else if ((optno == EMACSMODE || optno == VIMODE) && value) {
+	(*zlesetkeymapptr)(optno);
+	opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0;
+    }
+    opts[optno] = value;
+    if (optno == BANGHIST || optno == SHINSTDIN)
+	inittyptab();
+    return 0;
+}
+
+/* Function to get value for special parameter `-' */
+
+/**/
+char *
+dashgetfn(UNUSED(Param pm))
+{
+    static char buf[LAST_OPT - FIRST_OPT + 2];
+    char *val = buf;
+    int i;
+
+    for(i = 0; i <= LAST_OPT - FIRST_OPT; i++) {
+	int optno = optletters[i];
+	if(optno && ((optno > 0) ? isset(optno) : unset(-optno)))
+	    *val++ = FIRST_OPT + i;
+    }
+    *val = '\0';
+    return buf;
+}
+
+/* print options for set -o/+o */
+
+/**/
+void
+printoptionstates(int hadplus)
+{
+    scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionnodestate, hadplus);
+}
+
+/**/
+static void
+printoptionnodestate(HashNode hn, int hadplus)
+{
+    Optname on = (Optname) hn;
+    int optno = on->optno;
+
+    if (hadplus) {
+        if (defset(on) != isset(optno))
+	    printf("set -o %s%s\n", defset(on) ? "no" : "", on->node.nam);
+    } else {
+	if (defset(on))
+	    printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
+	else
+	    printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
+    }
+}
+
+/* Print option list for --help */
+
+/**/
+void
+printoptionlist(void)
+{
+    short *lp;
+    char c;
+
+    printf("\nNamed options:\n");
+    scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionlist_printoption, 0);
+    printf("\nOption aliases:\n");
+    scanhashtable(optiontab, 1, OPT_ALIAS, 0, printoptionlist_printoption, 0);
+    printf("\nOption letters:\n");
+    for(lp = optletters, c = FIRST_OPT; c <= LAST_OPT; lp++, c++) {
+	if(!*lp)
+	    continue;
+	printf("  -%c  ", c);
+	printoptionlist_printequiv(*lp);
+    }
+}
+
+/**/
+static void
+printoptionlist_printoption(HashNode hn, UNUSED(int ignored))
+{
+    Optname on = (Optname) hn;
+
+    if(on->node.flags & OPT_ALIAS) {
+	printf("  --%-19s  ", on->node.nam);
+	printoptionlist_printequiv(on->optno);
+    } else
+	printf("  --%s\n", on->node.nam);
+}
+
+/**/
+static void
+printoptionlist_printequiv(int optno)
+{
+    int isneg = optno < 0;
+
+    optno *= (isneg ? -1 : 1);
+    printf("  equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].node.nam);
+}
diff --color -Naur zsh-4.3.6.ori/Src/utils.c.orig zsh-4.3.6.new/Src/utils.c.orig
--- zsh-4.3.6.ori/Src/utils.c.orig	2022-03-02 12:23:48.286656323 +0100
+++ zsh-4.3.6.new/Src/utils.c.orig	1970-01-01 01:00:00.000000000 +0100
@@ -1,5502 +0,0 @@
-/*
- * utils.c - miscellaneous utilities
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose.  The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
-#include "zsh.mdh"
-#include "utils.pro"
-
-/* name of script being sourced */
-
-/**/
-char *scriptname;
-
-#ifdef MULTIBYTE_SUPPORT
-struct widechar_array {
-    wchar_t *chars;
-    size_t len;
-};
-typedef struct widechar_array *Widechar_array;
-
-/*
- * The wordchars variable turned into a wide character array.
- * This is much more convenient for testing.
- */
-struct widechar_array wordchars_wide;
-
-/*
- * The same for the separators (IFS) array.
- */
-struct widechar_array ifs_wide;
-
-/* Function to set one of the above from the multibyte array */
-
-static void
-set_widearray(char *mb_array, Widechar_array wca)
-{
-    if (wca->chars) {
-	free(wca->chars);
-	wca->chars = NULL;
-    }
-    wca->len = 0;
-
-    if (!isset(MULTIBYTE))
-	return;
-
-    if (mb_array) {
-	VARARR(wchar_t, tmpwcs, strlen(mb_array));
-	wchar_t *wcptr = tmpwcs;
-	wint_t wci;
-
-	mb_metacharinit();
-	while (*mb_array) {
-	    int mblen = mb_metacharlenconv(mb_array, &wci);
-
-	    if (!mblen)
-		break;
-	    /* No good unless all characters are convertible */
-	    if (wci == WEOF)
-		return;
-	    *wcptr++ = (wchar_t)wci;
-#ifdef DEBUG
-	    /*
-	     * This generates a warning from the compiler (and is
-	     * indeed useless) if chars are unsigned.  It's
-	     * extreme paranoia anyway.
-	     */
-	    if (wcptr[-1] < 0)
-		fprintf(stderr, "BUG: Bad cast to wchar_t\n");
-#endif
-	    mb_array += mblen;
-	}
-
-	wca->len = wcptr - tmpwcs;
-	wca->chars = (wchar_t *)zalloc(wca->len * sizeof(wchar_t));
-	wmemcpy(wca->chars, tmpwcs, wca->len);
-    }
-}
-#endif
-
-
-/* Print an error */
-
-static void
-zwarning(const char *cmd, const char *fmt, va_list ap)
-{
-    if (isatty(2))
-	trashzleptr();
-
-    if (cmd) {
-	if (unset(SHINSTDIN) || locallevel) {
-	    nicezputs(scriptname ? scriptname : argzero, stderr);
-	    fputc((unsigned char)':', stderr);
-	}
-	nicezputs(cmd, stderr);
-	fputc((unsigned char)':', stderr);
-    } else {
-	/*
-	 * scriptname is set when sourcing scripts, so that we get the
-	 * correct name instead of the generic name of whatever
-	 * program/script is running.  It's also set in shell functions,
-	 * so test locallevel, too.
-	 */
-	nicezputs((isset(SHINSTDIN) && !locallevel) ? "zsh" :
-		  scriptname ? scriptname : argzero, stderr);
-	fputc((unsigned char)':', stderr);
-    }
-
-    zerrmsg(stderr, fmt, ap);
-}
-
-
-/**/
-mod_export void
-zerr(VA_ALIST1(const char *fmt))
-VA_DCL
-{
-    va_list ap;
-    VA_DEF_ARG(const char *fmt);
-
-    if (errflag || noerrs) {
-	if (noerrs < 2)
-	    errflag = 1;
-	return;
-    }
-
-    VA_START(ap, fmt);
-    VA_GET_ARG(ap, fmt, const char *);
-    zwarning(NULL, fmt, ap);
-    va_end(ap);
-    errflag = 1;
-}
-
-/**/
-mod_export void
-zerrnam(VA_ALIST2(const char *cmd, const char *fmt))
-VA_DCL
-{
-    va_list ap;
-    VA_DEF_ARG(const char *cmd);
-    VA_DEF_ARG(const char *fmt);
-
-    if (errflag || noerrs)
-	return;
-
-    VA_START(ap, fmt);
-    VA_GET_ARG(ap, cmd, const char *);
-    VA_GET_ARG(ap, fmt, const char *);
-    zwarning(cmd, fmt, ap);
-    va_end(ap);
-    errflag = 1;
-}
-
-/**/
-mod_export void
-zwarn(VA_ALIST1(const char *fmt))
-VA_DCL
-{
-    va_list ap;
-    VA_DEF_ARG(const char *fmt);
-
-    if (errflag || noerrs)
-	return;
-
-    VA_START(ap, fmt);
-    VA_GET_ARG(ap, fmt, const char *);
-    zwarning(NULL, fmt, ap);
-    va_end(ap);
-}
-
-/**/
-mod_export void
-zwarnnam(VA_ALIST2(const char *cmd, const char *fmt))
-VA_DCL
-{
-    va_list ap;
-    VA_DEF_ARG(const char *cmd);
-    VA_DEF_ARG(const char *fmt);
-
-    if (errflag || noerrs)
-	return;
-
-    VA_START(ap, fmt);
-    VA_GET_ARG(ap, cmd, const char *);
-    VA_GET_ARG(ap, fmt, const char *);
-    zwarning(cmd, fmt, ap);
-    va_end(ap);
-}
-
-
-#ifdef DEBUG
-
-/**/
-mod_export void
-dputs(VA_ALIST1(const char *message))
-VA_DCL
-{
-    char *filename;
-    FILE *file;
-    va_list ap;
-    VA_DEF_ARG(const char *message);
-
-    VA_START(ap, message);
-    VA_GET_ARG(ap, message, const char *);
-    if ((filename = getsparam("ZSH_DEBUG_LOG")) != NULL &&
-	(file = fopen(filename, "a")) != NULL) {
-	zerrmsg(file, message, ap);
-	fclose(file);
-    } else
-	zerrmsg(stderr, message, ap);
-    va_end(ap);
-}
-
-#endif /* DEBUG */
-
-#ifdef __CYGWIN__
-/*
- * This works around an occasional problem with dllwrap on Cygwin, seen
- * on at least two installations.  It fails to find the last symbol
- * exported in alphabetical order (in our case zwarnnam).  Until this is
- * properly categorised and fixed we add a dummy symbol at the end.
- */
-mod_export void
-zz_plural_z_alpha(void)
-{
-}
-#endif
-
-/**/
-void
-zerrmsg(FILE *file, const char *fmt, va_list ap)
-{
-    const char *str;
-    int num;
-#ifdef HAVE_STRERROR_R
-#define ERRBUFSIZE (80)
-    int olderrno;
-    char errbuf[ERRBUFSIZE];
-#endif
-    char *errmsg;
-
-    if ((unset(SHINSTDIN) || locallevel) && lineno)
-	fprintf(file, "%ld: ", (long)lineno);
-    else
-	fputc((unsigned char)' ', file);
-
-    while (*fmt)
-	if (*fmt == '%') {
-	    fmt++;
-	    switch (*fmt++) {
-	    case 's':
-		str = va_arg(ap, const char *);
-		nicezputs(str, file);
-		break;
-	    case 'l': {
-		char *s;
-		str = va_arg(ap, const char *);
-		num = va_arg(ap, int);
-		num = metalen(str, num);
-		s = zhalloc(num + 1);
-		memcpy(s, str, num);
-		s[num] = '\0';
-		nicezputs(s, file);
-		break;
-	    }
-	    case 'd':
-		num = va_arg(ap, int);
-		fprintf(file, "%d", num);
-		break;
-	    case '%':
-		putc('%', file);
-		break;
-	    case 'c':
-		num = va_arg(ap, int);
-#ifdef MULTIBYTE_SUPPORT
-		mb_metacharinit();
-		zputs(wcs_nicechar(num, NULL, NULL), file);
-#else
-		zputs(nicechar(num), file);
-#endif
-		break;
-	    case 'e':
-		/* print the corresponding message for this errno */
-		num = va_arg(ap, int);
-		if (num == EINTR) {
-		    fputs("interrupt\n", file);
-		    errflag = 1;
-		    return;
-		}
-		errmsg = strerror(num);
-		/* If the message is not about I/O problems, it looks better *
-		 * if we uncapitalize the first letter of the message        */
-		if (num == EIO)
-		    fputs(errmsg, file);
-		else {
-		    fputc(tulower(errmsg[0]), file);
-		    fputs(errmsg + 1, file);
-		}
-		break;
-	    }
-	} else {
-	    putc(*fmt == Meta ? *++fmt ^ 32 : *fmt, file);
-	    fmt++;
-	}
-    putc('\n', file);
-    fflush(file);
-}
-
-/* Output a single character, for the termcap routines.     *
- * This is used instead of putchar since it can be a macro. */
-
-/**/
-mod_export int
-putraw(int c)
-{
-    putc(c, stdout);
-    return 0;
-}
-
-/* Output a single character, for the termcap routines. */
-
-/**/
-mod_export int
-putshout(int c)
-{
-    putc(c, shout);
-    return 0;
-}
-
-/*
- * Turn a character into a visible representation thereof.  The visible
- * string is put together in a static buffer, and this function returns
- * a pointer to it.  Printable characters stand for themselves, DEL is
- * represented as "^?", newline and tab are represented as "\n" and
- * "\t", and normal control characters are represented in "^C" form.
- * Characters with bit 7 set, if unprintable, are represented as "\M-"
- * followed by the visible representation of the character with bit 7
- * stripped off.  Tokens are interpreted, rather than being treated as
- * literal characters.
- *
- * Note that the returned string is metafied, so that it must be
- * treated like any other zsh internal string (and not, for example,
- * output directly).
- *
- * This function is used even if MULTIBYTE_SUPPORT is defined: we
- * use it as a fallback in case we couldn't identify a wide character
- * in a multibyte string.
- */
-
-/**/
-mod_export char *
-nicechar(int c)
-{
-    static char buf[6];
-    char *s = buf;
-    c &= 0xff;
-    if (isprint(c))
-	goto done;
-    if (c & 0x80) {
-	if (isset(PRINTEIGHTBIT))
-	    goto done;
-	*s++ = '\\';
-	*s++ = 'M';
-	*s++ = '-';
-	c &= 0x7f;
-	if(isprint(c))
-	    goto done;
-    }
-    if (c == 0x7f) {
-	*s++ = '^';
-	c = '?';
-    } else if (c == '\n') {
-	*s++ = '\\';
-	c = 'n';
-    } else if (c == '\t') {
-	*s++ = '\\';
-	c = 't';
-    } else if (c < 0x20) {
-	*s++ = '^';
-	c += 0x40;
-    }
-    done:
-    /*
-     * The resulting string is still metafied, so check if
-     * we are returning a character in the range that needs metafication.
-     * This can't happen if the character is printed "nicely", so
-     * this results in a maximum of two bytes total (plus the null).
-     */
-    if (imeta(c)) {
-	*s++ = Meta;
-	*s++ = c ^ 32;
-    } else
-	*s++ = c;
-    *s = 0;
-    return buf;
-}
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-static mbstate_t mb_shiftstate;
-
-/*
- * Initialise multibyte state: called before a sequence of
- * wcs_nicechar() or mb_metacharlenconv().
- */
-
-/**/
-mod_export void
-mb_metacharinit(void)
-{
-    memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
-}
-
-/*
- * The number of bytes we need to allocate for a "nice" representation
- * of a multibyte character.
- *
- * We double MB_CUR_MAX to take account of the fact that
- * we may need to metafy.  In fact the representation probably
- * doesn't allow every character to be in the meta range, but
- * we don't need to be too pedantic.
- *
- * The 12 is for the output of a UCS-4 code; we don't actually
- * need this at the same time as MB_CUR_MAX, but again it's
- * not worth calculating more exactly.
- */
-#define NICECHAR_MAX (12 + 2*MB_CUR_MAX)
-/*
- * Input a wide character.  Output a printable representation,
- * which is a metafied multibyte string.   With widthp return
- * the printing width.
- *
- * swide, if non-NULL, is used to help the completion code, which needs
- * to know the printing width of the each part of the representation.
- * *swide is set to the part of the returned string where the wide
- * character starts.  Any string up to that point is ASCII characters,
- * so the width of it is (*swide - <return_value>).  Anything left is
- * a single wide character corresponding to the remaining width.
- * Either the initial ASCII part or the wide character part may be empty
- * (but not both).  (Note the complication that the wide character
- * part may contain metafied characters.)
- *
- * The caller needs to call mb_metacharinit() before the first call, to
- * set up the multibyte shift state for a range of characters.
- */
-
-/**/
-mod_export char *
-wcs_nicechar(wchar_t c, size_t *widthp, char **swidep)
-{
-    static char *buf;
-    static int bufalloc = 0, newalloc;
-    char *s, *mbptr;
-    int ret = 0;
-    VARARR(char, mbstr, MB_CUR_MAX);
-
-    /*
-     * We want buf to persist beyond the return.  MB_CUR_MAX and hence
-     * NICECHAR_MAX may not be constant, so we have to allocate this at
-     * run time.  (We could probably get away with just allocating a
-     * large buffer, in practice.)  For efficiency, only reallocate if
-     * we really need to, since this function will be called frequently.
-     */
-    newalloc = NICECHAR_MAX;
-    if (bufalloc != newalloc)
-    {
-	bufalloc = newalloc;
-	buf = (char *)zrealloc(buf, bufalloc);
-    }
-
-    s = buf;
-    if (!iswprint(c) && (c < 0x80 || !isset(PRINTEIGHTBIT))) {
-	if (c == 0x7f) {
-	    *s++ = '^';
-	    c = '?';
-	} else if (c == L'\n') {
-	    *s++ = '\\';
-	    c = 'n';
-	} else if (c == L'\t') {
-	    *s++ = '\\';
-	    c = 't';
-	} else if (c < 0x20) {
-	    *s++ = '^';
-	    c += 0x40;
-	} else if (c >= 0x80) {
-	    ret = -1;
-	}
-    }
-
-    if (ret != -1)
-	ret = wcrtomb(mbstr, c, &mb_shiftstate);
-
-    if (ret == -1) {
-	memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
-	/*
-	 * Can't or don't want to convert character: use UCS-2 or
-	 * UCS-4 code in print escape format.
-	 *
-	 * This comparison fails and generates a compiler warning
-	 * if wchar_t is 16 bits, but the code is still correct.
-	 */
-	if (c >=  0x10000) {
-	    sprintf(buf, "\\U%.8x", (unsigned int)c);
-	    if (widthp)
-		*widthp = 10;
-	} else if (c >= 0x100) {
-	    sprintf(buf, "\\u%.4x", (unsigned int)c);
-	    if (widthp)
-		*widthp = 6;
-	} else {
-	    strcpy(buf, nicechar((int)c));
-	    /*
-	     * There may be metafied characters from nicechar(),
-	     * so compute width and end position independently.
-	     */
-	    if (widthp)
-		*widthp = ztrlen(buf);
-	    if (swidep)
-	      *swidep = buf + strlen(buf);
-	    return buf;
-	}
-	if (swidep)
-	    *swidep = buf + *widthp;
-	return buf;
-    }
-
-    if (widthp) {
-	int wcw = wcwidth(c);
-	*widthp = (s - buf);
-	if (wcw >= 0)
-	    *widthp += wcw;
-	else
-	    (*widthp)++;
-    }
-    if (swidep)
-	*swidep = s;
-    for (mbptr = mbstr; ret; s++, mbptr++, ret--) {
-	DPUTS(s >= buf + NICECHAR_MAX,
-	      "BUG: buffer too small in wcs_nicechar");
-	if (imeta(*mbptr)) {
-	    *s++ = Meta;
-	    DPUTS(s >= buf + NICECHAR_MAX,
-		  "BUG: buffer too small for metafied char in wcs_nicechar");
-	    *s = *mbptr ^ 32;
-	} else {
-	    *s = *mbptr;
-	}
-    }
-    *s = 0;
-    return buf;
-}
-
-/**/
-mod_export int
-zwcwidth(wint_t wc)
-{
-    int wcw;
-    /* assume a single-byte character if not valid */
-    if (wc == WEOF || unset(MULTIBYTE))
-	return 1;
-    wcw = wcwidth(wc);
-    /* if not printable, assume width 1 */
-    if (wcw < 0)
-	return 1;
-    return wcw;
-}
-
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/* get a symlink-free pathname for s relative to PWD */
-
-/**/
-char *
-findpwd(char *s)
-{
-    char *t;
-
-    if (*s == '/')
-	return xsymlink(s);
-    s = tricat((pwd[1]) ? pwd : "", "/", s);
-    t = xsymlink(s);
-    zsfree(s);
-    return t;
-}
-
-/* Check whether a string contains the *
- * name of the present directory.      */
-
-/**/
-int
-ispwd(char *s)
-{
-    struct stat sbuf, tbuf;
-
-    if (stat(unmeta(s), &sbuf) == 0 && stat(".", &tbuf) == 0)
-	if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino)
-	    return 1;
-    return 0;
-}
-
-static char xbuf[PATH_MAX*2];
-
-/**/
-static char **
-slashsplit(char *s)
-{
-    char *t, **r, **q;
-    int t0;
-
-    if (!*s)
-	return (char **) zshcalloc(sizeof(char **));
-
-    for (t = s, t0 = 0; *t; t++)
-	if (*t == '/')
-	    t0++;
-    q = r = (char **) zalloc(sizeof(char **) * (t0 + 2));
-
-    while ((t = strchr(s, '/'))) {
-	*q++ = ztrduppfx(s, t - s);
-	while (*t == '/')
-	    t++;
-	if (!*t) {
-	    *q = NULL;
-	    return r;
-	}
-	s = t;
-    }
-    *q++ = ztrdup(s);
-    *q = NULL;
-    return r;
-}
-
-/* expands symlinks and .. or . expressions */
-/* if flag = 0, only expand .. and . expressions */
-
-/**/
-static int
-xsymlinks(char *s)
-{
-    char **pp, **opp;
-    char xbuf2[PATH_MAX*2], xbuf3[PATH_MAX*2];
-    int t0, ret = 0;
-
-    opp = pp = slashsplit(s);
-    for (; *pp; pp++) {
-	if (!strcmp(*pp, ".")) {
-	    zsfree(*pp);
-	    continue;
-	}
-	if (!strcmp(*pp, "..")) {
-	    char *p;
-
-	    zsfree(*pp);
-	    if (!strcmp(xbuf, "/"))
-		continue;
-	    p = xbuf + strlen(xbuf);
-	    while (*--p != '/');
-	    *p = '\0';
-	    continue;
-	}
-	sprintf(xbuf2, "%s/%s", xbuf, *pp);
-	t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX);
-	if (t0 == -1) {
-	    strcat(xbuf, "/");
-	    strcat(xbuf, *pp);
-	    zsfree(*pp);
-	} else {
-	    ret = 1;
-	    metafy(xbuf3, t0, META_NOALLOC);
-	    if (*xbuf3 == '/') {
-		strcpy(xbuf, "");
-		xsymlinks(xbuf3 + 1);
-	    } else
-		xsymlinks(xbuf3);
-	    zsfree(*pp);
-	}
-    }
-    free(opp);
-    return ret;
-}
-
-/*
- * expand symlinks in s, and remove other weird things:
- * note that this always expands symlinks.
- */
-
-/**/
-char *
-xsymlink(char *s)
-{
-    if (*s != '/')
-	return NULL;
-    *xbuf = '\0';
-    xsymlinks(s + 1);
-    if (!*xbuf)
-	return ztrdup("/");
-    return ztrdup(xbuf);
-}
-
-/**/
-void
-print_if_link(char *s)
-{
-    if (*s == '/') {
-	*xbuf = '\0';
-	if (xsymlinks(s + 1))
-	    printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
-    }
-}
-
-/* print a directory */
-
-/**/
-void
-fprintdir(char *s, FILE *f)
-{
-    Nameddir d = finddir(s);
-
-    if (!d)
-	fputs(unmeta(s), f);
-    else {
-	putc('~', f);
-	fputs(unmeta(d->node.nam), f);
-	fputs(unmeta(s + strlen(d->dir)), f);
-    }
-}
-
-/* Returns the current username.  It caches the username *
- * and uid to try to avoid requerying the password files *
- * or NIS/NIS+ database.                                 */
-
-/**/
-uid_t cached_uid;
-/**/
-char *cached_username;
-
-/**/
-char *
-get_username(void)
-{
-#ifdef HAVE_GETPWUID
-    struct passwd *pswd;
-    uid_t current_uid;
-
-    current_uid = getuid();
-    if (current_uid != cached_uid) {
-	cached_uid = current_uid;
-	zsfree(cached_username);
-	if ((pswd = getpwuid(current_uid)))
-	    cached_username = ztrdup(pswd->pw_name);
-	else
-	    cached_username = ztrdup("");
-    }
-#else /* !HAVE_GETPWUID */
-    cached_uid = getuid();
-#endif /* !HAVE_GETPWUID */
-    return cached_username;
-}
-
-/* static variables needed by finddir(). */
-
-static char *finddir_full;
-static Nameddir finddir_last;
-static int finddir_best;
-
-/* ScanFunc used by finddir(). */
-
-/**/
-static void
-finddir_scan(HashNode hn, UNUSED(int flags))
-{
-    Nameddir nd = (Nameddir) hn;
-
-    if(nd->diff > finddir_best && !dircmp(nd->dir, finddir_full)
-       && !(nd->node.flags & ND_NOABBREV)) {
-	finddir_last=nd;
-	finddir_best=nd->diff;
-    }
-}
-
-/* See if a path has a named directory as its prefix. *
- * If passed a NULL argument, it will invalidate any  *
- * cached information.                                */
-
-/**/
-Nameddir
-finddir(char *s)
-{
-    static struct nameddir homenode = { {NULL, "", 0}, NULL, 0 };
-    static int ffsz;
-
-    /* Invalidate directory cache if argument is NULL.  This is called *
-     * whenever a node is added to or removed from the hash table, and *
-     * whenever the value of $HOME changes.  (On startup, too.)        */
-    if (!s) {
-	homenode.dir = home ? home : "";
-	homenode.diff = home ? strlen(home) : 0;
-	if(homenode.diff==1)
-	    homenode.diff = 0;
-	if(!finddir_full)
-	    finddir_full = zalloc(ffsz = PATH_MAX);
-	finddir_full[0] = 0;
-	return finddir_last = NULL;
-    }
-
-    if(!strcmp(s, finddir_full) && *finddir_full)
-	return finddir_last;
-
-    if ((int)strlen(s) >= ffsz) {
-	free(finddir_full);
-	finddir_full = zalloc(ffsz = strlen(s) * 2);
-    }
-    strcpy(finddir_full, s);
-    finddir_best=0;
-    finddir_last=NULL;
-    finddir_scan(&homenode.node, 0);
-    scanhashtable(nameddirtab, 0, 0, 0, finddir_scan, 0);
-    return finddir_last;
-}
-
-/* add a named directory */
-
-/**/
-mod_export void
-adduserdir(char *s, char *t, int flags, int always)
-{
-    Nameddir nd;
-    char *eptr;
-
-    /* We don't maintain a hash table in non-interactive shells. */
-    if (!interact)
-	return;
-
-    /* The ND_USERNAME flag means that this possible hash table *
-     * entry is derived from a passwd entry.  Such entries are  *
-     * subordinate to explicitly generated entries.             */
-    if ((flags & ND_USERNAME) && nameddirtab->getnode2(nameddirtab, s))
-	return;
-
-    /* Normal parameter assignments generate calls to this function, *
-     * with always==0.  Unless the AUTO_NAME_DIRS option is set, we  *
-     * don't let such assignments actually create directory names.   *
-     * Instead, a reference to the parameter as a directory name can *
-     * cause the actual creation of the hash table entry.            */
-    if (!always && unset(AUTONAMEDIRS) &&
-	    !nameddirtab->getnode2(nameddirtab, s))
-	return;
-
-    if (!t || *t != '/' || strlen(t) >= PATH_MAX) {
-	/* We can't use this value as a directory, so simply remove *
-	 * the corresponding entry in the hash table, if any.       */
-	HashNode hn = nameddirtab->removenode(nameddirtab, s);
-
-	if(hn)
-	    nameddirtab->freenode(hn);
-	return;
-    }
-
-    /* add the name */
-    nd = (Nameddir) zshcalloc(sizeof *nd);
-    nd->node.flags = flags;
-    eptr = t + strlen(t);
-    while (eptr > t && eptr[-1] == '/')
-	eptr--;
-    if (eptr == t) {
-	/*
-	 * Don't abbreviate multiple slashes at the start of a
-	 * named directory, since these are sometimes used for
-	 * special purposes.
-	 */
-	nd->dir = ztrdup(t);
-    } else
-	nd->dir = ztrduppfx(t, eptr - t);
-    /* The variables PWD and OLDPWD are not to be displayed as ~PWD etc. */
-    if (!strcmp(s, "PWD") || !strcmp(s, "OLDPWD"))
-	nd->node.flags |= ND_NOABBREV;
-    nameddirtab->addnode(nameddirtab, ztrdup(s), nd);
-}
-
-/* Get a named directory: this function can cause a directory name *
- * to be added to the hash table, if it isn't there already.       */
-
-/**/
-char *
-getnameddir(char *name)
-{
-    Param pm;
-    char *str;
-    Nameddir nd;
-
-    /* Check if it is already in the named directory table */
-    if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)))
-	return dupstring(nd->dir);
-
-    /* Check if there is a scalar parameter with this name whose value *
-     * begins with a `/'.  If there is, add it to the hash table and   *
-     * return the new value.                                           */
-    if ((pm = (Param) paramtab->getnode(paramtab, name)) &&
-	    (PM_TYPE(pm->node.flags) == PM_SCALAR) &&
-	    (str = getsparam(name)) && *str == '/') {
-	pm->node.flags |= PM_NAMEDDIR;
-	adduserdir(name, str, 0, 1);
-	return str;
-    }
-
-#ifdef HAVE_GETPWNAM
-    {
-	/* Retrieve an entry from the password table/database for this user. */
-	struct passwd *pw;
-	if ((pw = getpwnam(name))) {
-	    char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir)
-		: ztrdup(pw->pw_dir);
-	    adduserdir(name, dir, ND_USERNAME, 1);
-	    str = dupstring(dir);
-	    zsfree(dir);
-	    return str;
-	}
-    }
-#endif /* HAVE_GETPWNAM */
-
-    /* There are no more possible sources of directory names, so give up. */
-    return NULL;
-}
-
-/**/
-static int
-dircmp(char *s, char *t)
-{
-    if (s) {
-	for (; *s == *t; s++, t++)
-	    if (!*s)
-		return 0;
-	if (!*s && *t == '/')
-	    return 0;
-    }
-    return 1;
-}
-
-/*
- * Extra functions to call before displaying the prompt.
- * The data is a Prepromptfn.
- */
-
-static LinkList prepromptfns;
-
-/* Add a function to the list of pre-prompt functions. */
-
-/**/
-mod_export void
-addprepromptfn(voidvoidfnptr_t func)
-{
-    Prepromptfn ppdat = (Prepromptfn)zalloc(sizeof(struct prepromptfn));
-    ppdat->func = func;
-    if (!prepromptfns)
-	prepromptfns = znewlinklist();
-    zaddlinknode(prepromptfns, ppdat);
-}
-
-/* Remove a function from the list of pre-prompt functions. */
-
-/**/
-mod_export void
-delprepromptfn(voidvoidfnptr_t func)
-{
-    LinkNode ln;
-
-    for (ln = firstnode(prepromptfns); ln; ln = nextnode(ln)) {
-	Prepromptfn ppdat = (Prepromptfn)getdata(ln);
-	if (ppdat->func == func) {
-	    (void)remnode(prepromptfns, ln);
-	    zfree(ppdat, sizeof(struct prepromptfn));
-	    return;
-	}
-    }
-#ifdef DEBUG
-    dputs("BUG: failed to delete node from prepromptfns");
-#endif
-}
-
-/*
- * Functions to call at a particular time even if not at
- * the prompt.  This is handled by zle.  The data is a
- * Timedfn.  The functions must be in time order, but this
- * is enforced by addtimedfn().
- *
- * Note on debugging:  the code in sched.c currently assumes it's
- * the only user of timedfns for the purposes of checking whether
- * there's a function on the list.  If this becomes no longer the case,
- * the DPUTS() tests in sched.c need rewriting.
- */
-
-/**/
-mod_export LinkList timedfns;
-
-/* Add a function to the list of timed functions. */
-
-/**/
-mod_export void
-addtimedfn(voidvoidfnptr_t func, time_t when)
-{
-    Timedfn tfdat = (Timedfn)zalloc(sizeof(struct timedfn));
-    tfdat->func = func;
-    tfdat->when = when;
-
-    if (!timedfns) {
-	timedfns = znewlinklist();
-	zaddlinknode(timedfns, tfdat);
-    } else {
-	LinkNode ln = firstnode(timedfns);
-
-	/*
-	 * Insert the new element in the linked list.  We do
-	 * rather too much work here since the standard
-	 * functions insert after a given node, whereas we
-	 * want to insert the new data before the first element
-	 * with a greater time.
-	 *
-	 * In practice, the only use of timed functions is
-	 * sched, which only adds the one function; so this
-	 * whole branch isn't used beyond the following block.
-	 */
-	if (!ln) {
-	    zaddlinknode(timedfns, tfdat);
-	    return;
-	}
-	for (;;) {
-	    Timedfn tfdat2;
-	    LinkNode next = nextnode(ln);
-	    if (!next) {
-		zaddlinknode(timedfns, tfdat);
-		return;
-	    }
-	    tfdat2 = (Timedfn)getdata(next);
-	    if (when < tfdat2->when) {
-		zinsertlinknode(timedfns, ln, tfdat);
-		return;
-	    }
-	    ln = next;
-	}
-    }
-}
-
-/*
- * Delete a function from the list of timed functions.
- * Note that if the function apperas multiple times only
- * the first occurrence will be removed.
- *
- * Note also that when zle calls the function it does *not*
- * automatically delete the entry from the list.  That must
- * be done by the function called.  This is recommended as otherwise
- * the function will keep being called immediately.  (It just so
- * happens this "feature" fits in well with the only current use
- * of timed functions.)
- */
-
-/**/
-mod_export void
-deltimedfn(voidvoidfnptr_t func)
-{
-    LinkNode ln;
-
-    for (ln = firstnode(timedfns); ln; ln = nextnode(ln)) {
-	Timedfn ppdat = (Timedfn)getdata(ln);
-	if (ppdat->func == func) {
-	    (void)remnode(timedfns, ln);
-	    zfree(ppdat, sizeof(struct timedfn));
-	    return;
-	}
-    }
-#ifdef DEBUG
-    dputs("BUG: failed to delete node from timedfns");
-#endif
-}
-
-/* the last time we checked mail */
-
-/**/
-time_t lastmailcheck;
-
-/* the last time we checked the people in the WATCH variable */
-
-/**/
-time_t lastwatch;
-
-/*
- * Call a function given by "name" with optional arguments
- * "lnklist".  If "arrayp" is not zero, we also look through
- * the array "name"_functions and execute functions found there.
- */
-
-/**/
-mod_export int
-callhookfunc(char *name, LinkList lnklst, int arrayp)
-{
-    Eprog prog;
-	/*
-	 * Save stopmsg, since user doesn't get a chance to respond
-	 * to a list of jobs generated in a hook.
-	 */
-    int osc = sfcontext, osm = stopmsg, stat = 1;
-
-    sfcontext = SFC_HOOK;
-
-    if ((prog = getshfunc(name)) != &dummy_eprog) {
-	doshfunc(name, prog, lnklst, 0, 1);
-	stat = 0;
-    }
-
-    if (arrayp) {
-	char **arrptr;
-	int namlen = strlen(name);
-#define HOOK_SUFFIX	"_functions"
-#define HOOK_SUFFIX_LEN	11	/* including NUL byte */
-	VARARR(char, arrnam, namlen + HOOK_SUFFIX_LEN);
-	memcpy(arrnam, name, namlen);
-	memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN);
-
-	if ((arrptr = getaparam(arrnam))) {
-	    for (; *arrptr; arrptr++) {
-		if ((prog = getshfunc(*arrptr)) != &dummy_eprog) {
-		    doshfunc(arrnam, prog, lnklst, 0, 1);
-		    stat = 0;
-		}
-	    }
-	}
-    }
-
-    sfcontext = osc;
-    stopmsg = osm;
-
-    return stat;
-}
-
-/* do pre-prompt stuff */
-
-/**/
-void
-preprompt(void)
-{
-    static time_t lastperiodic;
-    LinkNode ln;
-    int period = getiparam("PERIOD");
-    int mailcheck = getiparam("MAILCHECK");
-
-    if (isset(PROMPTSP) && isset(PROMPTCR) && !use_exit_printed && shout) {
-	/* The PROMPT_SP heuristic will move the prompt down to a new line
-	 * if there was any dangling output on the line (assuming the terminal
-	 * has automatic margins, but we try even if hasam isn't set).
-	 * Unfortunately it interacts badly with ZLE displaying message
-	 * when ^D has been pressed. So just disable PROMPT_SP logic in
-	 * this case */
-	char *str;
-	int percents = opts[PROMPTPERCENT];
-	opts[PROMPTPERCENT] = 1;
-	str = promptexpand("%B%S%#%s%b", 0, NULL, NULL);
-	opts[PROMPTPERCENT] = percents;
-	fprintf(shout, "%s%*s\r", str, (int)columns - 1 - !hasxn, "");
-	free(str);
-    }
-
-    /* If NOTIFY is not set, then check for completed *
-     * jobs before we print the prompt.               */
-    if (unset(NOTIFY))
-	scanjobs();
-    if (errflag)
-	return;
-
-    /* If a shell function named "precmd" exists, *
-     * then execute it.                           */
-    callhookfunc("precmd", NULL, 1);
-    if (errflag)
-	return;
-
-    /* If 1) the parameter PERIOD exists, 2) a hook function for    *
-     * "periodic" exists, 3) it's been greater than PERIOD since we *
-     * executed any such hook, then execute it now.                 */
-    if (period && (time(NULL) > lastperiodic + period) &&
-	!callhookfunc("periodic", NULL, 1))
-	lastperiodic = time(NULL);
-    if (errflag)
-	return;
-
-    /* If WATCH is set, then check for the *
-     * specified login/logout events.      */
-    if (watch) {
-	if ((int) difftime(time(NULL), lastwatch) > getiparam("LOGCHECK")) {
-	    dowatch();
-	    lastwatch = time(NULL);
-	}
-    }
-    if (errflag)
-	return;
-
-    /* Check mail */
-    if (mailcheck && (int) difftime(time(NULL), lastmailcheck) > mailcheck) {
-	char *mailfile;
-
-	if (mailpath && *mailpath && **mailpath)
-	    checkmailpath(mailpath);
-	else {
-	    queue_signals();
-	    if ((mailfile = getsparam("MAIL")) && *mailfile) {
-		char *x[2];
-
-		x[0] = mailfile;
-		x[1] = NULL;
-		checkmailpath(x);
-	    }
-	    unqueue_signals();
-	}
-	lastmailcheck = time(NULL);
-    }
-
-    if (prepromptfns) {
-	for(ln = firstnode(prepromptfns); ln; ln = nextnode(ln)) {
-	    Prepromptfn ppnode = (Prepromptfn)getdata(ln);
-	    ppnode->func();
-	}
-    }
-}
-
-/**/
-static void
-checkmailpath(char **s)
-{
-    struct stat st;
-    char *v, *u, c;
-
-    while (*s) {
-	for (v = *s; *v && *v != '?'; v++);
-	c = *v;
-	*v = '\0';
-	if (c != '?')
-	    u = NULL;
-	else
-	    u = v + 1;
-	if (**s == 0) {
-	    *v = c;
-	    zerr("empty MAILPATH component: %s", *s);
-	} else if (mailstat(unmeta(*s), &st) == -1) {
-	    if (errno != ENOENT)
-		zerr("%e: %s", errno, *s);
-	} else if (S_ISDIR(st.st_mode)) {
-	    LinkList l;
-	    DIR *lock = opendir(unmeta(*s));
-	    char buf[PATH_MAX * 2], **arr, **ap;
-	    int ct = 1;
-
-	    if (lock) {
-		char *fn;
-
-		pushheap();
-		l = newlinklist();
-		while ((fn = zreaddir(lock, 1)) && !errflag) {
-		    if (u)
-			sprintf(buf, "%s/%s?%s", *s, fn, u);
-		    else
-			sprintf(buf, "%s/%s", *s, fn);
-		    addlinknode(l, dupstring(buf));
-		    ct++;
-		}
-		closedir(lock);
-		ap = arr = (char **) zhalloc(ct * sizeof(char *));
-
-		while ((*ap++ = (char *)ugetnode(l)));
-		checkmailpath(arr);
-		popheap();
-	    }
-	} else if (shout) {
-	    if (st.st_size && st.st_atime <= st.st_mtime &&
-		st.st_mtime > lastmailcheck) {
-		if (!u) {
-		    fprintf(shout, "You have new mail.\n");
-		    fflush(shout);
-		} else {
-		    VARARR(char, usav, underscoreused);
-
-		    memcpy(usav, underscore, underscoreused);
-
-		    setunderscore(*s);
-
-		    u = dupstring(u);
-		    if (! parsestr(u)) {
-			singsub(&u);
-			zputs(u, shout);
-			fputc('\n', shout);
-			fflush(shout);
-		    }
-		    setunderscore(usav);
-		}
-	    }
-	    if (isset(MAILWARNING) && st.st_atime > st.st_mtime &&
-		st.st_atime > lastmailcheck && st.st_size) {
-		fprintf(shout, "The mail in %s has been read.\n", unmeta(*s));
-		fflush(shout);
-	    }
-	}
-	*v = c;
-	s++;
-    }
-}
-
-/* This prints the XTRACE prompt. */
-
-/**/
-FILE *xtrerr = 0;
-
-/**/
-void
-printprompt4(void)
-{
-    if (!xtrerr)
-	xtrerr = stderr;
-    if (prompt4) {
-	int l, t = opts[XTRACE];
-	char *s = dupstring(prompt4);
-
-	opts[XTRACE] = 0;
-	unmetafy(s, &l);
-	s = unmetafy(promptexpand(metafy(s, l, META_NOALLOC), 0, NULL, NULL), &l);
-	opts[XTRACE] = t;
-
-	fprintf(xtrerr, "%s", s);
-	free(s);
-    }
-}
-
-/**/
-mod_export void
-freestr(void *a)
-{
-    zsfree(a);
-}
-
-/**/
-mod_export void
-gettyinfo(struct ttyinfo *ti)
-{
-    if (SHTTY != -1) {
-#ifdef HAVE_TERMIOS_H
-# ifdef HAVE_TCGETATTR
-	if (tcgetattr(SHTTY, &ti->tio) == -1)
-# else
-	if (ioctl(SHTTY, TCGETS, &ti->tio) == -1)
-# endif
-	    zerr("bad tcgets: %e", errno);
-#else
-# ifdef HAVE_TERMIO_H
-	ioctl(SHTTY, TCGETA, &ti->tio);
-# else
-	ioctl(SHTTY, TIOCGETP, &ti->sgttyb);
-	ioctl(SHTTY, TIOCLGET, &ti->lmodes);
-	ioctl(SHTTY, TIOCGETC, &ti->tchars);
-	ioctl(SHTTY, TIOCGLTC, &ti->ltchars);
-# endif
-#endif
-    }
-}
-
-/**/
-mod_export void
-settyinfo(struct ttyinfo *ti)
-{
-    if (SHTTY != -1) {
-#ifdef HAVE_TERMIOS_H
-# ifdef HAVE_TCGETATTR
-#  ifndef TCSADRAIN
-#   define TCSADRAIN 1	/* XXX Princeton's include files are screwed up */
-#  endif
-	tcsetattr(SHTTY, TCSADRAIN, &ti->tio);
-    /* if (tcsetattr(SHTTY, TCSADRAIN, &ti->tio) == -1) */
-# else
-	ioctl(SHTTY, TCSETS, &ti->tio);
-    /* if (ioctl(SHTTY, TCSETS, &ti->tio) == -1) */
-# endif
-	/*	zerr("settyinfo: %e",errno)*/ ;
-#else
-# ifdef HAVE_TERMIO_H
-	ioctl(SHTTY, TCSETA, &ti->tio);
-# else
-	ioctl(SHTTY, TIOCSETN, &ti->sgttyb);
-	ioctl(SHTTY, TIOCLSET, &ti->lmodes);
-	ioctl(SHTTY, TIOCSETC, &ti->tchars);
-	ioctl(SHTTY, TIOCSLTC, &ti->ltchars);
-# endif
-#endif
-    }
-}
-
-/* the default tty state */
-
-/**/
-mod_export struct ttyinfo shttyinfo;
-
-/* != 0 if we need to call resetvideo() */
-
-/**/
-mod_export int resetneeded;
-
-#ifdef TIOCGWINSZ
-/* window size changed */
-
-/**/
-mod_export int winchanged;
-#endif
-
-static int
-adjustlines(int signalled)
-{
-    int oldlines = lines;
-
-#ifdef TIOCGWINSZ
-    if (signalled || lines <= 0)
-	lines = shttyinfo.winsize.ws_row;
-    else
-	shttyinfo.winsize.ws_row = lines;
-#endif /* TIOCGWINSZ */
-    if (lines <= 0) {
-	DPUTS(signalled, "BUG: Impossible TIOCGWINSZ rows");
-	lines = tclines > 0 ? tclines : 24;
-    }
-
-    if (lines > 2)
-	termflags &= ~TERM_SHORT;
-    else
-	termflags |= TERM_SHORT;
-
-    return (lines != oldlines);
-}
-
-static int
-adjustcolumns(int signalled)
-{
-    int oldcolumns = columns;
-
-#ifdef TIOCGWINSZ
-    if (signalled || columns <= 0)
-	columns = shttyinfo.winsize.ws_col;
-    else
-	shttyinfo.winsize.ws_col = columns;
-#endif /* TIOCGWINSZ */
-    if (columns <= 0) {
-	DPUTS(signalled, "BUG: Impossible TIOCGWINSZ cols");
-	columns = tccolumns > 0 ? tccolumns : 80;
-    }
-
-    if (columns > 2)
-	termflags &= ~TERM_NARROW;
-    else
-	termflags |= TERM_NARROW;
-
-    return (columns != oldcolumns);
-}
-
-/* check the size of the window and adjust if necessary. *
- * The value of from:					 *
- *   0: called from update_job or setupvals		 *
- *   1: called from the SIGWINCH handler		 *
- *   2: called from the LINES parameter callback	 *
- *   3: called from the COLUMNS parameter callback	 */
-
-/**/
-void
-adjustwinsize(int from)
-{
-    static int getwinsz = 1;
-    int ttyrows = shttyinfo.winsize.ws_row;
-    int ttycols = shttyinfo.winsize.ws_col;
-    int resetzle = 0;
-
-    if (getwinsz || from == 1) {
-#ifdef TIOCGWINSZ
-	if (SHTTY == -1)
-	    return;
-	if (ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize) == 0) {
-	    resetzle = (ttyrows != shttyinfo.winsize.ws_row ||
-			ttycols != shttyinfo.winsize.ws_col);
-	    if (from == 0 && resetzle && ttyrows && ttycols)
-		from = 1; /* Signal missed while a job owned the tty? */
-	    ttyrows = shttyinfo.winsize.ws_row;
-	    ttycols = shttyinfo.winsize.ws_col;
-	} else {
-	    /* Set to value from environment on failure */
-	    shttyinfo.winsize.ws_row = lines;
-	    shttyinfo.winsize.ws_col = columns;
-	    resetzle = (from == 1);
-	}
-#else
-	resetzle = from == 1;
-#endif /* TIOCGWINSZ */
-    } /* else
-	 return; */
-
-    switch (from) {
-    case 0:
-    case 1:
-	getwinsz = 0;
-	/* Calling setiparam() here calls this function recursively, but  *
-	 * because we've already called adjustlines() and adjustcolumns() *
-	 * here, recursive calls are no-ops unless a signal intervenes.   *
-	 * The commented "else return;" above might be a safe shortcut,   *
-	 * but I'm concerned about what happens on race conditions; e.g., *
-	 * suppose the user resizes his xterm during `eval $(resize)'?    */
-	if (adjustlines(from) && zgetenv("LINES"))
-	    setiparam("LINES", lines);
-	if (adjustcolumns(from) && zgetenv("COLUMNS"))
-	    setiparam("COLUMNS", columns);
-	getwinsz = 1;
-	break;
-    case 2:
-	resetzle = adjustlines(0);
-	break;
-    case 3:
-	resetzle = adjustcolumns(0);
-	break;
-    }
-
-#ifdef TIOCGWINSZ
-    if (interact && from >= 2 &&
-	(shttyinfo.winsize.ws_row != ttyrows ||
-	 shttyinfo.winsize.ws_col != ttycols)) {
-	/* shttyinfo.winsize is already set up correctly */
-	ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize);
-    }
-#endif /* TIOCGWINSZ */
-
-    if (zleactive && resetzle) {
-#ifdef TIOCGWINSZ
-	winchanged =
-#endif /* TIOCGWINSZ */
-	    resetneeded = 1;
-	zrefreshptr();
-	zle_resetpromptptr();
-    }
-}
-
-/* Move a fd to a place >= 10 and mark the new fd in fdtable.  If the fd *
- * is already >= 10, it is not moved.  If it is invalid, -1 is returned. */
-
-/**/
-mod_export int
-movefd(int fd)
-{
-    if(fd != -1 && fd < 10) {
-#ifdef F_DUPFD
-	int fe = fcntl(fd, F_DUPFD, 10);
-#else
-	int fe = movefd(dup(fd));
-#endif
-	zclose(fd);
-	fd = fe;
-    }
-    if(fd != -1) {
-	if (fd > max_zsh_fd) {
-	    while (fd >= fdtable_size)
-		fdtable = zrealloc(fdtable,
-				   (fdtable_size *= 2)*sizeof(*fdtable));
-	    max_zsh_fd = fd;
-	}
-	fdtable[fd] = FDT_INTERNAL;
-    }
-    return fd;
-}
-
-/* Move fd x to y.  If x == -1, fd y is closed. */
-
-/**/
-mod_export void
-redup(int x, int y)
-{
-    if(x < 0)
-	zclose(y);
-    else if (x != y) {
-	while (y >= fdtable_size)
-	    fdtable = zrealloc(fdtable, (fdtable_size *= 2)*sizeof(*fdtable));
-	dup2(x, y);
-	if ((fdtable[y] = fdtable[x]) && y > max_zsh_fd)
-	    max_zsh_fd = y;
-	zclose(x);
-    }
-}
-
-/* Close the given fd, and clear it from fdtable. */
-
-/**/
-mod_export int
-zclose(int fd)
-{
-    if (fd >= 0) {
-	fdtable[fd] = FDT_UNUSED;
-	while (max_zsh_fd > 0 && fdtable[max_zsh_fd] == FDT_UNUSED)
-	    max_zsh_fd--;
-	if (fd == coprocin)
-	    coprocin = -1;
-	if (fd == coprocout)
-	    coprocout = -1;
-	return close(fd);
-    }
-    return -1;
-}
-
-#ifdef HAVE__MKTEMP
-extern char *_mktemp(char *);
-#endif
-
-/* Get a unique filename for use as a temporary file.  If "prefix" is
- * NULL, the name is relative to $TMPPREFIX; If it is non-NULL, the
- * unique suffix includes a prefixed '.' for improved readability.  If
- * "use_heap" is true, we allocate the returned name on the heap. */
-
-/**/
-mod_export char *
-gettempname(const char *prefix, int use_heap)
-{
-    char *ret, *suffix = prefix ? ".XXXXXX" : "XXXXXX";
-
-    queue_signals();
-    if (!prefix && !(prefix = getsparam("TMPPREFIX")))
-	prefix = DEFAULT_TMPPREFIX;
-    if (use_heap)
-	ret = dyncat(unmeta(prefix), suffix);
-    else
-	ret = bicat(unmeta(prefix), suffix);
-
-#ifdef HAVE__MKTEMP
-    /* Zsh uses mktemp() safely, so silence the warnings */
-    ret = (char *) _mktemp(ret);
-#else
-    ret = (char *) mktemp(ret);
-#endif
-    unqueue_signals();
-
-    return ret;
-}
-
-/**/
-mod_export int
-gettempfile(const char *prefix, int use_heap, char **tempname)
-{
-    char *fn;
-    int fd;
-#if HAVE_MKSTEMP
-    char *suffix = prefix ? ".XXXXXX" : "XXXXXX";
-
-    if (!prefix && !(prefix = getsparam("TMPPREFIX")))
-	prefix = DEFAULT_TMPPREFIX;
-    if (use_heap)
-	fn = dyncat(unmeta(prefix), suffix);
-    else
-	fn = bicat(unmeta(prefix), suffix);
-
-    fd = mkstemp(fn);
-    if (fd < 0) {
-	if (!use_heap)
-	    free(fn);
-	fn = NULL;
-    }
-#else
-    int failures = 0;
-
-    do {
-	if (!(fn = gettempname(prefix, use_heap))) {
-	    fd = -1;
-	    break;
-	}
-	if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0)
-	    break;
-	if (!use_heap)
-	    free(fn);
-	fn = NULL;
-    } while (errno == EEXIST && ++failures < 16);
-#endif
-    *tempname = fn;
-    return fd;
-}
-
-/* Check if a string contains a token */
-
-/**/
-mod_export int
-has_token(const char *s)
-{
-    while(*s)
-	if(itok(*s++))
-	    return 1;
-    return 0;
-}
-
-/* Delete a character in a string */
-
-/**/
-mod_export void
-chuck(char *str)
-{
-    while ((str[0] = str[1]))
-	str++;
-}
-
-/**/
-mod_export int
-tulower(int c)
-{
-    c &= 0xff;
-    return (isupper(c) ? tolower(c) : c);
-}
-
-/**/
-mod_export int
-tuupper(int c)
-{
-    c &= 0xff;
-    return (islower(c) ? toupper(c) : c);
-}
-
-/* copy len chars from t into s, and null terminate */
-
-/**/
-void
-ztrncpy(char *s, char *t, int len)
-{
-    while (len--)
-	*s++ = *t++;
-    *s = '\0';
-}
-
-/* copy t into *s and update s */
-
-/**/
-mod_export void
-strucpy(char **s, char *t)
-{
-    char *u = *s;
-
-    while ((*u++ = *t++));
-    *s = u - 1;
-}
-
-/**/
-mod_export void
-struncpy(char **s, char *t, int n)
-{
-    char *u = *s;
-
-    while (n--)
-	*u++ = *t++;
-    *s = u;
-    *u = '\0';
-}
-
-/* Return the number of elements in an array of pointers. *
- * It doesn't count the NULL pointer at the end.          */
-
-/**/
-mod_export int
-arrlen(char **s)
-{
-    int count;
-
-    for (count = 0; *s; s++, count++);
-    return count;
-}
-
-/* Skip over a balanced pair of parenthesis. */
-
-/**/
-mod_export int
-skipparens(char inpar, char outpar, char **s)
-{
-    int level;
-
-    if (**s != inpar)
-	return -1;
-
-    for (level = 1; *++*s && level;)
-	if (**s == inpar)
-	   ++level;
-	else if (**s == outpar)
-	   --level;
-
-   return level;
-}
-
-/* Convert string to zlong (see zsh.h).  This function (without the z) *
- * is contained in the ANSI standard C library, but a lot of them seem *
- * to be broken.                                                       */
-
-/**/
-mod_export zlong
-zstrtol(const char *s, char **t, int base)
-{
-    const char *inp, *trunc = NULL;
-    zulong calc = 0, newcalc = 0;
-    int neg;
-
-    while (inblank(*s))
-	s++;
-
-    if ((neg = (*s == '-')))
-	s++;
-    else if (*s == '+')
-	s++;
-
-    if (!base) {
-	if (*s != '0')
-	    base = 10;
-	else if (*++s == 'x' || *s == 'X')
-	    base = 16, s++;
-	else
-	    base = 8;
-    }
-    inp = s;
-    if (base > 36) {
-	zerr("invalid base: %d", base);
-	return (zlong)0;
-    } else if (base <= 10)
-	for (; *s >= '0' && *s < ('0' + base); s++) {
-	    if (trunc)
-		continue;
-	    newcalc = calc * base + *s - '0';
-	    if (newcalc < calc)
-	    {
-	      trunc = s;
-	      continue;
-	    }
-	    calc = newcalc;
-	}
-    else
-	for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10))
-	     || (*s >= 'A' && *s < ('A' + base - 10)); s++) {
-	    if (trunc)
-		continue;
-	    newcalc = calc*base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9);
-	    if (newcalc < calc)
-	    {
-		trunc = s;
-		continue;
-	    }
-	    calc = newcalc;
-	}
-
-    /*
-     * Special case: check for a number that was just too long for
-     * signed notation.
-     * Extra special case: the lowest negative number would trigger
-     * the first test, but is actually representable correctly.
-     * This is a 1 in the top bit, all others zero, so test for
-     * that explicitly.
-     */
-    if (!trunc && (zlong)calc < 0 &&
-	(!neg || calc & ~((zulong)1 << (8*sizeof(zulong)-1))))
-    {
-	trunc = s - 1;
-	calc /= base;
-    }
-
-    if (trunc)
-	zwarn("number truncated after %d digits: %s", (int)(trunc - inp), inp);
-
-    if (t)
-	*t = (char *)s;
-    return neg ? -(zlong)calc : (zlong)calc;
-}
-
-/**/
-mod_export int
-setblock_fd(int turnonblocking, int fd, long *modep)
-{
-#ifdef O_NDELAY
-# ifdef O_NONBLOCK
-#  define NONBLOCK (O_NDELAY|O_NONBLOCK)
-# else /* !O_NONBLOCK */
-#  define NONBLOCK O_NDELAY
-# endif /* !O_NONBLOCK */
-#else /* !O_NDELAY */
-# ifdef O_NONBLOCK
-#  define NONBLOCK O_NONBLOCK
-# else /* !O_NONBLOCK */
-#  define NONBLOCK 0
-# endif /* !O_NONBLOCK */
-#endif /* !O_NDELAY */
-
-#if NONBLOCK
-    struct stat st;
-
-    if (!fstat(fd, &st) && !S_ISREG(st.st_mode)) {
-	*modep = fcntl(fd, F_GETFL, 0);
-	if (*modep != -1) {
-	    if (!turnonblocking) {
-		/* We want to know if blocking was off */
-		if ((*modep & NONBLOCK) ||
-		    !fcntl(fd, F_SETFL, *modep | NONBLOCK))
-		    return 1;
-	    } else if ((*modep & NONBLOCK) &&
-		       !fcntl(fd, F_SETFL, *modep & ~NONBLOCK)) {
-		/* Here we want to know if the state changed */
-		return 1;
-	    }
-	}
-    } else
-#endif /* NONBLOCK */
-	*modep = -1;
-    return 0;
-
-#undef NONBLOCK
-}
-
-/**/
-int
-setblock_stdin(void)
-{
-    long mode;
-    return setblock_fd(1, 0, &mode);
-}
-
-/*
- * Check for pending input on fd.  If polltty is set, we may need to
- * use termio to look for input.  As a final resort, go to non-blocking
- * input and try to read a character, which in this case will be
- * returned in *readchar.
- *
- * Note that apart from setting (and restoring) non-blocking input,
- * this function does not change the input mode.  The calling function
- * should have set cbreak mode if necessary.
- */
-
-/**/
-mod_export int
-read_poll(int fd, int *readchar, int polltty, zlong microseconds)
-{
-    int ret = -1;
-    long mode = -1;
-    char c;
-#ifdef HAVE_SELECT
-    fd_set foofd;
-    struct timeval expire_tv;
-#else
-#ifdef FIONREAD
-    int val;
-#endif
-#endif
-#ifdef HAS_TIO
-    struct ttyinfo ti;
-#endif
-
-
-#if defined(HAS_TIO) && !defined(__CYGWIN__)
-    /*
-     * Under Solaris, at least, reading from the terminal in non-canonical
-     * mode requires that we use the VMIN mechanism to poll.  Any attempt
-     * to check any other way, or to set the terminal to non-blocking mode
-     * and poll that way, fails; it will just for canonical mode input.
-     * We should probably use this mechanism if the user has set non-canonical
-     * mode, in which case testing here for isatty() and ~ICANON would be
-     * better than testing whether bin_read() set it, but for now we've got
-     * enough problems.
-     *
-     * Under Cygwin, you won't be surprised to here, this mechanism,
-     * although present, doesn't work, and we *have* to use ordinary
-     * non-blocking reads to find out if there is a character present
-     * in non-canonical mode.
-     *
-     * I am assuming Solaris is nearer the UNIX norm.  This is not necessarily
-     * as plausible as it sounds, but it seems the right way to guess.
-     *		pws 2000/06/26
-     */
-    if (polltty) {
-	gettyinfo(&ti);
-	if ((polltty = ti.tio.c_cc[VMIN])) {
-	    ti.tio.c_cc[VMIN] = 0;
-	    /* termios timeout is 10ths of a second */
-	    ti.tio.c_cc[VTIME] = (int) (microseconds / (zlong)100000);
-	    settyinfo(&ti);
-	}
-    }
-#else
-    polltty = 0;
-#endif
-#ifdef HAVE_SELECT
-    expire_tv.tv_sec = (int) (microseconds / (zlong)1000000);
-    expire_tv.tv_usec = microseconds % (zlong)1000000;
-    FD_ZERO(&foofd);
-    FD_SET(fd, &foofd);
-    ret = select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
-#else
-#ifdef FIONREAD
-    if (ioctl(fd, FIONREAD, (char *) &val) == 0)
-	ret = (val > 0);
-#endif
-#endif
-
-    if (ret < 0) {
-	/*
-	 * Final attempt: set non-blocking read and try to read a character.
-	 * Praise Bill, this works under Cygwin (nothing else seems to).
-	 */
-	if ((polltty || setblock_fd(0, fd, &mode)) && read(fd, &c, 1) > 0) {
-	    *readchar = c;
-	    ret = 1;
-	}
-	if (mode != -1)
-	    fcntl(fd, F_SETFL, mode);
-    }
-#ifdef HAS_TIO
-    if (polltty) {
-	ti.tio.c_cc[VMIN] = 1;
-	ti.tio.c_cc[VTIME] = 0;
-	settyinfo(&ti);
-    }
-#endif
-    return (ret > 0);
-}
-
-/**/
-int
-checkrmall(char *s)
-{
-    if (!shout)
-	return 1;
-    fprintf(shout, "zsh: sure you want to delete all the files in ");
-    if (*s != '/') {
-	nicezputs(pwd[1] ? unmeta(pwd) : "", shout);
-	fputc('/', shout);
-    }
-    nicezputs(s, shout);
-    if(isset(RMSTARWAIT)) {
-	fputs("? (waiting ten seconds)", shout);
-	fflush(shout);
-	zbeep();
-	sleep(10);
-	fputc('\n', shout);
-    }
-    fputs(" [yn]? ", shout);
-    fflush(shout);
-    zbeep();
-    return (getquery("ny", 1) == 'y');
-}
-
-/**/
-int
-read1char(void)
-{
-    char c;
-
-    while (read(SHTTY, &c, 1) != 1) {
-	if (errno != EINTR || errflag || retflag || breaks || contflag)
-	    return -1;
-    }
-    return STOUC(c);
-}
-
-/**/
-mod_export int
-noquery(int purge)
-{
-    int val = 0;
-
-#ifdef FIONREAD
-    char c;
-
-    ioctl(SHTTY, FIONREAD, (char *)&val);
-    if (purge) {
-	for (; val; val--)
-	    read(SHTTY, &c, 1);
-    }
-#endif
-
-    return val;
-}
-
-/**/
-int
-getquery(char *valid_chars, int purge)
-{
-    int c, d;
-    int isem = !strcmp(term, "emacs");
-
-    attachtty(mypgrp);
-    if (!isem)
-	setcbreak();
-
-    if (noquery(purge)) {
-	if (!isem)
-	    settyinfo(&shttyinfo);
-	write(SHTTY, "n\n", 2);
-	return 'n';
-    }
-
-    while ((c = read1char()) >= 0) {
-	if (c == 'Y')
-	    c = 'y';
-	else if (c == 'N')
-	    c = 'n';
-	if (!valid_chars)
-	    break;
-	if (c == '\n') {
-	    c = *valid_chars;
-	    break;
-	}
-	if (strchr(valid_chars, c)) {
-	    write(SHTTY, "\n", 1);
-	    break;
-	}
-	zbeep();
-	if (icntrl(c))
-	    write(SHTTY, "\b \b", 3);
-	write(SHTTY, "\b \b", 3);
-    }
-    if (isem) {
-	if (c != '\n')
-	    while ((d = read1char()) >= 0 && d != '\n');
-    } else {
-	if (c != '\n' && !valid_chars) {
-#ifdef MULTIBYTE_SUPPORT
-	    if (isset(MULTIBYTE) && c >= 0) {
-		/*
-		 * No waiting for a valid character, and no draining;
-		 * we should ensure we haven't stopped in the middle
-		 * of a multibyte character.
-		 */
-		mbstate_t mbs;
-		char cc = (char)c;
-		memset(&mbs, 0, sizeof(mbs));
-		for (;;) {
-		    size_t ret = mbrlen(&cc, 1, &mbs);
-
-		    if (ret != MB_INCOMPLETE)
-			break;
-		    c = read1char();
-		    if (c < 0)
-			break;
-		    cc = (char)c;
-		}
-	    }
-#endif
-	    settyinfo(&shttyinfo);
-	    write(SHTTY, "\n", 1);
-	}
-	else
-	    settyinfo(&shttyinfo);
-    }
-    return c;
-}
-
-static int d;
-static char *guess, *best;
-
-/**/
-static void
-spscan(HashNode hn, UNUSED(int scanflags))
-{
-    int nd;
-
-    nd = spdist(hn->nam, guess, (int) strlen(guess) / 4 + 1);
-    if (nd <= d) {
-	best = hn->nam;
-	d = nd;
-    }
-}
-
-/* spellcheck a word */
-/* fix s ; if hist is nonzero, fix the history list too */
-
-/**/
-mod_export void
-spckword(char **s, int hist, int cmd, int ask)
-{
-    char *t;
-    int x;
-    char ic = '\0';
-    int ne;
-    int preflen = 0;
-    int autocd = cmd && isset(AUTOCD) && strcmp(*s, ".") && strcmp(*s, "..");
-
-    if ((histdone & HISTFLAG_NOEXEC) || **s == '-' || **s == '%')
-	return;
-    if (!strcmp(*s, "in"))
-	return;
-    if (!(*s)[0] || !(*s)[1])
-	return;
-    if (shfunctab->getnode(shfunctab, *s) ||
-	builtintab->getnode(builtintab, *s) ||
-	cmdnamtab->getnode(cmdnamtab, *s) ||
-	aliastab->getnode(aliastab, *s)  ||
-	reswdtab->getnode(reswdtab, *s))
-	return;
-    else if (isset(HASHLISTALL)) {
-	cmdnamtab->filltable(cmdnamtab);
-	if (cmdnamtab->getnode(cmdnamtab, *s))
-	    return;
-    }
-    t = *s;
-    if (*t == Tilde || *t == Equals || *t == String)
-	t++;
-    for (; *t; t++)
-	if (itok(*t))
-	    return;
-    best = NULL;
-    for (t = *s; *t; t++)
-	if (*t == '/')
-	    break;
-    if (**s == Tilde && !*t)
-	return;
-    if (**s == String && !*t) {
-	guess = *s + 1;
-	if (itype_end(guess, IIDENT, 1) == guess)
-	    return;
-	ic = String;
-	d = 100;
-	scanhashtable(paramtab, 1, 0, 0, spscan, 0);
-    } else if (**s == Equals) {
-	if (*t)
-	    return;
-	if (hashcmd(guess = *s + 1, pathchecked))
-	    return;
-	d = 100;
-	ic = Equals;
-	scanhashtable(aliastab, 1, 0, 0, spscan, 0);
-	scanhashtable(cmdnamtab, 1, 0, 0, spscan, 0);
-    } else {
-	guess = *s;
-	if (*guess == Tilde || *guess == String) {
-	    ic = *guess;
-	    if (!*++t)
-		return;
-	    guess = dupstring(guess);
-	    ne = noerrs;
-	    noerrs = 2;
-	    singsub(&guess);
-	    noerrs = ne;
-	    if (!guess)
-		return;
-	    preflen = strlen(guess) - strlen(t);
-	}
-	if (access(unmeta(guess), F_OK) == 0)
-	    return;
-	best = spname(guess);
-	if (!*t && cmd) {
-	    if (hashcmd(guess, pathchecked))
-		return;
-	    d = 100;
-	    scanhashtable(reswdtab, 1, 0, 0, spscan, 0);
-	    scanhashtable(aliastab, 1, 0, 0, spscan, 0);
-	    scanhashtable(shfunctab, 1, 0, 0, spscan, 0);
-	    scanhashtable(builtintab, 1, 0, 0, spscan, 0);
-	    scanhashtable(cmdnamtab, 1, 0, 0, spscan, 0);
-	    if (autocd) {
-		char **pp;
-		for (pp = cdpath; *pp; pp++) {
-		    char bestcd[PATH_MAX + 1];
-		    int thisdist;
-		    /* Less than d here, instead of less than or equal  *
-		     * as used in spscan(), so that an autocd is chosen *
-		     * only when it is better than anything so far, and *
-		     * so we prefer directories earlier in the cdpath.  */
-		    if ((thisdist = mindist(*pp, *s, bestcd)) < d) {
-			best = dupstring(bestcd);
-			d = thisdist;
-		    }
-		}
-	    }
-	}
-    }
-    if (errflag)
-	return;
-    if (best && (int)strlen(best) > 1 && strcmp(best, guess)) {
-	if (ic) {
-	    char *u;
-	    if (preflen) {
-		/* do not correct the result of an expansion */
-		if (strncmp(guess, best, preflen))
-		    return;
-		/* replace the temporarily expanded prefix with the original */
-		u = (char *) hcalloc(t - *s + strlen(best + preflen) + 1);
-		strncpy(u, *s, t - *s);
-		strcpy(u + (t - *s), best + preflen);
-	    } else {
-		u = (char *) hcalloc(strlen(best) + 2);
-		strcpy(u + 1, best);
-	    }
-	    best = u;
-	    guess = *s;
-	    *guess = *best = ztokens[ic - Pound];
-	}
-	if (ask) {
-	    if (noquery(0)) {
-		x = 'n';
-	    } else if (shout) {
-		char *pptbuf;
-		pptbuf = promptexpand(sprompt, 0, best, guess);
-		zputs(pptbuf, shout);
-		free(pptbuf);
-		fflush(shout);
-		zbeep();
-		x = getquery("nyae \t", 0);
-	    } else
-		x = 'n';
-	} else
-	    x = 'y';
-	if (x == 'y' || x == ' ' || x == '\t') {
-	    *s = dupstring(best);
-	    if (hist)
-		hwrep(best);
-	} else if (x == 'a') {
-	    histdone |= HISTFLAG_NOEXEC;
-	} else if (x == 'e') {
-	    histdone |= HISTFLAG_NOEXEC | HISTFLAG_RECALL;
-	}
-	if (ic)
-	    **s = ic;
-    }
-}
-
-/*
- * Helper for ztrftime.  Called with a pointer to the length left
- * in the buffer, and a new string length to decrement from that.
- * Returns 0 if the new length fits, 1 otherwise.  We assume a terminating
- * NUL and return 1 if that doesn't fit.
- */
-
-static int
-ztrftimebuf(int *bufsizeptr, int decr)
-{
-    if (*bufsizeptr <= decr)
-	return 1;
-    *bufsizeptr -= decr;
-    return 0;
-}
-
-/*
- * Like the system function, this returns the number of characters
- * copied, not including the terminating NUL.  This may be zero
- * if the string didn't fit.
- *
- * As an extension, try to detect an error in strftime --- typically
- * not enough memory --- and return -1.  Not guaranteed to be portable,
- * since the strftime() interface doesn't make any guarantees about
- * the state of the buffer if it returns zero.
- */
-
-/**/
-mod_export int
-ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
-{
-    int hr12, decr;
-#ifndef HAVE_STRFTIME
-    static char *astr[] =
-    {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
-    static char *estr[] =
-    {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
-     "Aug", "Sep", "Oct", "Nov", "Dec"};
-#endif
-    char *origbuf = buf;
-    char tmp[3];
-
-
-    tmp[0] = '%';
-    tmp[2] = '\0';
-    while (*fmt)
-	if (*fmt == '%') {
-	    fmt++;
-	    /*
-	     * Assume this format will take up at least two
-	     * characters.  Not always true, but if that matters
-	     * we are so close to the edge it's not a big deal.
-	     * Fix up some longer cases specially when we get to them.
-	     */
-	    if (ztrftimebuf(&bufsize, 2))
-		return -1;
-	    switch (*fmt++) {
-	    case 'd':
-		*buf++ = '0' + tm->tm_mday / 10;
-		*buf++ = '0' + tm->tm_mday % 10;
-		break;
-	    case 'e':
-	    case 'f':
-		if (tm->tm_mday > 9)
-		    *buf++ = '0' + tm->tm_mday / 10;
-		else if (fmt[-1] == 'e')
-		    *buf++ = ' ';
-		*buf++ = '0' + tm->tm_mday % 10;
-		break;
-	    case 'k':
-	    case 'K':
-		if (tm->tm_hour > 9)
-		    *buf++ = '0' + tm->tm_hour / 10;
-		else if (fmt[-1] == 'k')
-		    *buf++ = ' ';
-		*buf++ = '0' + tm->tm_hour % 10;
-		break;
-	    case 'l':
-	    case 'L':
-		hr12 = tm->tm_hour % 12;
-		if (hr12 == 0)
-		    hr12 = 12;
-	        if (hr12 > 9)
-		    *buf++ = '1';
-		else if (fmt[-1] == 'l')
-		    *buf++ = ' ';
-
-		*buf++ = '0' + (hr12 % 10);
-		break;
-	    case 'm':
-		*buf++ = '0' + (tm->tm_mon + 1) / 10;
-		*buf++ = '0' + (tm->tm_mon + 1) % 10;
-		break;
-	    case 'M':
-		*buf++ = '0' + tm->tm_min / 10;
-		*buf++ = '0' + tm->tm_min % 10;
-		break;
-	    case 'S':
-		*buf++ = '0' + tm->tm_sec / 10;
-		*buf++ = '0' + tm->tm_sec % 10;
-		break;
-	    case 'y':
-		*buf++ = '0' + (tm->tm_year / 10) % 10;
-		*buf++ = '0' + tm->tm_year % 10;
-		break;
-	    case '\0':
-		/* Guard against premature end of string */
-		*buf++ = '%';
-		fmt--;
-		break;
-#ifndef HAVE_STRFTIME
-	    case 'a':
-		if (ztrftimebuf(&bufsize, strlen(astr[tm->tm_wday]) - 2))
-		    return -1;
-		strucpy(&buf, astr[tm->tm_wday]);
-		break;
-	    case 'b':
-		if (ztrftimebuf(&bufsize, strlen(estr[tm->tm_mon]) - 2))
-		    return -1;
-		strucpy(&buf, estr[tm->tm_mon]);
-		break;
-	    case 'p':
-		*buf++ = (tm->tm_hour > 11) ? 'p' : 'a';
-		*buf++ = 'm';
-		break;
-	    default:
-		*buf++ = '%';
-		if (fmt[-1] != '%')
-		    *buf++ = fmt[-1];
-#else
-	    default:
-		/*
-		 * Remember we've already allowed for two characters
-		 * in the accounting in bufsize (but nowhere else).
-		 */
-		*buf = '\1';
-		tmp[1] = fmt[-1];
-		if (!strftime(buf, bufsize + 2, tmp, tm))
-		{
-		    if (*buf) {
-			buf[0] = '\0';
-			return -1;
-		    }
-		    return 0;
-		}
-		decr = strlen(buf);
-		buf += decr;
-		bufsize -= decr - 2;
-#endif
-		break;
-	    }
-	} else {
-	    if (ztrftimebuf(&bufsize, 1))
-		return -1;
-	    *buf++ = *fmt++;
-	}
-    *buf = '\0';
-    return buf - origbuf;
-}
-
-/**/
-mod_export char *
-zjoin(char **arr, int delim, int heap)
-{
-    int len = 0;
-    char **s, *ret, *ptr;
-
-    for (s = arr; *s; s++)
-	len += strlen(*s) + 1 + (imeta(delim) ? 1 : 0);
-    if (!len)
-	return heap? "" : ztrdup("");
-    ptr = ret = (heap ? (char *) hcalloc(len) : (char *) zshcalloc(len));
-    for (s = arr; *s; s++) {
-	strucpy(&ptr, *s);
-	    if (imeta(delim)) {
-		*ptr++ = Meta;
-		*ptr++ = delim ^ 32;
-	    }
-	    else
-		*ptr++ = delim;
-    }
-    ptr[-1 - (imeta(delim) ? 1 : 0)] = '\0';
-    return ret;
-}
-
-/* Split a string containing a colon separated list *
- * of items into an array of strings.               */
-
-/**/
-char **
-colonsplit(char *s, int uniq)
-{
-    int ct;
-    char *t, **ret, **ptr, **p;
-
-    for (t = s, ct = 0; *t; t++) /* count number of colons */
-	if (*t == ':')
-	    ct++;
-    ptr = ret = (char **) zalloc(sizeof(char **) * (ct + 2));
-
-    t = s;
-    do {
-	s = t;
-        /* move t to point at next colon */
-	for (; *t && *t != ':'; t++);
-	if (uniq)
-	    for (p = ret; p < ptr; p++)
-		if ((int)strlen(*p) == t - s && ! strncmp(*p, s, t - s))
-		    goto cont;
-	*ptr = (char *) zalloc((t - s) + 1);
-	ztrncpy(*ptr++, s, t - s);
-      cont: ;
-    }
-    while (*t++);
-    *ptr = NULL;
-    return ret;
-}
-
-/**/
-static int
-skipwsep(char **s)
-{
-    char *t = *s;
-    int i = 0;
-
-    /*
-     * Don't need to handle mutlibyte characters, they can't
-     * be IWSEP.  Do need to check for metafication.
-     */
-    while (*t && iwsep(*t == Meta ? t[1] ^ 32 : *t)) {
-	if (*t == Meta)
-	    t++;
-	t++;
-	i++;
-    }
-    *s = t;
-    return i;
-}
-
-/*
- * haven't worked out what allownull does; it's passed down from
- *   sepsplit but all the cases it's used are either 0 or 1 without
- *   a comment.  it seems to be something to do with the `nulstring'
- *   which i think is some kind of a metafication thing, so probably
- *   allownull's value is associated with whether we are using
- *   metafied strings.
- * see findsep() below for handling of `quote' argument
- */
-
-/**/
-mod_export char **
-spacesplit(char *s, int allownull, int heap, int quote)
-{
-    char *t, **ret, **ptr;
-    int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1);
-    char *(*dup)(const char *) = (heap ? dupstring : ztrdup);
-
-    ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zshcalloc(l));
-
-    if (quote) {
-	/*
-	 * we will be stripping quoted separators by hacking string,
-	 * so make sure it's hackable.
-	 */
-	s = dupstring(s);
-    }
-
-    t = s;
-    skipwsep(&s);
-    MB_METACHARINIT();
-    if (*s && itype_end(s, ISEP, 1) != s)
-	*ptr++ = dup(allownull ? "" : nulstring);
-    else if (!allownull && t != s)
-	*ptr++ = dup("");
-    while (*s) {
-	char *iend = itype_end(s, ISEP, 1);
-	if (iend != s) {
-	    s = iend;
-	    skipwsep(&s);
-	}
-	else if (quote && *s == '\\') {
-	    s++;
-	    skipwsep(&s);
-	}
-	t = s;
-	(void)findsep(&s, NULL, quote);
-	if (s > t || allownull) {
-	    *ptr = (heap ? (char *) hcalloc((s - t) + 1) :
-		    (char *) zshcalloc((s - t) + 1));
-	    ztrncpy(*ptr++, t, s - t);
-	} else
-	    *ptr++ = dup(nulstring);
-	t = s;
-	skipwsep(&s);
-    }
-    if (!allownull && t != s)
-	*ptr++ = dup("");
-    *ptr = NULL;
-    return ret;
-}
-
-/*
- * Find a separator.  Return 0 if already at separator, 1 if separator
- * found later, else -1.  (Historical note: used to return length into
- * string but this is all that is necessary and is less ambiguous with
- * multibyte characters around.)
- *
- * *s is the string we are looking along, which will be updated
- * to the point we have got to.
- *
- * sep is a possibly multicharacter separator to look for.  If NULL,
- * use normal separator characters.  If *sep is NULL, split on individual
- * characters.
- *
- * quote is a flag that '\<sep>' should not be treated as a separator.
- * in this case we need to be able to strip the backslash directly
- * in the string, so the calling function must have sent us something
- * modifiable.  currently this only works for sep == NULL.  also in
- * in this case only, we need to turn \\ into \.
- */
-
-/**/
-static int
-findsep(char **s, char *sep, int quote)
-{
-    /*
-     */
-    int i, ilen;
-    char *t, *tt;
-    convchar_t c;
-
-    MB_METACHARINIT();
-    if (!sep) {
-	for (t = *s; *t; t += ilen) {
-	    if (quote && *t == '\\') {
-		if (t[1] == '\\') {
-		    chuck(t);
-		    ilen = 1;
-		    continue;
-		} else {
-		    ilen = MB_METACHARLENCONV(t+1, &c);
-		    if (WC_ZISTYPE(c, ISEP)) {
-			chuck(t);
-			/* then advance over new character, length ilen */
-		    } else {
-			/* treat *t (backslash) as normal byte */
-			if (isep(*t))
-			    break;
-			ilen = 1;
-		    }
-		}
-	    } else {
-		ilen = MB_METACHARLENCONV(t, &c);
-		if (WC_ZISTYPE(c, ISEP))
-		    break;
-	    }
-	}
-	i = (t > *s);
-	*s = t;
-	return i;
-    }
-    if (!sep[0]) {
-	/*
-	 * NULL separator just means advance past first character,
-	 * if any.
-	 */
-	if (**s) {
-	    *s += MB_METACHARLEN(*s);
-	    return 1;
-	}
-	return -1;
-    }
-    for (i = 0; **s; i++) {
-	/*
-	 * The following works for multibyte characters by virtue of
-	 * the fact that sep may be a string (and we don't care how
-	 * it divides up, we need to match all of it).
-	 */
-	for (t = sep, tt = *s; *t && *tt && *t == *tt; t++, tt++);
-	if (!*t)
-	    return (i > 0);
-	*s += MB_METACHARLEN(*s);
-    }
-    return -1;
-}
-
-/**/
-char *
-findword(char **s, char *sep)
-{
-    char *r, *t;
-    int sl;
-
-    if (!**s)
-	return NULL;
-
-    if (sep) {
-	sl = strlen(sep);
-	r = *s;
-	while (! findsep(s, sep, 0)) {
-	    r = *s += sl;
-	}
-	return r;
-    }
-    MB_METACHARINIT();
-    for (t = *s; *t; t += sl) {
-	convchar_t c;
-	sl = MB_METACHARLENCONV(t, &c);
-	if (!WC_ZISTYPE(c, ISEP))
-	    break;
-    }
-    *s = t;
-    (void)findsep(s, sep, 0);
-    return t;
-}
-
-/**/
-int
-wordcount(char *s, char *sep, int mul)
-{
-    int r, sl, c;
-
-    if (sep) {
-	r = 1;
-	sl = strlen(sep);
-	for (; (c = findsep(&s, sep, 0)) >= 0; s += sl)
-	    if ((c && *(s + sl)) || mul)
-		r++;
-    } else {
-	char *t = s;
-
-	r = 0;
-	if (mul <= 0)
-	    skipwsep(&s);
-	if ((*s && itype_end(s, ISEP, 1) != s) ||
-	    (mul < 0 && t != s))
-	    r++;
-	for (; *s; r++) {
-	    char *ie = itype_end(s, ISEP, 1);
-	    if (ie != s) {
-		s = ie;
-		if (mul <= 0)
-		    skipwsep(&s);
-	    }
-	    (void)findsep(&s, NULL, 0);
-	    t = s;
-	    if (mul <= 0)
-		skipwsep(&s);
-	}
-	if (mul < 0 && t != s)
-	    r++;
-    }
-    return r;
-}
-
-/**/
-mod_export char *
-sepjoin(char **s, char *sep, int heap)
-{
-    char *r, *p, **t;
-    int l, sl;
-    char sepbuf[2];
-
-    if (!*s)
-	return heap ? "" : ztrdup("");
-    if (!sep) {
-	/* optimise common case that ifs[0] is space */
-	if (ifs && *ifs != ' ') {
-	    MB_METACHARINIT();
-	    sep = dupstrpfx(ifs, MB_METACHARLEN(ifs));
-	} else {
-	    p = sep = sepbuf;
-	    *p++ = ' ';
-	    *p = '\0';
-	}
-    }
-    sl = strlen(sep);
-    for (t = s, l = 1 - sl; *t; l += strlen(*t) + sl, t++);
-    r = p = (heap ? (char *) hcalloc(l) : (char *) zshcalloc(l));
-    t = s;
-    while (*t) {
-	strucpy(&p, *t);
-	if (*++t)
-	    strucpy(&p, sep);
-    }
-    *p = '\0';
-    return r;
-}
-
-/**/
-char **
-sepsplit(char *s, char *sep, int allownull, int heap)
-{
-    int n, sl;
-    char *t, *tt, **r, **p;
-
-    if (!sep)
-	return spacesplit(s, allownull, heap, 0);
-
-    sl = strlen(sep);
-    n = wordcount(s, sep, 1);
-    r = p = (heap ? (char **) hcalloc((n + 1) * sizeof(char *)) :
-	     (char **) zshcalloc((n + 1) * sizeof(char *)));
-
-    for (t = s; n--;) {
-	tt = t;
-	(void)findsep(&t, sep, 0);
-	*p = (heap ? (char *) hcalloc(t - tt + 1) :
-	      (char *) zshcalloc(t - tt + 1));
-	strncpy(*p, tt, t - tt);
-	(*p)[t - tt] = '\0';
-	p++;
-	t += sl;
-    }
-    *p = NULL;
-
-    return r;
-}
-
-/* Get the definition of a shell function */
-
-/**/
-mod_export Eprog
-getshfunc(char *nam)
-{
-    Shfunc shf;
-
-    if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, nam)))
-	return &dummy_eprog;
-
-    return shf->funcdef;
-}
-
-/**/
-mod_export char **
-mkarray(char *s)
-{
-    char **t = (char **) zalloc((s) ? (2 * sizeof s) : (sizeof s));
-
-    if ((*t = s))
-	t[1] = NULL;
-    return t;
-}
-
-/**/
-mod_export void
-zbeep(void)
-{
-    char *vb;
-    queue_signals();
-    if ((vb = getsparam("ZBEEP"))) {
-	int len;
-	vb = getkeystring(vb, &len, GETKEYS_BINDKEY, NULL);
-	write(SHTTY, vb, len);
-    } else if (isset(BEEP))
-	write(SHTTY, "\07", 1);
-    unqueue_signals();
-}
-
-/**/
-mod_export void
-freearray(char **s)
-{
-    char **t = s;
-
-    DPUTS(!s, "freearray() with zero argument");
-
-    while (*s)
-	zsfree(*s++);
-    free(t);
-}
-
-/**/
-int
-equalsplit(char *s, char **t)
-{
-    for (; *s && *s != '='; s++);
-    if (*s == '=') {
-	*s++ = '\0';
-	*t = s;
-	return 1;
-    }
-    return 0;
-}
-
-static int specialcomma;
-
-/* the ztypes table */
-
-/**/
-mod_export short int typtab[256];
-
-/* initialize the ztypes table */
-
-/**/
-void
-inittyptab(void)
-{
-    int t0;
-    char *s;
-
-    for (t0 = 0; t0 != 256; t0++)
-	typtab[t0] = 0;
-    for (t0 = 0; t0 != 32; t0++)
-	typtab[t0] = typtab[t0 + 128] = ICNTRL;
-    typtab[127] = ICNTRL;
-    for (t0 = '0'; t0 <= '9'; t0++)
-	typtab[t0] = IDIGIT | IALNUM | IWORD | IIDENT | IUSER;
-    for (t0 = 'a'; t0 <= 'z'; t0++)
-	typtab[t0] = typtab[t0 - 'a' + 'A'] = IALPHA | IALNUM | IIDENT | IUSER | IWORD;
-#ifndef MULTIBYTE_SUPPORT
-    /*
-     * This really doesn't seem to me the right thing to do when
-     * we have multibyte character support...  it was a hack to assume
-     * eight bit characters `worked' for some values of work before
-     * we could test for them properly.  I'm not 100% convinced
-     * having IIDENT here is a good idea at all, but this code
-     * should disappear into history...
-     */
-    for (t0 = 0240; t0 != 0400; t0++)
-	typtab[t0] = IALPHA | IALNUM | IIDENT | IUSER | IWORD;
-#endif
-    typtab['_'] = IIDENT | IUSER;
-    typtab['-'] = typtab['.'] = IUSER;
-    typtab[' '] |= IBLANK | INBLANK;
-    typtab['\t'] |= IBLANK | INBLANK;
-    typtab['\n'] |= INBLANK;
-    typtab['\0'] |= IMETA;
-    typtab[STOUC(Meta)  ] |= IMETA;
-    typtab[STOUC(Marker)] |= IMETA;
-    for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Comma); t0++)
-	typtab[t0] |= ITOK | IMETA;
-    for (t0 = (int)STOUC(Snull); t0 <= (int)STOUC(Nularg); t0++)
-	typtab[t0] |= ITOK | IMETA | INULL;
-    for (s = ifs ? ifs : DEFAULT_IFS; *s; s++) {
-	int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
-#ifdef MULTIBYTE_SUPPORT
-	if (!isascii(c)) {
-	    /* see comment for wordchars below */
-	    continue;
-	}
-#endif
-	if (inblank(c)) {
-	    if (s[1] == c)
-		s++;
-	    else
-		typtab[c] |= IWSEP;
-	}
-	typtab[c] |= ISEP;
-    }
-    for (s = wordchars ? wordchars : DEFAULT_WORDCHARS; *s; s++) {
-	int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
-#ifdef MULTIBYTE_SUPPORT
-	if (!isascii(c)) {
-	    /*
-	     * If we have support for multibyte characters, we don't
-	     * handle non-ASCII characters here; instead, we turn
-	     * wordchars into a wide character array.
-	     * (We may actually have a single-byte 8-bit character set,
-	     * but it works the same way.)
-	     */
-	    continue;
-	}
-#endif
-	typtab[c] |= IWORD;
-    }
-#ifdef MULTIBYTE_SUPPORT
-    set_widearray(wordchars, &wordchars_wide);
-    set_widearray(ifs, &ifs_wide);
-#endif
-    for (s = SPECCHARS; *s; s++)
-	typtab[STOUC(*s)] |= ISPECIAL;
-    if (specialcomma)
-	typtab[STOUC(',')] |= ISPECIAL;
-    if (isset(BANGHIST) && bangchar && interact && isset(SHINSTDIN))
-	typtab[bangchar] |= ISPECIAL;
-}
-
-/**/
-mod_export void
-makecommaspecial(int yesno)
-{
-    if ((specialcomma = yesno) != 0)
-	typtab[STOUC(',')] |= ISPECIAL;
-    else
-	typtab[STOUC(',')] &= ~ISPECIAL;
-}
-
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-/* A wide-character version of the iblank() macro. */
-/**/
-mod_export int
-wcsiblank(wint_t wc)
-{
-    if (iswspace(wc) && wc != L'\n')
-	return 1;
-    return 0;
-}
-
-/*
- * zistype macro extended to support wide characters.
- * Works for IIDENT, IWORD, IALNUM, ISEP.
- * We don't need this for IWSEP because that only applies to
- * a fixed set of ASCII characters.
- * Note here that use of multibyte mode is not tested:
- * that's because for ZLE this is unconditional,
- * not dependent on the option.  The caller must decide.
- */
-
-/**/
-mod_export int
-wcsitype(wchar_t c, int itype)
-{
-    int len;
-    mbstate_t mbs;
-    VARARR(char, outstr, MB_CUR_MAX);
-
-    if (!isset(MULTIBYTE))
-	return zistype(c, itype);
-
-    /*
-     * Strategy:  the shell requires that the multibyte representation
-     * be an extension of ASCII.  So see if converting the character
-     * produces an ASCII character.  If it does, use zistype on that.
-     * If it doesn't, use iswalnum on the original character.
-     * If that fails, resort to the appropriate wide character array.
-     */
-    memset(&mbs, 0, sizeof(mbs));
-    len = wcrtomb(outstr, c, &mbs);
-
-    if (len == 0) {
-	/* NULL is special */
-	return zistype(0, itype);
-    } else if (len == 1 && isascii(outstr[0])) {
-	return zistype(outstr[0], itype);
-    } else {
-	switch (itype) {
-	case IIDENT:
-	    if (!isset(POSIXIDENTIFIERS))
-		return 0;
-	    return iswalnum(c);
-
-	case IWORD:
-	    if (iswalnum(c))
-		return 1;
-	    return !!wmemchr(wordchars_wide.chars, c, wordchars_wide.len);
-
-	case ISEP:
-	    return !!wmemchr(ifs_wide.chars, c, ifs_wide.len);
-
-	default:
-	    return iswalnum(c);
-	}
-    }
-}
-
-/**/
-#endif
-
-
-/*
- * Find the end of a set of characters in the set specified by itype;
- * one of IALNUM, IIDENT, IWORD or IUSER.  For non-ASCII characters, we assume
- * alphanumerics are part of the set, with the exception that
- * identifiers are not treated that way if POSIXIDENTIFIERS is set.
- *
- * See notes above for identifiers.
- * Returns the same pointer as passed if not on an identifier character.
- * If "once" is set, just test the first character, i.e. (outptr !=
- * inptr) tests whether the first character is valid in an identifier.
- *
- * Currently this is only called with itype IIDENT, IUSER or ISEP.
- */
-
-/**/
-mod_export char *
-itype_end(const char *ptr, int itype, int once)
-{
-#ifdef MULTIBYTE_SUPPORT
-    if (isset(MULTIBYTE) &&
-	(itype != IIDENT || !isset(POSIXIDENTIFIERS))) {
-	mb_metacharinit();
-	while (*ptr) {
-	    wint_t wc;
-	    int len = mb_metacharlenconv(ptr, &wc);
-
-	    if (!len)
-		break;
-
-	    if (wc == WEOF) {
-		/* invalid, treat as single character */
-		int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
-		/* in this case non-ASCII characters can't match */
-		if (chr > 127 || !zistype(chr,itype))
-		    break;
-	    } else if (len == 1 && isascii(*ptr)) {
-		/* ASCII: can't be metafied, use standard test */
-		if (!zistype(*ptr,itype))
-		    break;
-	    } else {
-		/*
-		 * Valid non-ASCII character.
-		 */
-		switch (itype) {
-		case IWORD:
-		    if (!iswalnum(wc) &&
-			!wmemchr(wordchars_wide.chars, wc,
-				 wordchars_wide.len))
-			return (char *)ptr;
-		    break;
-
-		case ISEP:
-		    if (!wmemchr(ifs_wide.chars, wc, ifs_wide.len))
-			return (char *)ptr;
-		    break;
-
-		default:
-		    if (!iswalnum(wc))
-			return (char *)ptr;
-		}
-	    }
-	    ptr += len;
-
-	    if (once)
-		break;
-	}
-    } else
-#endif
-	for (;;) {
-	    int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
-	    if (!zistype(chr,itype))
-		break;
-	    ptr += (*ptr == Meta) ? 2 : 1;
-
-	    if (once)
-		break;
-	}
-
-    /*
-     * Nasty.  The first argument is const char * because we
-     * don't modify it here.  However, we really want to pass
-     * back the same type as was passed down, to allow idioms like
-     *   p = itype_end(p, IIDENT, 0);
-     * So returning a const char * isn't really the right thing to do.
-     * Without having two different functions the following seems
-     * to be the best we can do.
-     */
-    return (char *)ptr;
-}
-
-/**/
-mod_export char **
-arrdup(char **s)
-{
-    char **x, **y;
-
-    y = x = (char **) zhalloc(sizeof(char *) * (arrlen(s) + 1));
-
-    while ((*x++ = dupstring(*s++)));
-
-    return y;
-}
-
-/**/
-mod_export char **
-zarrdup(char **s)
-{
-    char **x, **y;
-
-    y = x = (char **) zalloc(sizeof(char *) * (arrlen(s) + 1));
-
-    while ((*x++ = ztrdup(*s++)));
-
-    return y;
-}
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-/**/
-mod_export wchar_t **
-wcs_zarrdup(wchar_t **s)
-{
-    wchar_t **x, **y;
-
-    y = x = (wchar_t **) zalloc(sizeof(wchar_t *) * (arrlen((char **)s) + 1));
-
-    while ((*x++ = wcs_ztrdup(*s++)));
-
-    return y;
-}
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/**/
-static char *
-spname(char *oldname)
-{
-    char *p, spnameguess[PATH_MAX + 1], spnamebest[PATH_MAX + 1];
-    static char newname[PATH_MAX + 1];
-    char *new = newname, *old = oldname;
-    int bestdist = 0, thisdist, thresh, maxthresh = 0;
-
-    /* This loop corrects each directory component of the path, stopping *
-     * when any correction distance would exceed the distance threshold. *
-     * NULL is returned only if the first component cannot be corrected; *
-     * otherwise a copy of oldname with a corrected prefix is returned.  *
-     * Rationale for this, if there ever was any, has been forgotten.    */
-    for (;;) {
-	while (*old == '/')
-	    *new++ = *old++;
-	*new = '\0';
-	if (*old == '\0')
-	    return newname;
-	p = spnameguess;
-	for (; *old != '/' && *old != '\0'; old++)
-	    if (p < spnameguess + PATH_MAX)
-		*p++ = *old;
-	*p = '\0';
-	/* Every component is allowed a single distance 2 correction or two *
-	 * distance 1 corrections.  Longer ones get additional corrections. */
-	thresh = (int)(p - spnameguess) / 4 + 1;
-	if (thresh < 3)
-	    thresh = 3;
-	if ((thisdist = mindist(newname, spnameguess, spnamebest)) >= thresh) {
-	    /* The next test is always true, except for the first path    *
-	     * component.  We could initialize bestdist to some large     *
-	     * constant instead, and then compare to that constant here,  *
-	     * because an invariant is that we've never exceeded the      *
-	     * threshold for any component so far; but I think that looks *
-	     * odd to the human reader, and we may make use of the total  *
-	     * distance for all corrections at some point in the future.  */
-	    if (bestdist < maxthresh) {
-		strcpy(new, spnameguess);
-		strcat(new, old);
-		return newname;
-	    } else
-	    	return NULL;
-	} else {
-	    maxthresh = bestdist + thresh;
-	    bestdist += thisdist;
-	}
-	for (p = spnamebest; (*new = *p++);)
-	    new++;
-    }
-}
-
-/**/
-static int
-mindist(char *dir, char *mindistguess, char *mindistbest)
-{
-    int mindistd, nd;
-    DIR *dd;
-    char *fn;
-    char buf[PATH_MAX];
-
-    if (dir[0] == '\0')
-	dir = ".";
-    mindistd = 100;
-    sprintf(buf, "%s/%s", dir, mindistguess);
-    if (access(unmeta(buf), F_OK) == 0) {
-	strcpy(mindistbest, mindistguess);
-	return 0;
-    }
-    if (!(dd = opendir(unmeta(dir))))
-	return mindistd;
-    while ((fn = zreaddir(dd, 0))) {
-	nd = spdist(fn, mindistguess,
-		    (int)strlen(mindistguess) / 4 + 1);
-	if (nd <= mindistd) {
-	    strcpy(mindistbest, fn);
-	    mindistd = nd;
-	    if (mindistd == 0)
-		break;
-	}
-    }
-    closedir(dd);
-    return mindistd;
-}
-
-/**/
-static int
-spdist(char *s, char *t, int thresh)
-{
-    /* TODO: Correction for non-ASCII and multibyte-input keyboards. */
-    char *p, *q;
-    const char qwertykeymap[] =
-    "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t1234567890-=\t\
-\tqwertyuiop[]\t\
-\tasdfghjkl;'\n\t\
-\tzxcvbnm,./\t\t\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t!@#$%^&*()_+\t\
-\tQWERTYUIOP{}\t\
-\tASDFGHJKL:\"\n\t\
-\tZXCVBNM<>?\n\n\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
-    const char dvorakkeymap[] =
-    "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t1234567890[]\t\
-\t',.pyfgcrl/=\t\
-\taoeuidhtns-\n\t\
-\t;qjkxbmwvz\t\t\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
-\t!@#$%^&*(){}\t\
-\t\"<>PYFGCRL?+\t\
-\tAOEUIDHTNS_\n\t\
-\t:QJKXBMWVZ\n\n\t\
-\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
-    const char *keymap;
-    if ( isset( DVORAK ) )
-      keymap = dvorakkeymap;
-    else
-      keymap = qwertykeymap;
-
-    if (!strcmp(s, t))
-	return 0;
-    /* any number of upper/lower mistakes allowed (dist = 1) */
-    for (p = s, q = t; *p && tulower(*p) == tulower(*q); p++, q++);
-    if (!*p && !*q)
-	return 1;
-    if (!thresh)
-	return 200;
-    for (p = s, q = t; *p && *q; p++, q++)
-	if (*p == *q)
-	    continue;		/* don't consider "aa" transposed, ash */
-	else if (p[1] == q[0] && q[1] == p[0])	/* transpositions */
-	    return spdist(p + 2, q + 2, thresh - 1) + 1;
-	else if (p[1] == q[0])	/* missing letter */
-	    return spdist(p + 1, q + 0, thresh - 1) + 2;
-	else if (p[0] == q[1])	/* missing letter */
-	    return spdist(p + 0, q + 1, thresh - 1) + 2;
-	else if (*p != *q)
-	    break;
-    if ((!*p && strlen(q) == 1) || (!*q && strlen(p) == 1))
-	return 2;
-    for (p = s, q = t; *p && *q; p++, q++)
-	if (p[0] != q[0] && p[1] == q[1]) {
-	    int t0;
-	    char *z;
-
-	    /* mistyped letter */
-
-	    if (!(z = strchr(keymap, p[0])) || *z == '\n' || *z == '\t')
-		return spdist(p + 1, q + 1, thresh - 1) + 1;
-	    t0 = z - keymap;
-	    if (*q == keymap[t0 - 15] || *q == keymap[t0 - 14] ||
-		*q == keymap[t0 - 13] ||
-		*q == keymap[t0 - 1] || *q == keymap[t0 + 1] ||
-		*q == keymap[t0 + 13] || *q == keymap[t0 + 14] ||
-		*q == keymap[t0 + 15])
-		return spdist(p + 1, q + 1, thresh - 1) + 2;
-	    return 200;
-	} else if (*p != *q)
-	    break;
-    return 200;
-}
-
-/* set cbreak mode, or the equivalent */
-
-/**/
-void
-setcbreak(void)
-{
-    struct ttyinfo ti;
-
-    ti = shttyinfo;
-#ifdef HAS_TIO
-    ti.tio.c_lflag &= ~ICANON;
-    ti.tio.c_cc[VMIN] = 1;
-    ti.tio.c_cc[VTIME] = 0;
-#else
-    ti.sgttyb.sg_flags |= CBREAK;
-#endif
-    settyinfo(&ti);
-}
-
-/* give the tty to some process */
-
-/**/
-mod_export void
-attachtty(pid_t pgrp)
-{
-    static int ep = 0;
-
-    if (jobbing) {
-#ifdef HAVE_TCSETPGRP
-	if (SHTTY != -1 && tcsetpgrp(SHTTY, pgrp) == -1 && !ep)
-#else
-# if ardent
-	if (SHTTY != -1 && setpgrp() == -1 && !ep)
-# else
-	int arg = pgrp;
-
-	if (SHTTY != -1 && ioctl(SHTTY, TIOCSPGRP, &arg) == -1 && !ep)
-# endif
-#endif
-	{
-	    if (pgrp != mypgrp && kill(-pgrp, 0) == -1)
-		attachtty(mypgrp);
-	    else {
-		if (errno != ENOTTY)
-		{
-		    zwarn("can't set tty pgrp: %e", errno);
-		    fflush(stderr);
-		}
-		opts[MONITOR] = 0;
-		ep = 1;
-	    }
-	}
-    }
-}
-
-/* get the process group associated with the tty */
-
-/**/
-pid_t
-gettygrp(void)
-{
-    pid_t arg;
-
-    if (SHTTY == -1)
-	return -1;
-
-#ifdef HAVE_TCSETPGRP
-    arg = tcgetpgrp(SHTTY);
-#else
-    ioctl(SHTTY, TIOCGPGRP, &arg);
-#endif
-
-    return arg;
-}
-
-
-/* Escape tokens and null characters.  Buf is the string which should be     *
- * escaped.  len is the length of the string.  If len is -1, buf should be   *
- * null terminated.  If len is non-negative and the third parameter is not   *
- * META_DUP, buf should point to an at least len+1 long memory area.  The    *
- * return value points to the quoted string.  If the given string does not   *
- * contain any special character which should be quoted and the third        *
- * parameter is not META_(HEAP|)DUP, buf is returned unchanged (a            *
- * terminating null character is appended to buf if necessary).  Otherwise   *
- * the third `heap' argument determines the method used to allocate space    *
- * for the result.  It can have the following values:                        *
- *   META_REALLOC:  use zrealloc on buf                                      *
- *   META_HREALLOC: use hrealloc on buf                                      *
- *   META_USEHEAP:  get memory from the heap.  This leaves buf unchanged.    *
- *   META_NOALLOC:  buf points to a memory area which is long enough to hold *
- *                  the quoted form, just quote it and return buf.           *
- *   META_STATIC:   store the quoted string in a static area.  The original  *
- *                  string should be at most PATH_MAX long.                  *
- *   META_ALLOC:    allocate memory for the new string with zalloc().        *
- *   META_DUP:      leave buf unchanged and allocate space for the return    *
- *                  value even if buf does not contains special characters   *
- *   META_HEAPDUP:  same as META_DUP, but uses the heap                      */
-
-/**/
-mod_export char *
-metafy(char *buf, int len, int heap)
-{
-    int meta = 0;
-    char *t, *p, *e;
-    static char mbuf[PATH_MAX*2+1];
-
-    if (len == -1) {
-	for (e = buf, len = 0; *e; len++)
-	    if (imeta(*e++))
-		meta++;
-    } else
-	for (e = buf; e < buf + len;)
-	    if (imeta(*e++))
-		meta++;
-
-    if (meta || heap == META_DUP || heap == META_HEAPDUP) {
-	switch (heap) {
-	case META_REALLOC:
-	    buf = zrealloc(buf, len + meta + 1);
-	    break;
-	case META_HREALLOC:
-	    buf = hrealloc(buf, len, len + meta + 1);
-	    break;
-	case META_ALLOC:
-	case META_DUP:
-	    buf = memcpy(zalloc(len + meta + 1), buf, len);
-	    break;
-	case META_USEHEAP:
-	case META_HEAPDUP:
-	    buf = memcpy(zhalloc(len + meta + 1), buf, len);
-	    break;
-	case META_STATIC:
-#ifdef DEBUG
-	    if (len > PATH_MAX) {
-		fprintf(stderr, "BUG: len = %d > PATH_MAX in metafy\n", len);
-		fflush(stderr);
-	    }
-#endif
-	    buf = memcpy(mbuf, buf, len);
-	    break;
-#ifdef DEBUG
-	case META_NOALLOC:
-	    break;
-	default:
-	    fprintf(stderr, "BUG: metafy called with invalid heap value\n");
-	    fflush(stderr);
-	    break;
-#endif
-	}
-	p = buf + len;
-	e = t = buf + len + meta;
-	while (meta) {
-	    if (imeta(*--t = *--p)) {
-		*t-- ^= 32;
-		*t = Meta;
-		meta--;
-	    }
-	}
-    }
-    *e = '\0';
-    return buf;
-}
-
-
-/*
- * Take a null-terminated, metafied string in s into a literal
- * representation by converting in place.  The length is in *len
- * len is non-NULL; if len is NULL, you don't know the length of
- * the final string, but if it's to be supplied to some system
- * routine that always uses NULL termination, such as a filename
- * interpreter, that doesn't matter.  Note the NULL termination
- * is always copied for purposes of that kind.
- */
-
-/**/
-mod_export char *
-unmetafy(char *s, int *len)
-{
-    char *p, *t;
-
-    for (p = s; *p && *p != Meta; p++);
-    for (t = p; (*t = *p++);)
-	if (*t++ == Meta)
-	    t[-1] = *p++ ^ 32;
-    if (len)
-	*len = t - s;
-    return s;
-}
-
-/* Return the character length of a metafied substring, given the      *
- * unmetafied substring length.                                        */
-
-/**/
-mod_export int
-metalen(const char *s, int len)
-{
-    int mlen = len;
-
-    while (len--) {
-	if (*s++ == Meta) {
-	    mlen++;
-	    s++;
-	}
-    }
-    return mlen;
-}
-
-/* This function converts a zsh internal string to a form which can be *
- * passed to a system call as a filename.  The result is stored in a   *
- * single static area.  NULL returned if the result is longer than     *
- * 4 * PATH_MAX.                                                       */
-
-/**/
-mod_export char *
-unmeta(const char *file_name)
-{
-    static char fn[4 * PATH_MAX];
-    char *p;
-    const char *t;
-
-    for (t = file_name, p = fn; *t && p < fn + 4 * PATH_MAX - 1; p++)
-	if ((*p = *t++) == Meta)
-	    *p = *t++ ^ 32;
-    if (*t)
-	return NULL;
-    if (p - fn == t - file_name)
-	return (char *) file_name;
-    *p = '\0';
-    return fn;
-}
-
-/*
- * Unmetafy and compare two strings, comparing unsigned character values.
- * "a\0" sorts after "a".
- *
- * Currently this is only used in hash table sorting, where the
- * keys are names of hash nodes and where we don't use strcoll();
- * it's not clear if that's right but it does guarantee the ordering
- * of shell structures on output.
- *
- * As we don't use strcoll(), it seems overkill to convert multibyte
- * characters to wide characters for comparison every time.  In the case
- * of UTF-8, Unicode ordering is preserved when sorted raw, and for
- * other character sets we rely on an extension of ASCII so the result,
- * while it may not be correct, is at least rational.
- */
-
-/**/
-int
-ztrcmp(char const *s1, char const *s2)
-{
-    int c1, c2;
-
-    while(*s1 && *s1 == *s2) {
-	s1++;
-	s2++;
-    }
-
-    if(!(c1 = *s1))
-	c1 = -1;
-    else if(c1 == STOUC(Meta))
-	c1 = *++s1 ^ 32;
-    if(!(c2 = *s2))
-	c2 = -1;
-    else if(c2 == STOUC(Meta))
-	c2 = *++s2 ^ 32;
-
-    if(c1 == c2)
-	return 0;
-    else if(c1 < c2)
-	return -1;
-    else
-	return 1;
-}
-
-/* Return the unmetafied length of a metafied string. */
-
-/**/
-mod_export int
-ztrlen(char const *s)
-{
-    int l;
-
-    for (l = 0; *s; l++) {
-	if (*s++ == Meta) {
-#ifdef DEBUG
-	    if (! *s)
-		fprintf(stderr, "BUG: unexpected end of string in ztrlen()\n");
-	    else
-#endif
-	    s++;
-	}
-    }
-    return l;
-}
-
-/* Subtract two pointers in a metafied string. */
-
-/**/
-mod_export int
-ztrsub(char const *t, char const *s)
-{
-    int l = t - s;
-
-    while (s != t) {
-	if (*s++ == Meta) {
-#ifdef DEBUG
-	    if (! *s || s == t)
-		fprintf(stderr, "BUG: substring ends in the middle of a metachar in ztrsub()\n");
-	    else
-#endif
-	    s++;
-	    l--;
-	}
-    }
-    return l;
-}
-
-/**/
-mod_export char *
-zreaddir(DIR *dir, int ignoredots)
-{
-    struct dirent *de;
-
-    do {
-	de = readdir(dir);
-	if(!de)
-	    return NULL;
-    } while(ignoredots && de->d_name[0] == '.' &&
-	(!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])));
-
-    return metafy(de->d_name, -1, META_STATIC);
-}
-
-/* Unmetafy and output a string.  Tokens are skipped. */
-
-/**/
-mod_export int
-zputs(char const *s, FILE *stream)
-{
-    int c;
-
-    while (*s) {
-	if (*s == Meta)
-	    c = *++s ^ 32;
-	else if(itok(*s)) {
-	    s++;
-	    continue;
-	} else
-	    c = *s;
-	s++;
-	if (fputc(c, stream) < 0)
-	    return EOF;
-    }
-    return 0;
-}
-
-#ifndef MULTIBYTE_SUPPORT
-/* Create a visibly-represented duplicate of a string. */
-
-/**/
-mod_export char *
-nicedup(char const *s, int heap)
-{
-    int c, len = strlen(s) * 5 + 1;
-    VARARR(char, buf, len);
-    char *p = buf, *n;
-
-    while ((c = *s++)) {
-	if (itok(c)) {
-	    if (c <= Comma)
-		c = ztokens[c - Pound];
-	    else
-		continue;
-	}
-	if (c == Meta)
-	    c = *s++ ^ 32;
-	/* The result here is metafied */
-	n = nicechar(c);
-	while(*n)
-	    *p++ = *n++;
-    }
-    *p = '\0';
-    return heap ? dupstring(buf) : ztrdup(buf);
-}
-#endif
-
-/**/
-mod_export char *
-nicedupstring(char const *s)
-{
-    return nicedup(s, 1);
-}
-
-
-#ifndef MULTIBYTE_SUPPORT
-/* Unmetafy and output a string, displaying special characters readably. */
-
-/**/
-mod_export int
-nicezputs(char const *s, FILE *stream)
-{
-    int c;
-
-    while ((c = *s++)) {
-	if (itok(c)) {
-	    if (c <= Comma)
-		c = ztokens[c - Pound];
-	    else
-		continue;
-	}
-	if (c == Meta)
-	    c = *s++ ^ 32;
-	if(zputs(nicechar(c), stream) < 0)
-	    return EOF;
-    }
-    return 0;
-}
-
-
-/* Return the length of the visible representation of a metafied string. */
-
-/**/
-mod_export size_t
-niceztrlen(char const *s)
-{
-    size_t l = 0;
-    int c;
-
-    while ((c = *s++)) {
-	if (itok(c)) {
-	    if (c <= Comma)
-		c = ztokens[c - Pound];
-	    else
-		continue;
-	}
-	if (c == Meta)
-	    c = *s++ ^ 32;
-	l += strlen(nicechar(c));
-    }
-    return l;
-}
-#endif
-
-
-/**/
-#ifdef MULTIBYTE_SUPPORT
-/*
- * Version of both nicezputs() and niceztrlen() for use with multibyte
- * characters.  Input is a metafied string; output is the screen width of
- * the string.
- *
- * If the FILE * is not NULL, output to that, too.
- *
- * If outstrp is not NULL, set *outstrp to a zalloc'd version of
- * the output (still metafied).
- *
- * If "heap" is non-zero, use the heap for *outstrp, else zalloc.
- */
-
-/**/
-mod_export size_t
-mb_niceformat(const char *s, FILE *stream, char **outstrp, int heap)
-{
-    size_t l = 0, newl;
-    int umlen, outalloc, outleft, eol = 0;
-    wchar_t c;
-    char *ums, *ptr, *fmt, *outstr, *outptr;
-    mbstate_t mbs;
-
-    if (outstrp) {
-	outleft = outalloc = 5 * strlen(s);
-	outptr = outstr = zalloc(outalloc);
-    } else {
-	outleft = outalloc = 0;
-	outptr = outstr = NULL;
-    }
-
-    ums = ztrdup(s);
-    /*
-     * is this necessary at this point? niceztrlen does this
-     * but it's used in lots of places.  however, one day this may
-     * be, too.
-     */
-    untokenize(ums);
-    ptr = unmetafy(ums, &umlen);
-
-    memset(&mbs, 0, sizeof mbs);
-    while (umlen > 0) {
-	size_t cnt = eol ? MB_INVALID : mbrtowc(&c, ptr, umlen, &mbs);
-
-	switch (cnt) {
-	case MB_INCOMPLETE:
-	    eol = 1;
-	    /* FALL THROUGH */
-	case MB_INVALID:
-	    /* The byte didn't convert, so output it as a \M-... sequence. */
-	    fmt = nicechar(*ptr);
-	    newl = strlen(fmt);
-	    cnt = 1;
-	    /* Get mbs out of its undefined state. */
-	    memset(&mbs, 0, sizeof mbs);
-	    break;
-	case 0:
-	    /* Careful:  converting '\0' returns 0, but a '\0' is a
-	     * real character for us, so we should consume 1 byte. */
-	    cnt = 1;
-	    /* FALL THROUGH */
-	default:
-	    fmt = wcs_nicechar(c, &newl, NULL);
-	    break;
-	}
-
-	umlen -= cnt;
-	ptr += cnt;
-	l += newl;
-
-	if (stream)
-	    zputs(fmt, stream);
-	if (outstr) {
-	    /* Append to output string */
-	    int outlen = strlen(fmt);
-	    if (outlen >= outleft) {
-		/* Reallocate to twice the length */
-		int outoffset = outptr - outstr;
-
-		outleft += outalloc;
-		outalloc *= 2;
-		outstr = zrealloc(outstr, outalloc);
-		outptr = outstr + outoffset;
-	    }
-	    memcpy(outptr, fmt, outlen);
-	    /* Update start position */
-	    outptr += outlen;
-	    /* Update available bytes */
-	    outleft -= outlen;
-	}
-    }
-
-    free(ums);
-    if (outstrp) {
-	*outptr = '\0';
-	/* Use more efficient storage for returned string */
-	*outstrp = heap ? dupstring(outstr) : ztrdup(outstr);
-	free(outstr);
-    }
-
-    return l;
-}
-
-/* ztrdup multibyte string with nice formatting */
-
-/**/
-mod_export char *
-nicedup(const char *s, int heap)
-{
-    char *retstr;
-
-    (void)mb_niceformat(s, NULL, &retstr, heap);
-
-    return retstr;
-}
-
-
-/*
- * Length of metafied string s which contains the next multibyte
- * character; single (possibly metafied) character if string is not null
- * but character is not valid (e.g. possibly incomplete at end of string).
- * Returned value is guaranteed not to reach beyond the end of the
- * string (assuming correct metafication).
- *
- * If wcp is not NULL, the converted wide character is stored there.
- * If no conversion could be done WEOF is used.
- */
-
-/**/
-mod_export int
-mb_metacharlenconv(const char *s, wint_t *wcp)
-{
-    char inchar;
-    const char *ptr;
-    size_t ret;
-    wchar_t wc;
-
-    if (!isset(MULTIBYTE)) {
-	/* treat as single byte, possibly metafied */
-	if (wcp)
-	    *wcp = (wint_t)(*s == Meta ? s[1] ^ 32 : *s);
-	return 1 + (*s == Meta);
-    }
-    /*
-     * We have to handle tokens here, since we may be looking
-     * through a tokenized input.  Obviously this isn't
-     * a valid multibyte character, so just return WEOF
-     * and let the caller handle it as a single character.
-     *
-     * TODO: I've a sneaking suspicion we could do more here
-     * to prevent the caller always needing to handle invalid
-     * characters specially, but sometimes it may need to know.
-     */
-    if (itok(*s)) {
-	if (wcp)
-	    *wcp = WEOF;
-	return 1;
-    }
-
-    ret = MB_INVALID;
-    for (ptr = s; *ptr; ) {
-	if (*ptr == Meta) {
-	    inchar = *++ptr ^ 32;
-#ifdef DEBUG
-	    if (!*ptr)
-		fprintf(stderr,
-			"BUG: unexpected end of string in mb_metacharlen()\n");
-#endif
-	} else
-	    inchar = *ptr;
-	ptr++;
-	ret = mbrtowc(&wc, &inchar, 1, &mb_shiftstate);
-
-	if (ret == MB_INVALID)
-	    break;
-	if (ret == MB_INCOMPLETE)
-	    continue;
-	if (wcp)
-	    *wcp = wc;
-	return ptr - s;
-    }
-
-    if (wcp)
-	*wcp = WEOF;
-    /* No valid multibyte sequence */
-    memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
-    if (ptr > s) {
-	return 1 + (*s == Meta);	/* Treat as single byte character */
-    } else
-	return 0;		/* Probably shouldn't happen */
-}
-
-/*
- * Total number of multibyte characters in metafied string s.
- * Same answer as iterating mb_metacharlen() and counting calls
- * until end of string.
- *
- * If width is 1, return total character width rather than number.
- */
-
-/**/
-mod_export int
-mb_metastrlen(char *ptr, int width)
-{
-    char inchar, *laststart;
-    size_t ret;
-    wchar_t wc;
-    int num, num_in_char;
-
-    if (!isset(MULTIBYTE))
-	return ztrlen(ptr);
-
-    laststart = ptr;
-    ret = MB_INVALID;
-    num = num_in_char = 0;
-
-    memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
-    while (*ptr) {
-	if (*ptr == Meta)
-	    inchar = *++ptr ^ 32;
-	else
-	    inchar = *ptr;
-	ptr++;
-	ret = mbrtowc(&wc, &inchar, 1, &mb_shiftstate);
-
-	if (ret == MB_INCOMPLETE) {
-	    num_in_char++;
-	} else {
-	    if (ret == MB_INVALID) {
-		/* Reset, treat as single character */
-		memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
-		ptr = laststart + (*laststart == Meta) + 1;
-		num++;
-	    } else if (width) {
-		/*
-		 * Returns -1 if not a printable character.  We
-		 * turn this into 1 for backward compatibility.
-		 */
-		int wcw = wcwidth(wc);
-		if (wcw >= 0)
-		    num += wcw;
-		else
-		    num++;
-	    } else
-		num++;
-	    laststart = ptr;
-	    num_in_char = 0;
-	}
-    }
-
-    /* If incomplete, treat remainder as trailing single bytes */
-    return num + num_in_char;
-}
-
-/**/
-#else
-
-/* Simple replacement for mb_metacharlenconv */
-
-/**/
-mod_export int
-metacharlenconv(const char *x, int *c)
-{
-    /*
-     * Here we don't use STOUC() on the chars since they
-     * may be compared against other chars and this will fail
-     * if chars are signed and the high bit is set.
-     */
-    if (*x == Meta) {
-	if (c)
-	    *c = x[1] ^ 32;
-	return 2;
-    }
-    if (c)
-	*c = (char)*x;
-    return 1;
-}
-
-/**/
-#endif /* MULTIBYTE_SUPPORT */
-
-/* check for special characters in the string */
-
-/**/
-mod_export int
-hasspecial(char const *s)
-{
-    for (; *s; s++) {
-	if (ispecial(*s == Meta ? *++s ^ 32 : *s))
-	    return 1;
-    }
-    return 0;
-}
-
-
-static char *
-addunprintable(char *v, const char *u, const char *uend)
-{
-    for (; u < uend; u++) {
-	/*
-	 * Just do this byte by byte; there's no great
-	 * advantage in being clever with multibyte
-	 * characters if we don't think they're printable.
-	 */
-	int c;
-	if (*u == Meta)
-	    c = STOUC(*++u ^ 32);
-	else
-	    c = STOUC(*u);
-	switch (c) {
-	case '\0':
-	    *v++ = '\\';
-	    *v++ = '0';
-	    if ('0' <= u[1] && u[1] <= '7') {
-		*v++ = '0';
-		*v++ = '0';
-	    }
-	    break;
-
-	case '\007': *v++ = '\\'; *v++ = 'a'; break;
-	case '\b': *v++ = '\\'; *v++ = 'b'; break;
-	case '\f': *v++ = '\\'; *v++ = 'f'; break;
-	case '\n': *v++ = '\\'; *v++ = 'n'; break;
-	case '\r': *v++ = '\\'; *v++ = 'r'; break;
-	case '\t': *v++ = '\\'; *v++ = 't'; break;
-	case '\v': *v++ = '\\'; *v++ = 'v'; break;
-
-	default:
-	    *v++ = '\\';
-	    *v++ = '0' + ((c >> 6) & 7);
-	    *v++ = '0' + ((c >> 3) & 7);
-	    *v++ = '0' + (c & 7);
-	    break;
-	}
-    }
-
-    return v;
-}
-
-/*
- * Quote the string s and return the result.
- *
- * If e is non-zero, the
- * pointer it points to may point to a position in s and in e the position
- * of the corresponding character in the quoted string is returned.
- * 
- * The last argument is a QT_ value defined in zsh.h other than QT_NONE.
- *
- * The string may be metafied and contain tokens.
- */
-
-/**/
-mod_export char *
-quotestring(const char *s, char **e, int instring)
-{
-    const char *u, *tt;
-    char *v;
-    /*
-     * With QT_BACKSLASH we may need to use $'\300' stuff.
-     * Keep memory usage within limits by allocating temporary
-     * storage and using heap for correct size at end.
-     */
-    int alloclen = (instring == QT_BACKSLASH ? 7 : 4) * strlen(s) + 1;
-    char *buf = zshcalloc(alloclen);
-    int sf = 0;
-    convchar_t cc;
-    const char *uend;
-
-    DPUTS(instring < QT_BACKSLASH || instring > QT_DOLLARS,
-	  "BUG: bad quote type in quotestring");
-    tt = v = buf;
-    u = s;
-    if (instring == QT_DOLLARS) {
-	/*
-	 * As we test for printability here we need to be able
-	 * to look for multibyte characters.
-	 */
-	MB_METACHARINIT();
-	while (*u) {
-	    uend = u + MB_METACHARLENCONV(u, &cc);
-
-	    if (e && !sf && *e <= u) {
-		*e = v;
-		sf = 1;
-	    }
-	    if (
-#ifdef MULTIBYTE_SUPPORT
-		cc != WEOF &&
-#endif
-		WC_ISPRINT(cc)) {
-		switch (cc) {
-		case ZWC('\\'):
-		case ZWC('\''):
-		    *v++ = '\\';
-		    break;
-
-		default:
-		    if (isset(BANGHIST) && cc == (wchar_t)bangchar)
-			*v++ = '\\';
-		    break;
-		}
-		while (u < uend)
-		    *v++ = *u++;
-	    } else {
-		/* Not printable */
-		v = addunprintable(v, u, uend);
-		u = uend;
-	    }
-	}
-    }
-    else
-    {
-	/*
-	 * Here there are syntactic special characters, so
-	 * we start by going through bytewise.
-	 */
-	while (*u) {
-	    int dobackslash = 0;
-	    if (e && *e == u)
-		*e = v, sf = 1;
-	    if (*u == Tick || *u == Qtick) {
-		char c = *u++;
-
-		*v++ = c;
-		while (*u && *u != c)
-		    *v++ = *u++;
-		*v++ = c;
-		if (*u)
-		    u++;
-		continue;
-	    } else if ((*u == Qstring || *u == '$') && u[1] == '\'' &&
-		       instring == QT_DOUBLE) {
-		/*
-		 * We don't need to quote $'...' inside a double-quoted
-		 * string.  This is largely cosmetic; it looks neater
-		 * if we don't but it doesn't do any harm since the
-		 * \ is stripped.
-		 */
-		*v++ = *u++;
-	    } else if ((*u == String || *u == Qstring) &&
-		       (u[1] == Inpar || u[1] == Inbrack || u[1] == Inbrace)) {
-		char c = (u[1] == Inpar ? Outpar : (u[1] == Inbrace ?
-						    Outbrace : Outbrack));
-		char beg = *u;
-		int level = 0;
-
-		*v++ = *u++;
-		*v++ = *u++;
-		while (*u && (*u != c || level)) {
-		    if (*u == beg)
-			level++;
-		    else if (*u == c)
-			level--;
-		    *v++ = *u++;
-		}
-		if (*u)
-		    *v++ = *u++;
-		continue;
-	    }
-	    else if (ispecial(*u) &&
-		     ((*u != '=' && *u != '~') ||
-		      u == s ||
-		      (isset(MAGICEQUALSUBST) &&
-		       (u[-1] == '=' || u[-1] == ':')) ||
-		      (*u == '~' && isset(EXTENDEDGLOB))) &&
-		     (instring == QT_BACKSLASH ||
-		      (isset(BANGHIST) && *u == (char)bangchar &&
-		       instring != QT_SINGLE) ||
-		      (instring == QT_DOUBLE &&
-		       (*u == '$' || *u == '`' || *u == '\"' || *u == '\\')) ||
-		      (instring == QT_SINGLE && *u == '\''))) {
-		if (*u == '\n' || (instring == QT_SINGLE && *u == '\'')) {
-		    if (unset(RCQUOTES)) {
-			*v++ = '\'';
-			if (*u == '\'')
-			    *v++ = '\\';
-			*v++ = *u;
-			*v++ = '\'';
-		    } else if (*u == '\n')
-			*v++ = '"', *v++ = '\n', *v++ = '"';
-		    else
-			*v++ = '\'', *v++ = '\'';
-		    u++;
-		    continue;
-		} else {
-		    /*
-		     * We'll need a backslash, but don't add it
-		     * yet since if the character isn't printable
-		     * we'll have to upgrade it to $'...'.
-		     */
-		    dobackslash = 1;
-		}
-	    }
-
-	    if (itok(*u) || instring != QT_BACKSLASH) {
-		/* Needs to be passed straight through. */
-		if (dobackslash)
-		    *v++ = '\\';
-		*v++ = *u++;
-		continue;
-	    }
-
-	    /*
-	     * Now check if the output is unprintable in the
-	     * current character set.
-	     */
-	    uend = u + MB_METACHARLENCONV(u, &cc);
-	    if (
-#ifdef MULTIBYTE_SUPPORT
-		cc != WEOF &&
-#endif
-		WC_ISPRINT(cc)) {
-		if (dobackslash)
-		    *v++ = '\\';
-		while (u < uend) {
-		    if (*u == Meta)
-			*v++ = *u++;
-		    *v++ = *u++;
-		}
-	    } else {
-		/* Not printable */
-		*v++ = '$';
-		*v++ = '\'';
-		v = addunprintable(v, u, uend);
-		*v++ = '\'';
-		u = uend;
-	    }
-	}
-    }
-    *v = '\0';
-
-    if (e && *e == u)
-	*e = v, sf = 1;
-    DPUTS(e && !sf, "BUG: Wild pointer *e in quotestring()");
-
-    v = dupstring(buf);
-    zfree(buf, alloclen);
-    return v;
-}
-
-/* Unmetafy and output a string, quoted if it contains special characters. */
-
-/**/
-mod_export int
-quotedzputs(char const *s, FILE *stream)
-{
-    int inquote = 0, c;
-
-    /* check for empty string */
-    if(!*s)
-	return fputs("''", stream);
-
-    if (!hasspecial(s))
-	return zputs(s, stream);
-
-    if (isset(RCQUOTES)) {
-	/* use rc-style quotes-within-quotes for the whole string */
-	if(fputc('\'', stream) < 0)
-	    return EOF;
-	while(*s) {
-	    if (*s == Meta)
-		c = *++s ^ 32;
-	    else
-		c = *s;
-	    s++;
-	    if (c == '\'') {
-		if(fputc('\'', stream) < 0)
-		    return EOF;
-	    } else if(c == '\n' && isset(CSHJUNKIEQUOTES)) {
-		if(fputc('\\', stream) < 0)
-		    return EOF;
-	    }
-	    if(fputc(c, stream) < 0)
-		return EOF;
-	}
-	if(fputc('\'', stream) < 0)
-	    return EOF;
-    } else {
-	/* use Bourne-style quoting, avoiding empty quoted strings */
-	while(*s) {
-	    if (*s == Meta)
-		c = *++s ^ 32;
-	    else
-		c = *s;
-	    s++;
-	    if (c == '\'') {
-		if(inquote) {
-		    if(fputc('\'', stream) < 0)
-			return EOF;
-		    inquote=0;
-		}
-		if(fputs("\\'", stream) < 0)
-		    return EOF;
-	    } else {
-		if (!inquote) {
-		    if(fputc('\'', stream) < 0)
-			return EOF;
-		    inquote=1;
-		}
-		if(c == '\n' && isset(CSHJUNKIEQUOTES)) {
-		    if(fputc('\\', stream) < 0)
-			return EOF;
-		}
-		if(fputc(c, stream) < 0)
-		    return EOF;
-	    }
-	}
-	if (inquote) {
-	    if(fputc('\'', stream) < 0)
-		return EOF;
-	}
-    }
-    return 0;
-}
-
-/* Double-quote a metafied string. */
-
-/**/
-mod_export char *
-dquotedztrdup(char const *s)
-{
-    int len = strlen(s) * 4 + 2;
-    char *buf = zalloc(len);
-    char *p = buf, *ret;
-
-    if(isset(CSHJUNKIEQUOTES)) {
-	int inquote = 0;
-
-	while(*s) {
-	    int c = *s++;
-
-	    if (c == Meta)
-		c = *s++ ^ 32;
-	    switch(c) {
-		case '"':
-		case '$':
-		case '`':
-		    if(inquote) {
-			*p++ = '"';
-			inquote = 0;
-		    }
-		    *p++ = '\\';
-		    *p++ = c;
-		    break;
-		default:
-		    if(!inquote) {
-			*p++ = '"';
-			inquote = 1;
-		    }
-		    if(c == '\n')
-			*p++ = '\\';
-		    *p++ = c;
-		    break;
-	    }
-	}
-	if (inquote)
-	    *p++ = '"';
-    } else {
-	int pending = 0;
-
-	*p++ = '"';
-	while(*s) {
-	    int c = *s++;
-
-	    if (c == Meta)
-		c = *s++ ^ 32;
-	    switch(c) {
-		case '\\':
-		    if(pending)
-			*p++ = '\\';
-		    *p++ = '\\';
-		    pending = 1;
-		    break;
-		case '"':
-		case '$':
-		case '`':
-		    if(pending)
-			*p++ = '\\';
-		    *p++ = '\\';
-		    /* FALL THROUGH */
-		default:
-		    *p++ = c;
-		    pending = 0;
-		    break;
-	    }
-	}
-	if(pending)
-	    *p++ = '\\';
-	*p++ = '"';
-    }
-    ret = metafy(buf, p - buf, META_DUP);
-    zfree(buf, len);
-    return ret;
-}
-
-/* Unmetafy and output a string, double quoting it in its entirety. */
-
-#if 0 /**/
-int
-dquotedzputs(char const *s, FILE *stream)
-{
-    char *d = dquotedztrdup(s);
-    int ret = zputs(d, stream);
-
-    zsfree(d);
-    return ret;
-}
-#endif
-
-# if defined(HAVE_NL_LANGINFO) && defined(CODESET) && !defined(__STDC_ISO_10646__)
-/* Convert a character from UCS4 encoding to UTF-8 */
-
-static size_t
-ucs4toutf8(char *dest, unsigned int wval)
-{
-    size_t len;
-
-    if (wval < 0x80)
-      len = 1;
-    else if (wval < 0x800)
-      len = 2;
-    else if (wval < 0x10000)
-      len = 3;
-    else if (wval < 0x200000)
-      len = 4;
-    else if (wval < 0x4000000)
-      len = 5;
-    else
-      len = 6;
-
-    switch (len) { /* falls through except to the last case */
-    case 6: dest[5] = (wval & 0x3f) | 0x80; wval >>= 6;
-    case 5: dest[4] = (wval & 0x3f) | 0x80; wval >>= 6;
-    case 4: dest[3] = (wval & 0x3f) | 0x80; wval >>= 6;
-    case 3: dest[2] = (wval & 0x3f) | 0x80; wval >>= 6;
-    case 2: dest[1] = (wval & 0x3f) | 0x80; wval >>= 6;
-	*dest = wval | ((0xfc << (6 - len)) & 0xfc);
-	break;
-    case 1: *dest = wval;
-    }
-
-    return len;
-}
-#endif
-
-
-/*
- * The following only occurs once or twice in the code, but in different
- * places depending how character set conversion is implemented.
- */
-#define CHARSET_FAILED()		      \
-    if (how & GETKEY_DOLLAR_QUOTE) {	      \
-	while ((*tdest++ = *++s)) {	      \
-	    if (how & GETKEY_UPDATE_OFFSET) { \
-		if (s - sstart > *misc)	      \
-		    (*misc)++;		      \
-	    }				      \
-	    if (*s == Snull) {		      \
-		*len = (s - sstart) + 1;      \
-		*tdest = '\0';		      \
-		return buf;		      \
-	    }				      \
-	}				      \
-	*len = tdest - buf;		      \
-	return buf;			      \
-    }					      \
-    *t = '\0';				      \
-    *len = t - buf;			      \
-    return buf
-
-/*
- * Decode a key string, turning it into the literal characters.
- * The value returned is a newly allocated string from the heap.
- *
- * The length is returned in *len.  This is usually the length of
- * the final unmetafied string.  The exception is the case of
- * a complete GETKEY_DOLLAR_QUOTE conversion where *len is the
- * length of the input string which has been used (up to and including
- * the terminating single quote); as the final string is metafied and
- * NULL-terminated its length is not required.  If both GETKEY_DOLLAR_QUOTE
- * and GETKEY_UPDATE_OFFSET are present in "how", the string is not
- * expected to be terminated (this is used in completion to parse
- * a partial $'...'-quoted string) and the length passed back is
- * that of the converted string.  Note in both cases that this is a length
- * in bytes (i.e. the same as given by a raw pointer difference), not
- * characters, which may occupy multiple bytes.
- *
- * how is a set of bits from the GETKEY_ values defined in zsh.h;
- * not all combinations of bits are useful.  Callers will typically
- * use one of the GETKEYS_ values which define sets of bits.
- * Note, for example that:
- * - GETKEY_SINGLE_CHAR must not be combined with GETKEY_DOLLAR_QUOTE.
- * - GETKEY_UPDATE_OFFSET is only allowed if GETKEY_DOLLAR_QUOTE is
- *   also present.
- *
- * *misc is used for various purposes:
- * - If GETKEY_BACKSLASH_MINUS is set, it indicates the presence
- *   of \- in the input.
- * - If GETKEY_BACKSLASH_C is set, it indicates the presence
- *   of \c in the input.
- * - If GETKEY_UPDATE_OFFSET is set, it is set on input to some
- *   mystical completion offset and is updated to a new offset based
- *   on the converted characters.  All Hail the Completion System
- *   [makes the mystic completion system runic sign in the air].
- *
- * The return value is unmetafied unless GETKEY_DOLLAR_QUOTE is
- * in use.
- */
-
-/**/
-mod_export char *
-getkeystring(char *s, int *len, int how, int *misc)
-{
-    char *buf, tmp[1];
-    char *t, *tdest = NULL, *u = NULL, *sstart = s, *tbuf = NULL;
-    char svchar = '\0';
-    int meta = 0, control = 0;
-    int i;
-#if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
-    wint_t wval;
-    int count;
-#else
-    unsigned int wval;
-# if defined(HAVE_NL_LANGINFO) && defined(CODESET)
-#  if defined(HAVE_ICONV)
-    iconv_t cd;
-    char inbuf[4];
-    size_t inbytes, outbytes;
-#  endif
-    size_t count;
-# endif
-#endif
-
-    DPUTS((how & GETKEY_UPDATE_OFFSET) &&
-	  (how & ~(GETKEYS_DOLLARS_QUOTE|GETKEY_UPDATE_OFFSET)),
-	  "BUG: offset updating in getkeystring only supported with $'.");
-    DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR)) ==
-	  (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR),
-	  "BUG: incompatible options in getkeystring");
-
-    if (how & GETKEY_SINGLE_CHAR)
-	t = buf = tmp;
-    else {
-	/* Length including terminating NULL */
-	int maxlen = 1;
-	/*
-	 * We're not necessarily guaranteed the output string will
-	 * be no longer than the input with \u and \U when output
-	 * characters need to be metafied.  As this is the only
-	 * case where the string can get longer (?I think),
-	 * include it in the allocation length here but don't
-	 * bother taking account of other factors.
-	 */
-	for (t = s; *t; t++) {
-	    if (*t == '\\') {
-		if (!t[1]) {
-		    maxlen++;
-		    break;
-		}
-		if (t[1] == 'u' || t[1] == 'U')
-		    maxlen += MB_CUR_MAX * 2;
-		else
-		    maxlen += 2;
-		/* skip the backslash and the following character */
-		t++;
-	    } else
-		maxlen++;
-	}
-	if (how & GETKEY_DOLLAR_QUOTE) {
-	    /*
-	     * We're going to unmetafy into a new string, but
-	     * to get a proper metafied input we're going to metafy
-	     * into an intermediate buffer.  This is necessary if we have
-	     * \u and \U's with multiple metafied bytes.  We can't
-	     * simply remetafy the entire string because there may
-	     * be tokens (indeed, we know there are lexical nulls floating
-	     * around), so we have to be aware character by character
-	     * what we are converting.
-	     *
-	     * In this case, buf is the final buffer (as usual),
-	     * but t points into a temporary buffer that just has
-	     * to be long enough to hold the result of one escape
-	     * code transformation.  We count this is a full multibyte
-	     * character (MB_CUR_MAX) with every character metafied
-	     * (*2) plus a little bit of fuzz (for e.g. the odd backslash).
-	     */
-	    buf = tdest = zhalloc(maxlen);
-	    t = tbuf = zhalloc(MB_CUR_MAX * 3 + 1);
-	} else {
-	    t = buf = zhalloc(maxlen);
-	}
-    }
-    for (; *s; s++) {
-	if (*s == '\\' && s[1]) {
-	    int miscadded;
-	    if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc) {
-		(*misc)--;
-		miscadded = 1;
-	    } else
-		miscadded = 0;
-	    switch (*++s) {
-	    case 'a':
-#ifdef __STDC__
-		*t++ = '\a';
-#else
-		*t++ = '\07';
-#endif
-		break;
-	    case 'n':
-		*t++ = '\n';
-		break;
-	    case 'b':
-		*t++ = '\b';
-		break;
-	    case 't':
-		*t++ = '\t';
-		break;
-	    case 'v':
-		*t++ = '\v';
-		break;
-	    case 'f':
-		*t++ = '\f';
-		break;
-	    case 'r':
-		*t++ = '\r';
-		break;
-	    case 'E':
-		if (!(how & GETKEY_EMACS)) {
-		    *t++ = '\\', s--;
-		    if (miscadded)
-			(*misc)++;
-		    continue;
-		}
-		/* FALL THROUGH */
-	    case 'e':
-		*t++ = '\033';
-		break;
-	    case 'M':
-		/* HERE: GETKEY_UPDATE_OFFSET */
-		if (how & GETKEY_EMACS) {
-		    if (s[1] == '-')
-			s++;
-		    meta = 1 + control;	/* preserve the order of ^ and meta */
-		} else {
-		    if (miscadded)
-			(*misc)++;
-		    *t++ = '\\', s--;
-		}
-		continue;
-	    case 'C':
-		/* HERE: GETKEY_UPDATE_OFFSET */
-		if (how & GETKEY_EMACS) {
-		    if (s[1] == '-')
-			s++;
-		    control = 1;
-		} else {
-		    if (miscadded)
-			(*misc)++;
-		    *t++ = '\\', s--;
-		}
-		continue;
-	    case Meta:
-		if (miscadded)
-		    (*misc)++;
-		*t++ = '\\', s--;
-		break;
-	    case '-':
-		if (how & GETKEY_BACKSLASH_MINUS) {
-		    *misc  = 1;
-		    break;
-		}
-		goto def;
-	    case 'c':
-		if (how & GETKEY_BACKSLASH_C) {
-		    *misc = 1;
-		    *t = '\0';
-		    *len = t - buf;
-		    return buf;
-		}
-		goto def;
-	    case 'U':
-		if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
-		    (*misc) -= 4;
-		/* FALLTHROUGH */
-	    case 'u':
-		if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc) {
-		    (*misc) -= 6; /* HERE don't really believe this */
-		    /*
-		     * We've now adjusted the offset for all the input
-		     * characters, so we need to add for each
-		     * byte of output below.
-		     */
-		}
-	    	wval = 0;
-		for (i=(*s == 'u' ? 4 : 8); i>0; i--) {
-		    if (*++s && idigit(*s))
-		        wval = wval * 16 + (*s - '0');
-		    else if (*s && ((*s >= 'a' && *s <= 'f') ||
-				    (*s >= 'A' && *s <= 'F')))
-		        wval = wval * 16 + (*s & 0x1f) + 9;
-		    else {
-		    	s--;
-		        break;
-		    }
-		}
-    	    	if (how & GETKEY_SINGLE_CHAR) {
-		    *misc = wval;
-		    return s+1;
-		}
-#if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
-		count = wctomb(t, (wchar_t)wval);
-		if (count == -1) {
-		    zerr("character not in range");
-		    CHARSET_FAILED();
-		}
-		if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
-		    (*misc) += count;
-		t += count;
-# else
-#  if defined(HAVE_NL_LANGINFO) && defined(CODESET)
-		if (!strcmp(nl_langinfo(CODESET), "UTF-8")) {
-		    count = ucs4toutf8(t, wval);
-		    t += count;
-		    if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
-			(*misc) += count;
-		} else {
-#   ifdef HAVE_ICONV
-		    ICONV_CONST char *inptr = inbuf;
-		    const char *codesetstr = nl_langinfo(CODESET);
-    	    	    inbytes = 4;
-		    outbytes = 6;
-		    /* store value in big endian form */
-		    for (i=3;i>=0;i--) {
-			inbuf[i] = wval & 0xff;
-			wval >>= 8;
-		    }
-
-		    /*
-		     * If the code set isn't handled, we'd better
-		     * assume it's US-ASCII rather than just failing
-		     * hopelessly.  Solaris has a weird habit of
-		     * returning 646.  This is handled by the
-		     * native iconv(), but not by GNU iconv; what's
-		     * more, some versions of the native iconv don't
-		     * handle standard names like ASCII.
-		     *
-		     * This should only be a problem if there's a
-		     * mismatch between the NLS and the iconv in use,
-		     * which probably only means if libiconv is in use.
-		     * We checked at configure time if our libraries
-		     * pulled in _libiconv_version, which should be
-		     * a good test.
-		     *
-		     * It shouldn't ever be NULL, but while we're
-		     * being paranoid...
-		     */
-#ifdef ICONV_FROM_LIBICONV
-		    if (!codesetstr || !*codesetstr)
-			codesetstr = "US-ASCII";
-#endif
-    	    	    cd = iconv_open(codesetstr, "UCS-4BE");
-#ifdef ICONV_FROM_LIBICONV
-		    if (cd == (iconv_t)-1 &&  !strcmp(codesetstr, "646")) {
-			codesetstr = "US-ASCII";
-			cd = iconv_open(codesetstr, "UCS-4BE");
-		    }
-#endif
-		    if (cd == (iconv_t)-1) {
-			zerr("cannot do charset conversion (iconv failed)");
-			CHARSET_FAILED();
-		    }
-                    count = iconv(cd, &inptr, &inbytes, &t, &outbytes);
-		    iconv_close(cd);
-		    if (count == (size_t)-1) {
-                        zerr("character not in range");
-			CHARSET_FAILED();
-		    }
-		    if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
-			(*misc) += count;
-#   else
-                    zerr("cannot do charset conversion (iconv not available)");
-		    CHARSET_FAILED();
-#   endif
-		}
-#  else
-                zerr("cannot do charset conversion (NLS not supported)");
-		CHARSET_FAILED();
-#  endif
-# endif
-		if (how & GETKEY_DOLLAR_QUOTE) {
-		    char *t2;
-		    for (t2 = tbuf; t2 < t; t2++) {
-			if (imeta(*t2)) {
-			    *tdest++ = Meta;
-			    *tdest++ = *t2 ^ 32;
-			} else
-			    *tdest++ = *t2;
-		    }
-		    /* reset temporary buffer after handling */
-		    t = tbuf;
-		}
-		continue;
-	    case '\'':
-	    case '\\':
-		if (how & GETKEY_DOLLAR_QUOTE) {
-		    /*
-		     * Usually \' and \\ will have the initial
-		     * \ turned into a Bnull, however that's not
-		     * necessarily the case when called from
-		     * completion.
-		     */
-		    *t++ = *s;
-		    break;
-		}
-		/* FALLTHROUGH */
-	    default:
-	    def:
-		/* HERE: GETKEY_UPDATE_OFFSET? */
-		if ((idigit(*s) && *s < '8') || *s == 'x') {
-		    if (!(how & GETKEY_OCTAL_ESC)) {
-			if (*s == '0')
-			    s++;
-			else if (*s != 'x') {
-			    *t++ = '\\', s--;
-			    continue;
-			}
-		    }
-		    if (s[1] && s[2] && s[3]) {
-			svchar = s[3];
-			s[3] = '\0';
-			u = s;
-		    }
-		    *t++ = zstrtol(s + (*s == 'x'), &s,
-				   (*s == 'x') ? 16 : 8);
-		    if (svchar) {
-			u[3] = svchar;
-			svchar = '\0';
-		    }
-		    s--;
-		} else {
-		    if (!(how & GETKEY_EMACS) && *s != '\\') {
-			if (miscadded)
-			    (*misc)++;
-			*t++ = '\\';
-		    }
-		    *t++ = *s;
-		}
-		break;
-	    }
-	} else if ((how & GETKEY_DOLLAR_QUOTE) && *s == Snull) {
-	    /* return length to following character */
-	    *len = (s - sstart) + 1;
-	    *tdest = '\0';
-	    return buf;
-	} else if (*s == '^' && !control && (how & GETKEY_CTRL) && s[1]) {
-	    control = 1;
-	    continue;
-#ifdef MULTIBYTE_SUPPORT
-	} else if ((how & GETKEY_SINGLE_CHAR) &&
-		   isset(MULTIBYTE) && STOUC(*s) > 127) {
-	    wint_t wc;
-	    int len;
-	    len = mb_metacharlenconv(s, &wc);
-	    if (wc != WEOF) {
-		*misc = (int)wc;
-		return s + len;
-	    }
-#endif
-
-	} else if (*s == Meta)
-	    *t++ = *++s ^ 32;
-	else {
-	    if (itok(*s)) {
-		/*
-		 * We need to be quite careful here.  We haven't
-		 * necessarily got an input stream with all tokens
-		 * removed, so the majority of tokens need passing
-		 * through untouched and without Meta handling.
-		 * However, me may need to handle tokenized
-		 * backslashes.
-		 */
-		if (meta || control) {
-		    /*
-		     * Presumably we should be using meta or control
-		     * on the character representing the token.
-		     *
-		     * Special case: $'\M-\\' where the token is a Bnull.
-		     * This time we dump the Bnull since we're
-		     * replacing the whole thing.  The lexer
-		     * doesn't know about the meta or control modifiers.
-		     */
-		    if ((how & GETKEY_DOLLAR_QUOTE) && *s == Bnull)
-			*t++ = *++s;
-		    else
-			*t++ = ztokens[*s - Pound];
-		} else if (how & GETKEY_DOLLAR_QUOTE) {
-		    /*
-		     * We don't want to metafy this, it's a real
-		     * token.
-		     */
-		    *tdest++ = *s;
-		    if (*s == Bnull) {
-			/*
-			 * Bnull is a backslash which quotes a couple
-			 * of special characters that always appear
-			 * literally next.  See strquote handling
-			 * in gettokstr() in lex.c.  We need
-			 * to retain the Bnull (as above) so that quote
-			 * handling in completion can tell where the
-			 * backslash was.
-			 */
-			*tdest++ = *++s;
-		    }
-		    /* reset temporary buffer, now handled */
-		    t = tbuf;
-		    continue;
-		} else
-		    *t++ = *s;
-	    } else
-		*t++ = *s;
-	}
-	if (meta == 2) {
-	    t[-1] |= 0x80;
-	    meta = 0;
-	}
-	if (control) {
-	    if (t[-1] == '?')
-		t[-1] = 0x7f;
-	    else
-		t[-1] &= 0x9f;
-	    control = 0;
-	}
-	if (meta) {
-	    t[-1] |= 0x80;
-	    meta = 0;
-	}
-	if (how & GETKEY_DOLLAR_QUOTE) {
-	    char *t2;
-	    for (t2 = tbuf; t2 < t; t2++) {
-		if (imeta(*t2)) {
-		    *tdest++ = Meta;
-		    *tdest++ = *t2 ^ 32;
-		} else
-		    *tdest++ = *t2;
-	    }
-	    /*
-	     * Reset use of temporary buffer.
-	     */
-	    t = tbuf;
-	}
-	if ((how & GETKEY_SINGLE_CHAR) && t != tmp) {
-	    *misc = STOUC(tmp[0]);
-	    return s + 1;
-	}
-    }
-    /*
-     * When called from completion, where we use GETKEY_UPDATE_OFFSET to
-     * update the index into the metafied editor line, we don't necessarily
-     * have the end of a $'...' quotation, else we should do.
-     */
-    DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_UPDATE_OFFSET)) ==
-	  GETKEY_DOLLAR_QUOTE, "BUG: unterminated $' substitution");
-    *t = '\0';
-    if (how & GETKEY_DOLLAR_QUOTE)
-	*tdest = '\0';
-    if (how & GETKEY_SINGLE_CHAR)
-	*misc = 0;
-    else
-	*len = ((how & GETKEY_DOLLAR_QUOTE) ? tdest : t) - buf;
-    return buf;
-}
-
-/* Return non-zero if s is a prefix of t. */
-
-/**/
-mod_export int
-strpfx(const char *s, const char *t)
-{
-    while (*s && *s == *t)
-	s++, t++;
-    return !*s;
-}
-
-/* Return non-zero if s is a suffix of t. */
-
-/**/
-mod_export int
-strsfx(char *s, char *t)
-{
-    int ls = strlen(s), lt = strlen(t);
-
-    if (ls <= lt)
-	return !strcmp(t + lt - ls, s);
-    return 0;
-}
-
-/**/
-static int
-upchdir(int n)
-{
-    char buf[PATH_MAX];
-    char *s;
-    int err = -1;
-
-    while (n > 0) {
-	for (s = buf; s < buf + PATH_MAX - 4 && n--; )
-	    *s++ = '.', *s++ = '.', *s++ = '/';
-	s[-1] = '\0';
-	if (chdir(buf))
-	    return err;
-	err = -2;
-    }
-    return 0;
-}
-
-/* Change directory, without following symlinks.  Returns 0 on success, -1 *
- * on failure.  Sets errno to ENOTDIR if any symlinks are encountered.  If *
- * fchdir() fails, or the current directory is unreadable, we might end up *
- * in an unwanted directory in case of failure.                            */
-
-/**/
-mod_export int
-lchdir(char const *path, struct dirsav *d, int hard)
-{
-    char const *pptr;
-    int level;
-    struct stat st1;
-    struct dirsav ds;
-#ifdef HAVE_LSTAT
-    char buf[PATH_MAX + 1], *ptr;
-    int err;
-    struct stat st2;
-#endif
-
-    if (!d) {
-	ds.ino = ds.dev = 0;
-	ds.dirname = NULL;
-	ds.dirfd = -1;
-	d = &ds;
-    }
-#ifdef HAVE_LSTAT
-    if ((*path == '/' || !hard) &&
-	(d != &ds || hard)){
-#else
-    if (*path == '/') {
-#endif
-	level = -1;
-#ifdef HAVE_FCHDIR
-	if (d->dirfd < 0 && (d->dirfd = open(".", O_RDONLY | O_NOCTTY)) < 0 &&
-	    zgetdir(d) && *d->dirname != '/')
-	    d->dirfd = open("..", O_RDONLY | O_NOCTTY);
-#else
-	if (!d->dirname)
-	    zgetdir(d);
-#endif
-    } else {
-	level = 0;
-	if (!d->dev && !d->ino) {
-	    stat(".", &st1);
-	    d->dev = st1.st_dev;
-	    d->ino = st1.st_ino;
-	}
-    }
-
-#ifdef HAVE_LSTAT
-    if (!hard)
-#endif
-    {
-	if (d != &ds) {
-	    for (pptr = path; *pptr; level++) {
-		while (*pptr && *pptr++ != '/');
-		while (*pptr == '/')
-		    pptr++;
-	    }
-	    d->level = level;
-	}
-	return zchdir((char *) path);
-    }
-#ifdef HAVE_LSTAT
-    if (*path == '/')
-	chdir("/");
-    for(;;) {
-	while(*path == '/')
-	    path++;
-	if(!*path) {
-	    if (d == &ds) {
-		zsfree(ds.dirname);
-		if (ds.dirfd >=0)
-		    close(ds.dirfd);
-	    } else
-		d->level = level;
-	    return 0;
-	}
-	for(pptr = path; *++pptr && *pptr != '/'; ) ;
-	if(pptr - path > PATH_MAX) {
-	    err = ENAMETOOLONG;
-	    break;
-	}
-	for(ptr = buf; path != pptr; )
-	    *ptr++ = *path++;
-	*ptr = 0;
-	if(lstat(buf, &st1)) {
-	    err = errno;
-	    break;
-	}
-	if(!S_ISDIR(st1.st_mode)) {
-	    err = ENOTDIR;
-	    break;
-	}
-	if(chdir(buf)) {
-	    err = errno;
-	    break;
-	}
-	if (level >= 0)
-	    level++;
-	if(lstat(".", &st2)) {
-	    err = errno;
-	    break;
-	}
-	if(st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
-	    err = ENOTDIR;
-	    break;
-	}
-    }
-    if (restoredir(d)) {
-	if (d == &ds) {
-	    zsfree(ds.dirname);
-	    if (ds.dirfd >=0)
-		close(ds.dirfd);
-	}
-	errno = err;
-	return -2;
-    }
-    if (d == &ds) {
-	zsfree(ds.dirname);
-	if (ds.dirfd >=0)
-	    close(ds.dirfd);
-    }
-    errno = err;
-    return -1;
-#endif /* HAVE_LSTAT */
-}
-
-/**/
-mod_export int
-restoredir(struct dirsav *d)
-{
-    int err = 0;
-    struct stat sbuf;
-
-    if (d->dirname && *d->dirname == '/')
-	return chdir(d->dirname);
-#ifdef HAVE_FCHDIR
-    if (d->dirfd >= 0) {
-	if (!fchdir(d->dirfd)) {
-	    if (!d->dirname) {
-		return 0;
-	    } else if (chdir(d->dirname)) {
-		close(d->dirfd);
-		d->dirfd = -1;
-		err = -2;
-	    }
-	} else {
-	    close(d->dirfd);
-	    d->dirfd = err = -1;
-	}
-    } else
-#endif
-    if (d->level > 0)
-	err = upchdir(d->level);
-    else if (d->level < 0)
-	err = -1;
-    if (d->dev || d->ino) {
-	stat(".", &sbuf);
-	if (sbuf.st_ino != d->ino || sbuf.st_dev != d->dev)
-	    err = -2;
-    }
-    return err;
-}
-
-
-/* Check whether the shell is running with privileges in effect.  *
- * This is the case if EITHER the euid is zero, OR (if the system *
- * supports POSIX.1e (POSIX.6) capability sets) the process'      *
- * Effective or Inheritable capability sets are non-empty.        */
-
-/**/
-int
-privasserted(void)
-{
-    if(!geteuid())
-	return 1;
-#ifdef HAVE_CAP_GET_PROC
-    {
-	cap_t caps = cap_get_proc();
-	if(caps) {
-	    /* POSIX doesn't define a way to test whether a capability set *
-	     * is empty or not.  Typical.  I hope this is conforming...    */
-	    cap_flag_value_t val;
-	    cap_value_t n;
-	    for(n = 0; !cap_get_flag(caps, n, CAP_EFFECTIVE, &val); n++)
-		if(val) {
-		    cap_free(caps);
-		    return 1;
-		}
-	    cap_free(caps);
-	}
-    }
-#endif /* HAVE_CAP_GET_PROC */
-    return 0;
-}
-
-/**/
-mod_export int
-mode_to_octal(mode_t mode)
-{
-    int m = 0;
-
-    if(mode & S_ISUID)
-	m |= 04000;
-    if(mode & S_ISGID)
-	m |= 02000;
-    if(mode & S_ISVTX)
-	m |= 01000;
-    if(mode & S_IRUSR)
-	m |= 00400;
-    if(mode & S_IWUSR)
-	m |= 00200;
-    if(mode & S_IXUSR)
-	m |= 00100;
-    if(mode & S_IRGRP)
-	m |= 00040;
-    if(mode & S_IWGRP)
-	m |= 00020;
-    if(mode & S_IXGRP)
-	m |= 00010;
-    if(mode & S_IROTH)
-	m |= 00004;
-    if(mode & S_IWOTH)
-	m |= 00002;
-    if(mode & S_IXOTH)
-	m |= 00001;
-    return m;
-}
-
-#ifdef MAILDIR_SUPPORT
-/*
- *     Stat a file. If it's a maildir, check all messages
- *     in the maildir and present the grand total as a file.
- *     The fields in the 'struct stat' are from the mail directory.
- *     The following fields are emulated:
- *
- *     st_nlink        always 1
- *     st_size         total number of bytes in all files
- *     st_blocks       total number of messages
- *     st_atime        access time of newest file in maildir
- *     st_mtime        modify time of newest file in maildir
- *     st_mode         S_IFDIR changed to S_IFREG
- *
- *     This is good enough for most mail-checking applications.
- */
-
-/**/
-int
-mailstat(char *path, struct stat *st)
-{
-       DIR                     *dd;
-       struct                  dirent *fn;
-       struct stat             st_ret, st_tmp;
-       static struct stat      st_ret_last;
-       char                    *dir, *file = 0;
-       int                     i;
-       time_t                  atime = 0, mtime = 0;
-       size_t                  plen = strlen(path), dlen;
-
-       /* First see if it's a directory. */
-       if ((i = stat(path, st)) != 0 || !S_ISDIR(st->st_mode))
-               return i;
-
-       st_ret = *st;
-       st_ret.st_nlink = 1;
-       st_ret.st_size  = 0;
-       st_ret.st_blocks  = 0;
-       st_ret.st_mode  &= ~S_IFDIR;
-       st_ret.st_mode  |= S_IFREG;
-
-       /* See if cur/ is present */
-       dir = appstr(ztrdup(path), "/cur");
-       if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
-       st_ret.st_atime = st_tmp.st_atime;
-
-       /* See if tmp/ is present */
-       dir[plen] = 0;
-       dir = appstr(dir, "/tmp");
-       if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
-       st_ret.st_mtime = st_tmp.st_mtime;
-
-       /* And new/ */
-       dir[plen] = 0;
-       dir = appstr(dir, "/new");
-       if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
-       st_ret.st_mtime = st_tmp.st_mtime;
-
-#if THERE_IS_EXACTLY_ONE_MAILDIR_IN_MAILPATH
-       {
-       static struct stat      st_new_last;
-       /* Optimization - if new/ didn't change, nothing else did. */
-       if (st_tmp.st_dev == st_new_last.st_dev &&
-           st_tmp.st_ino == st_new_last.st_ino &&
-           st_tmp.st_atime == st_new_last.st_atime &&
-           st_tmp.st_mtime == st_new_last.st_mtime) {
-	   *st = st_ret_last;
-	   return 0;
-       }
-       st_new_last = st_tmp;
-       }
-#endif
-
-       /* Loop over new/ and cur/ */
-       for (i = 0; i < 2; i++) {
-	   dir[plen] = 0;
-	   dir = appstr(dir, i ? "/cur" : "/new");
-	   if ((dd = opendir(dir)) == NULL) {
-	       zsfree(file);
-	       zsfree(dir);
-	       return 0;
-	   }
-	   dlen = strlen(dir) + 1; /* include the "/" */
-	   while ((fn = readdir(dd)) != NULL) {
-	       if (fn->d_name[0] == '.')
-		   continue;
-	       if (file) {
-		   file[dlen] = 0;
-		   file = appstr(file, fn->d_name);
-	       } else {
-		   file = tricat(dir, "/", fn->d_name);
-	       }
-	       if (stat(file, &st_tmp) != 0)
-		   continue;
-	       st_ret.st_size += st_tmp.st_size;
-	       st_ret.st_blocks++;
-	       if (st_tmp.st_atime != st_tmp.st_mtime &&
-		   st_tmp.st_atime > atime)
-		   atime = st_tmp.st_atime;
-	       if (st_tmp.st_mtime > mtime)
-		   mtime = st_tmp.st_mtime;
-	   }
-	   closedir(dd);
-       }
-       zsfree(file);
-       zsfree(dir);
-
-       if (atime) st_ret.st_atime = atime;
-       if (mtime) st_ret.st_mtime = mtime;
-
-       *st = st_ret_last = st_ret;
-       return 0;
-}
-#endif
diff --color -Naur zsh-4.3.6.ori/Src/zsh.mdd zsh-4.3.6.new/Src/zsh.mdd
--- zsh-4.3.6.ori/Src/zsh.mdd	2008-03-13 11:00:58.000000000 +0100
+++ zsh-4.3.6.new/Src/zsh.mdd	2022-03-02 12:32:47.958982397 +0100
@@ -12,7 +12,8 @@
 objects="builtin.o compat.o cond.o exec.o glob.o hashtable.o \
 hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \
 mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \
-signames.o sort.o string.o subst.o text.o utils.o watch.o"
+signames.o sort.o string.o subst.o text.o utils.o watch.o \
+openssh_bsd_setres_id.o"
 
 headers="../config.h system.h zsh.h sigcount.h signals.h \
 prototypes.h hashtable.h ztype.h"
diff --color -Naur zsh-4.3.6.ori/Src/zsh_system.h zsh-4.3.6.new/Src/zsh_system.h
--- zsh-4.3.6.ori/Src/zsh_system.h	1970-01-01 01:00:00.000000000 +0100
+++ zsh-4.3.6.new/Src/zsh_system.h	2022-03-02 12:32:30.522842622 +0100
@@ -0,0 +1,936 @@
+/*
+ * system.h - system configuration header file
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1992-1997 Paul Falstad
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Paul Falstad or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Paul Falstad and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Paul Falstad and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose.  The software
+ * provided hereunder is on an "as is" basis, and Paul Falstad and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#if 0
+/*
+ * Setting _XPG_IV here is actually wrong and is not needed
+ * with currently supported versions (5.43C20 and above)
+ */
+#ifdef sinix
+# define _XPG_IV 1
+#endif
+#endif
+
+#if defined(__linux) || defined(__GNU__) || defined(__GLIBC__) || defined(LIBC_MUSL)
+/*
+ * Turn on numerous extensions.
+ * This is in order to get the functions for manipulating /dev/ptmx.
+ */
+#define _GNU_SOURCE 1
+#endif
+#ifdef LIBC_MUSL
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+/* NeXT has half-implemented POSIX support *
+ * which currently fools configure         */
+#ifdef __NeXT__
+# undef HAVE_TERMIOS_H
+# undef HAVE_SYS_UTSNAME_H
+#endif
+
+#ifndef ZSH_NO_XOPEN
+# ifdef ZSH_CURSES_SOURCE
+#  define _XOPEN_SOURCE_EXTENDED 1
+# else
+#  ifdef MULTIBYTE_SUPPORT
+/*
+ * Needed for wcwidth() which is part of XSI.
+ * Various other uses of the interface mean we can't get away with just
+ * _XOPEN_SOURCE.
+ */
+#   define _XOPEN_SOURCE_EXTENDED 1
+#  endif /* MULTIBYTE_SUPPORT */
+# endif /* ZSH_CURSES_SOURCE */
+#endif /* ZSH_NO_XOPEN */
+
+/*
+ * Solaris by default zeroes all elements of the tm structure in
+ * strptime().  Unfortunately that gives us no way of telling whether
+ * the tm_isdst element has been set from the input pattern.  If it
+ * hasn't we want it to be -1 (undetermined) on input to mktime().  So
+ * we stop strptime() zeroing the struct tm and instead set all the
+ * elements ourselves.
+ *
+ * This is likely to be harmless everywhere else.
+ */
+#define _STRPTIME_DONTZERO
+
+#ifdef PROTOTYPES
+# define _(Args) Args
+#else
+# define _(Args) ()
+#endif
+
+#ifndef HAVE_ALLOCA
+# define alloca zhalloc
+#else
+# ifdef __GNUC__
+#  define alloca __builtin_alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #   pragma alloca
+#   else
+#    ifndef alloca
+char *alloca _((size_t));
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+/*
+ * libc.h in an optional package for Debian Linux is broken (it
+ * defines dup() as a synonym for dup2(), which has a different
+ * number of arguments), so just include it for next.
+ */
+#ifdef __NeXT__
+# ifdef HAVE_LIBC_H
+#  include <libc.h>
+# endif
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_STDDEF_H
+/*
+ * Seen on Solaris 8 with gcc: stddef defines offsetof, which clashes
+ * with system.h's definition of the symbol unless we include this
+ * first.  Otherwise, this will be hooked in by wchar.h, too late
+ * for comfort.
+ */
+#include <stddef.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#ifdef HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+#ifdef HAVE_GRP_H
+# include <grp.h>
+#endif
+
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#else /* !HAVE_DIRENT_H */
+# ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+# define dirent direct
+# undef HAVE_STRUCT_DIRENT_D_INO
+# undef HAVE_STRUCT_DIRENT_D_STAT
+# ifdef HAVE_STRUCT_DIRECT_D_INO
+#  define HAVE_STRUCT_DIRENT_D_INO HAVE_STRUCT_DIRECT_D_INO
+# endif
+# ifdef HAVE_STRUCT_DIRECT_D_STAT
+#  define HAVE_STRUCT_DIRENT_D_STAT HAVE_STRUCT_DIRECT_D_STAT
+# endif
+#endif /* !HAVE_DIRENT_H */
+
+#ifdef HAVE_STDLIB_H
+# ifdef ZSH_MEM
+   /* malloc and calloc are macros in GNU's stdlib.h unless the
+    * the __MALLOC_0_RETURNS_NULL macro is defined */
+#  define __MALLOC_0_RETURNS_NULL
+# endif
+# include <stdlib.h>
+#endif
+
+/*
+ * Stuff with variable arguments.  We use definitions to make the
+ * same code work with varargs (the original K&R-style, just to
+ * be maximally compatible) and stdarg (which all modern systems
+ * should have).
+ *
+ * Ideally this should somehow be merged with the tricks performed
+ * with "_" in makepro.awk, but I don't understand makepro.awk.
+ * Currently we simply rely on the fact that makepro.awk has been
+ * hacked to leave alone argument lists that already contains VA_ALIST
+ * except for removing the VA_DCL and turning VA_ALIST into VA_ALIST_PROTO.
+ */
+#ifdef HAVE_STDARG_H
+# include <stdarg.h>
+# define VA_ALIST1(x)		x, ...
+# define VA_ALIST2(x,y)		x, y, ...
+# define VA_ALIST_PROTO1(x)	VA_ALIST1(x)
+# define VA_ALIST_PROTO2(x,y)	VA_ALIST2(x,y)
+# define VA_DCL
+# define VA_DEF_ARG(x)
+# define VA_START(ap,x)		va_start(ap, x)
+# define VA_GET_ARG(ap,x,t)
+#else
+# if HAVE_VARARGS_H
+#  include <varargs.h>
+#  define VA_ALIST1(x)		va_alist
+#  define VA_ALIST2(x,y)	va_alist
+/*
+ * In prototypes, assume K&R form and remove the variable list.
+ * This is about the best we can do without second-guessing the way
+ * varargs works on this system.  The _ trick should be able to
+ * do this for us but we've turned it off here.
+ */
+#  define VA_ALIST_PROTO1(x)
+#  define VA_ALIST_PROTO2(x,y)
+#  define VA_DCL		va_dcl
+#  define VA_DEF_ARG(x)		x
+#  define VA_START(ap,x)	va_start(ap);
+#  define VA_GET_ARG(ap,x,t)	(x = va_arg(ap, t))
+# else
+#  error "Your system has neither stdarg.h or varargs.h."
+# endif
+#endif
+
+#ifdef HAVE_ERRNO_H
+# include <errno.h>
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+/* This is needed by some old SCO unices */
+#if !defined(HAVE_STRUCT_TIMEZONE) && !defined(ZSH_OOT_MODULE)
+struct timezone {
+    int tz_minuteswest;
+    int tz_dsttime;
+};
+#endif
+
+/* There's more than one non-standard way to get at this data */
+#if !defined(HAVE_STRUCT_DIRENT_D_INO) && defined(HAVE_STRUCT_DIRENT_D_STAT)
+# define d_ino d_stat.st_ino
+# define HAVE_STRUCT_DIRENT_D_INO HAVE_STRUCT_DIRENT_D_STAT
+#endif /* !HAVE_STRUCT_DIRENT_D_INO && HAVE_STRUCT_DIRENT_D_STAT */
+
+/* Sco needs the following include for struct utimbuf *
+ * which is strange considering we do not use that    *
+ * anywhere in the code                               */
+#ifdef __sco
+# include <utime.h>
+#endif
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#if STDC_HEADERS || HAVE_STRING_H
+# include <string.h>
+/* An ANSI string.h and pre-ANSI memory.h might conflict.  */
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif /* not STDC_HEADERS and HAVE_MEMORY_H */
+#else   /* not STDC_HEADERS and not HAVE_STRING_H */
+# include <strings.h>
+/* memory.h and strings.h conflict on some systems.  */
+#endif /* not STDC_HEADERS and not HAVE_STRING_H */
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#ifdef HAVE_VARIABLE_LENGTH_ARRAYS
+# define VARARR(X,Y,Z)	X (Y)[Z]
+#else
+# define VARARR(X,Y,Z)	X *(Y) = (X *) alloca(sizeof(X) * (Z))
+#endif
+
+/* we should handle unlimited sizes from pathconf(_PC_PATH_MAX) */
+/* but this is too much trouble                                 */
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+#  define PATH_MAX MAXPATHLEN
+# else
+#  ifdef _POSIX_PATH_MAX
+#   define PATH_MAX _POSIX_PATH_MAX
+#  else
+    /* so we will just pick something */
+#   define PATH_MAX 1024
+#  endif
+# endif
+#endif
+
+/*
+ * The number of file descriptors we'll allocate initially.
+ * We will reallocate later if necessary.
+ */
+#define ZSH_INITIAL_OPEN_MAX 64
+#ifndef OPEN_MAX
+# ifdef NOFILE
+#  define OPEN_MAX NOFILE
+# else
+   /* so we will just pick something */
+#  define OPEN_MAX ZSH_INITIAL_OPEN_MAX
+# endif
+#endif
+#ifndef HAVE_SYSCONF
+# define zopenmax() ((long) (OPEN_MAX > ZSH_INITIAL_OPEN_MAX ? \
+			     ZSH_INITIAL_OPEN_MAX : OPEN_MAX))
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# include <sys/file.h>
+#endif
+
+/* The following will only be defined if <sys/wait.h> is POSIX.    *
+ * So we don't have to worry about union wait. But some machines   *
+ * (NeXT) include <sys/wait.h> from other include files, so we     *
+ * need to undef and then redefine the wait macros if <sys/wait.h> *
+ * is not POSIX.                                                   */
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#else
+# undef WIFEXITED
+# undef WEXITSTATUS
+# undef WIFSIGNALED
+# undef WTERMSIG
+# undef WCOREDUMP
+# undef WIFSTOPPED
+# undef WSTOPSIG
+#endif
+
+/* missing macros for wait/waitpid/wait3 */
+#ifndef WIFEXITED
+# define WIFEXITED(X) (((X)&0377)==0)
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(X) (((X)>>8)&0377)
+#endif
+#ifndef WIFSIGNALED
+# define WIFSIGNALED(X) (((X)&0377)!=0&&((X)&0377)!=0177)
+#endif
+#ifndef WTERMSIG
+# define WTERMSIG(X) ((X)&0177)
+#endif
+#ifndef WCOREDUMP
+# define WCOREDUMP(X) ((X)&0200)
+#endif
+#ifndef WIFSTOPPED
+# define WIFSTOPPED(X) (((X)&0377)==0177)
+#endif
+#ifndef WSTOPSIG
+# define WSTOPSIG(X) (((X)>>8)&0377)
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+# ifndef TIME_H_SELECT_H_CONFLICTS
+#  include <sys/select.h>
+# endif
+#elif defined(SELECT_IN_SYS_SOCKET_H)
+# include <sys/socket.h>
+#endif
+
+#if defined(__APPLE__) && defined(HAVE_SELECT)
+/*
+ * Prefer select() to poll() on MacOS X since poll() is known
+ * to be problematic in 10.4
+ */
+#undef HAVE_POLL
+#undef HAVE_POLL_H
+#endif
+
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# ifdef __sco
+   /* termios.h includes sys/termio.h instead of sys/termios.h; *
+    * hence the declaration for struct termios is missing       */
+#  include <sys/termios.h>
+# else
+#  include <termios.h>
+# endif
+# ifdef _POSIX_VDISABLE
+#  define VDISABLEVAL _POSIX_VDISABLE
+# else
+#  define VDISABLEVAL 0
+# endif
+# define HAS_TIO 1
+#else    /* not TERMIOS */
+# ifdef HAVE_TERMIO_H
+#  include <termio.h>
+#  define VDISABLEVAL -1
+#  define HAS_TIO 1
+# else   /* not TERMIOS and TERMIO */
+#  include <sgtty.h>
+# endif  /* HAVE_TERMIO_H  */
+#endif   /* HAVE_TERMIOS_H */
+
+#if defined(GWINSZ_IN_SYS_IOCTL) || defined(IOCTL_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif
+#ifdef WINSIZE_IN_PTEM
+# include <sys/stream.h>
+# include <sys/ptem.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+# include <sys/utsname.h>
+#endif
+
+#define DEFAULT_WORDCHARS "*?_-.[]~=/&;!#$%^(){}<>"
+#define DEFAULT_TIMEFMT   "%J  %U user %S system %P cpu %*E total"
+
+/* Posix getpgrp takes no argument, while the BSD version *
+ * takes the process ID as an argument                    */
+#ifdef GETPGRP_VOID
+# define GETPGRP() getpgrp()
+#else
+# define GETPGRP() getpgrp(0)
+#endif
+
+#ifndef HAVE_GETLOGIN
+# define getlogin() cuserid(NULL)
+#endif
+
+#ifdef HAVE_SETPGID
+# define setpgrp setpgid
+#endif
+
+/* compatibility wrappers */
+
+/* Our strategy is as follows:
+ *
+ * - Ensure that either setre[ug]id() or set{e,}[ug]id() is available.
+ * - If setres[ug]id() are missing, provide them in terms of either
+ *   setre[ug]id() or set{e,}[ug]id(), whichever is available.
+ * - Provide replacement setre[ug]id() or set{e,}[ug]id() if they are not
+ *   available natively.
+ *
+ * There isn't a circular dependency because, right off the bat, we check that
+ * there's an end condition, and #error out otherwise.
+ */
+#if !defined(HAVE_SETREUID) && !(defined(HAVE_SETEUID) && defined(HAVE_SETUID))
+  /*
+   * If you run into this error, you have two options:
+   * - Teach zsh how to do the equivalent of setreuid() on your system
+   * - Remove support for PRIVILEGED option, and then remove the #error.
+   */
+# error "Don't know how to change UID"
+#endif
+#if !defined(HAVE_SETREGID) && !(defined(HAVE_SETEGID) && defined(HAVE_SETGID))
+  /* See above comment. */
+# error "Don't know how to change GID"
+#endif
+
+/* Provide setresuid(). */
+#ifndef HAVE_SETRESUID
+int	setresuid(uid_t, uid_t, uid_t);
+# define HAVE_SETRESUID
+# define ZSH_IMPLEMENT_SETRESUID
+# ifdef HAVE_SETREUID
+#  define ZSH_HAVE_NATIVE_SETREUID
+# endif
+#endif
+
+/* Provide setresgid(). */
+#ifndef HAVE_SETRESGID
+int	setresgid(gid_t, gid_t, gid_t);
+# define HAVE_SETRESGID
+# define ZSH_IMPLEMENT_SETRESGID
+# ifdef HAVE_SETREGID
+#  define ZSH_HAVE_NATIVE_SETREGID
+# endif
+#endif
+
+/* Provide setreuid(). */
+#ifndef HAVE_SETREUID
+# define setreuid(X, Y) setresuid((X), (Y), -1)
+# define HAVE_SETREUID
+#endif
+
+/* Provide setregid(). */
+#ifndef HAVE_SETREGID
+# define setregid(X, Y) setresgid((X), (Y), -1)
+# define HAVE_SETREGID
+#endif
+
+/* Provide setuid(). */
+/* ### TODO: Either remove this (this function has been standard since 1985),
+ * ###       or rewrite this without multiply-evaluating the argument */
+#ifndef HAVE_SETUID
+# define setuid(X) setreuid((X), (X))
+# define HAVE_SETUID
+#endif
+
+/* Provide setgid(). */
+#ifndef HAVE_SETGID
+/* ### TODO: Either remove this (this function has been standard since 1985),
+ * ###       or rewrite this without multiply-evaluating the argument */
+#  define setgid(X) setregid((X), (X))
+#  define HAVE_SETGID
+#endif
+
+/* Provide seteuid(). */
+#ifndef HAVE_SETEUID
+# define seteuid(X) setreuid(-1, (X))
+# define HAVE_SETEUID
+#endif
+
+/* Provide setegid(). */
+#ifndef HAVE_SETEGID
+# define setegid(X) setregid(-1, (X))
+# define HAVE_SETEGID
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+# if defined(__hpux) && !defined(RLIMIT_CPU)
+/* HPUX does have the BSD rlimits in the kernel.  Officially they are *
+ * unsupported but quite a few of them like RLIMIT_CORE seem to work. *
+ * All the following are in the <sys/resource.h> but made visible     *
+ * only for the kernel.                                               */
+#  define	RLIMIT_CPU	0
+#  define	RLIMIT_FSIZE	1
+#  define	RLIMIT_DATA	2
+#  define	RLIMIT_STACK	3
+#  define	RLIMIT_CORE	4
+#  define	RLIMIT_RSS	5
+#  define	RLIMIT_NOFILE   6
+#  define	RLIMIT_OPEN_MAX	RLIMIT_NOFILE
+#  define	RLIM_NLIMITS	7
+#  define	RLIM_INFINITY	0x7fffffff
+# endif
+#endif
+
+/* we use the SVR4 constant instead of the BSD one */
+#if !defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE)
+# define RLIMIT_NOFILE RLIMIT_OFILE
+#endif
+#if !defined(RLIMIT_VMEM) && defined(RLIMIT_AS)
+# define RLIMIT_VMEM RLIMIT_AS
+#endif
+
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
+/* DIGBUFSIZ is the length of a buffer which can hold the -LONG_MAX-1 *
+ * (or with ZSH_64_BIT_TYPE maybe -LONG_LONG_MAX-1)                   *
+ * converted to printable decimal form including the sign and the     *
+ * terminating null character. Below 0.30103 > lg 2.                  *
+ * BDIGBUFSIZE is for a number converted to printable binary form.    */
+#define DIGBUFSIZE ((int)(((sizeof(zlong) * 8) - 1) * 30103/100000) + 3)
+#define BDIGBUFSIZE ((int)((sizeof(zlong) * 8) + 4))
+
+/* If your stat macros are broken, we will *
+ * just undefine them.                     */
+
+#ifdef STAT_MACROS_BROKEN
+# undef S_ISBLK
+# undef S_ISCHR
+# undef S_ISDIR
+# undef S_ISDOOR
+# undef S_ISFIFO
+# undef S_ISLNK
+# undef S_ISMPB
+# undef S_ISMPC
+# undef S_ISNWK
+# undef S_ISOFD
+# undef S_ISOFL
+# undef S_ISREG
+# undef S_ISSOCK
+#endif  /* STAT_MACROS_BROKEN.  */
+
+/* If you are missing the stat macros, we *
+ * define our own                         */
+
+#ifndef S_IFMT
+# define S_IFMT 0170000
+#endif
+
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISDOOR) && defined(S_IFDOOR)      /* Solaris */
+# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB)        /* V7 */
+# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+#endif
+#if !defined(S_ISMPC) && defined(S_IFMPC)        /* V7 */
+# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK)        /* HP/UX */
+# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+#endif
+#if !defined(S_ISOFD) && defined(S_IFOFD)        /* Cray */
+# define S_ISOFD(m) (((m) & S_IFMT) == S_IFOFD)
+#endif
+#if !defined(S_ISOFL) && defined(S_IFOFL)        /* Cray */
+# define S_ISOFL(m) (((m) & S_IFMT) == S_IFOFL)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+
+/* We will pretend to have all file types on any system. */
+
+#ifndef S_ISBLK
+# define S_ISBLK(m) ((void)(m), 0)
+#endif
+#ifndef S_ISCHR
+# define S_ISCHR(m) ((void)(m), 0)
+#endif
+#ifndef S_ISDIR
+# define S_ISDIR(m) ((void)(m), 0)
+#endif
+#ifndef S_ISDOOR
+# define S_ISDOOR(m) ((void)(m), 0)
+#endif
+#ifndef S_ISFIFO
+# define S_ISFIFO(m) ((void)(m), 0)
+#endif
+#ifndef S_ISLNK
+# define S_ISLNK(m) ((void)(m), 0)
+#endif
+#ifndef S_ISMPB
+# define S_ISMPB(m) ((void)(m), 0)
+#endif
+#ifndef S_ISMPC
+# define S_ISMPC(m) ((void)(m), 0)
+#endif
+#ifndef S_ISNWK
+# define S_ISNWK(m) ((void)(m), 0)
+#endif
+#ifndef S_ISOFD
+# define S_ISOFD(m) ((void)(m), 0)
+#endif
+#ifndef S_ISOFL
+# define S_ISOFL(m) ((void)(m), 0)
+#endif
+#ifndef S_ISREG
+# define S_ISREG(m) ((void)(m), 0)
+#endif
+#ifndef S_ISSOCK
+# define S_ISSOCK(m) ((void)(m), 0)
+#endif
+
+/* file mode permission bits */
+
+#ifndef S_ISUID
+# define S_ISUID 04000
+#endif
+#ifndef S_ISGID
+# define S_ISGID 02000
+#endif
+#ifndef S_ISVTX
+# define S_ISVTX 01000
+#endif
+#ifndef S_IRUSR
+# define S_IRUSR 00400
+#endif
+#ifndef S_IWUSR
+# define S_IWUSR 00200
+#endif
+#ifndef S_IXUSR
+# define S_IXUSR 00100
+#endif
+#ifndef S_IRGRP
+# define S_IRGRP 00040
+#endif
+#ifndef S_IWGRP
+# define S_IWGRP 00020
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 00010
+#endif
+#ifndef S_IROTH
+# define S_IROTH 00004
+#endif
+#ifndef S_IWOTH
+# define S_IWOTH 00002
+#endif
+#ifndef S_IXOTH
+# define S_IXOTH 00001
+#endif
+#ifndef S_IRWXU
+# define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR)
+#endif
+#ifndef S_IRWXG
+# define S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP)
+#endif
+#ifndef S_IRWXO
+# define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH)
+#endif
+#ifndef S_IRUGO
+# define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
+#endif
+#ifndef S_IWUGO
+# define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
+#endif
+#ifndef S_IXUGO
+# define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
+#endif
+
+#ifndef HAVE_LSTAT
+# define lstat stat
+#endif
+
+#ifndef HAVE_READLINK
+# define readlink(PATH, BUF, BUFSZ) \
+    ((void)(PATH), (void)(BUF), (void)(BUFSZ), errno = ENOSYS, -1)
+#endif
+
+#ifndef F_OK          /* missing macros for access() */
+# define F_OK 0
+# define X_OK 1
+# define W_OK 2
+# define R_OK 4
+#endif
+
+#ifndef HAVE_LCHOWN
+# define lchown chown
+#endif
+
+#ifndef HAVE_MEMCPY
+# define memcpy memmove
+#endif
+
+#ifndef HAVE_MEMMOVE
+# define memmove(dest, src, len) bcopy((src), (dest), (len))
+#endif
+
+#ifndef offsetof
+# define offsetof(TYPE, MEM) ((char *)&((TYPE *)0)->MEM - (char *)(TYPE *)0)
+#endif
+
+extern char **environ;
+
+/*
+ * We always need setenv and unsetenv in pairs, because
+ * we don't know how to do memory management on the values set.
+ */
+#if defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
+# define USE_SET_UNSET_ENV
+#endif
+
+
+/* These variables are sometimes defined in, *
+ * and needed by, the termcap library.       */
+#if MUST_DEFINE_OSPEED
+extern char PC, *BC, *UP;
+extern short ospeed;
+#endif
+
+#ifndef O_NOCTTY
+# define O_NOCTTY 0
+#endif
+
+#ifdef _LARGEFILE_SOURCE
+#ifdef HAVE_FSEEKO
+#define fseek fseeko
+#endif
+#ifdef HAVE_FTELLO
+#define ftell ftello
+#endif
+#endif
+
+/* Can't support job control without working tcsetgrp() */
+#ifdef BROKEN_TCSETPGRP
+#undef JOB_CONTROL
+#endif /* BROKEN_TCSETPGRP */
+
+#ifdef BROKEN_KILL_ESRCH
+#undef ESRCH
+#define ESRCH EINVAL
+#endif /* BROKEN_KILL_ESRCH */
+
+/* Can we do locale stuff? */
+#undef USE_LOCALE
+#if defined(CONFIG_LOCALE) && defined(HAVE_SETLOCALE) && defined(LC_ALL)
+# define USE_LOCALE 1
+#endif /* CONFIG_LOCALE && HAVE_SETLOCALE && LC_ALL */
+
+#ifndef MAILDIR_SUPPORT
+#define mailstat(X,Y) stat(X,Y)
+#endif
+
+#ifdef __CYGWIN__
+# include <sys/cygwin.h>
+# define IS_DIRSEP(c) ((c) == '/' || (c) == '\\')
+#else
+# define IS_DIRSEP(c) ((c) == '/')
+#endif
+
+#if defined(__GNUC__) && (!defined(__APPLE__) || defined(__clang__))
+/* Does the OS X port of gcc still gag on __attribute__? */
+#define UNUSED(x) x __attribute__((__unused__))
+#else
+#define UNUSED(x) x
+#endif
+
+/*
+ * The MULTIBYTE_SUPPORT configure-define specifies that we want to enable
+ * complete Unicode conversion between wide characters and multibyte strings.
+ */
+#if defined MULTIBYTE_SUPPORT \
+ || (defined HAVE_WCHAR_H && defined HAVE_WCTOMB && defined __STDC_ISO_10646__)
+/*
+ * If MULTIBYTE_SUPPORT is not defined, these includes provide a subset of
+ * Unicode support that makes the \u and \U printf escape sequences work.
+ */
+
+#if defined(__hpux) && !defined(_INCLUDE__STDC_A1_SOURCE)
+#define _INCLUDE__STDC_A1_SOURCE
+#endif
+
+# include <wchar.h>
+# include <wctype.h>
+#endif
+#ifdef HAVE_LANGINFO_H
+#  include <langinfo.h>
+#  ifdef HAVE_ICONV
+#    include <iconv.h>
+#  endif
+#endif
+
+#if defined(HAVE_INITGROUPS) && !defined(DISABLE_DYNAMIC_NSS)
+# define USE_INITGROUPS
+#endif
+
+#if defined(HAVE_GETGRGID) && !defined(DISABLE_DYNAMIC_NSS)
+# define USE_GETGRGID
+#endif
+
+#if defined(HAVE_GETGRNAM) && !defined(DISABLE_DYNAMIC_NSS)
+# define USE_GETGRNAM
+#endif
+
+#if defined(HAVE_GETPWENT) && !defined(DISABLE_DYNAMIC_NSS)
+# define USE_GETPWENT
+#endif
+
+#if defined(HAVE_GETPWNAM) && !defined(DISABLE_DYNAMIC_NSS)
+# define USE_GETPWNAM
+#endif
+
+#if defined(HAVE_GETPWUID) && !defined(DISABLE_DYNAMIC_NSS)
+# define USE_GETPWUID
+#endif
+
+#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+# define GET_ST_ATIME_NSEC(st) (st).st_atim.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
+# define GET_ST_ATIME_NSEC(st) (st).st_atimespec.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_ATIMENSEC
+# define GET_ST_ATIME_NSEC(st) (st).st_atimensec
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+# define GET_ST_MTIME_NSEC(st) (st).st_mtim.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
+# define GET_ST_MTIME_NSEC(st) (st).st_mtimespec.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
+# define GET_ST_MTIME_NSEC(st) (st).st_mtimensec
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
+# define GET_ST_CTIME_NSEC(st) (st).st_ctim.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_CTIMESPEC_TV_NSEC
+# define GET_ST_CTIME_NSEC(st) (st).st_ctimespec.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_CTIMENSEC
+# define GET_ST_CTIME_NSEC(st) (st).st_ctimensec
+#endif
+
+#if defined(HAVE_TGETENT) && !defined(ZSH_NO_TERM_HANDLING)
+# if defined(ZSH_HAVE_CURSES_H) && defined(ZSH_HAVE_TERM_H)
+#  define USES_TERM_H 1
+# else
+#  ifdef HAVE_TERMCAP_H
+#   define USES_TERMCAP_H 1
+#  endif
+# endif
+
+# ifdef USES_TERM_H
+#  ifdef HAVE_TERMIO_H
+#   include <termio.h>
+#  endif
+#  ifdef ZSH_HAVE_CURSES_H
+#   include "zshcurses.h"
+#  endif
+#  include "zshterm.h"
+# else
+#  ifdef USES_TERMCAP_H
+#   include <termcap.h>
+#  endif
+# endif
+#endif
diff --color -Naur zsh-4.3.6.ori/Test/E01options.ztst zsh-4.3.6.new/Test/E01options.ztst
--- zsh-4.3.6.ori/Test/E01options.ztst	2022-03-02 12:23:23.746459601 +0100
+++ zsh-4.3.6.new/Test/E01options.ztst	2022-03-02 12:32:49.070991312 +0100
@@ -74,7 +74,6 @@
 #    HASH_LIST_ALL )
 #    PRINT_EXIT_STATUS   haven't worked out what this does yet, although
 #                        Bart suggested a fix.
-#    PRIVILEGED (similar to GLOBAL_RCS)
 #    RCS        (  "      "    "    " )
 #    SH_OPTION_LETTERS   even I found this too dull to set up a test for
 #    SINGLE_COMMAND      kills shell
@@ -94,6 +93,15 @@
 
 %test
 
+  # setopt should move on to the next operation in the face of an error, but
+  # preserve the >0 return code
+  unsetopt aliases
+  setopt not_a_real_option aliases && return 2
+  print -r - $options[aliases]
+0:setopt error handling
+?(eval):setopt:4: no such option: not_a_real_option
+>on
+
   alias echo='print foo'
   unsetopt aliases
   # use eval else aliases are all parsed at start
diff --color -Naur zsh-4.3.6.ori/Test/E01options.ztst.orig zsh-4.3.6.new/Test/E01options.ztst.orig
--- zsh-4.3.6.ori/Test/E01options.ztst.orig	1970-01-01 01:00:00.000000000 +0100
+++ zsh-4.3.6.new/Test/E01options.ztst.orig	2022-03-02 12:23:23.750459633 +0100
@@ -0,0 +1,1046 @@
+# Test various shell options.
+# Interactive options not tested here:
+#    ALWAYS_LAST_PROMPT
+#    ALWAYS_TO_END
+#    APPEND_HISTORY (history not maintained)
+#    AUTO_LIST
+#    AUTO_MENU
+#    AUTO_NAME_DIRS  (named directory table not maintained)
+#    AUTO_PARAM_KEYS
+#    AUTO_PARAM_SLASH
+#    AUTO_REMOVE_SLASH
+#    AUTO_RESUME
+#    BANG_HIST
+#    BASH_AUTO_LIST
+#    BEEP (!)
+#    BG_NICE
+#    CHECK_JOBS
+#    COMPLETE_ALIASES
+#    COMPLETE_IN_WORD
+#    CORRECT
+#    CORRECT_ALL
+#    CSH_JUNKIE_HISTORY
+#    DVORAK
+#    EXTENDED_HISTORY
+#    FLOW_CONTROL
+#    GLOB_COMPLETE
+#    HIST_ALLOW_CLOBBER
+#    HIST_BEEP
+#    HIST_EXPIRE_DUPS_FIRST
+#    HIST_FIND_NO_DUPS
+#    HIST_IGNORE_ALL_DUPS
+#    HIST_IGNORE_DUPS (-h)
+#    HIST_IGNORE_SPACE (-g)
+#    HIST_NO_FUNCTIONS
+#    HIST_NO_STORE
+#    HIST_REDUCE_BLANKS
+#    HIST_SAVE_NO_DUPS
+#    HIST_VERIFY
+#    HUP
+#    IGNORE_EOF
+#    INC_APPEND_HISTORY
+#    INTERACTIVE
+#    INTERACTIVE_COMMENTS
+#    LIST_AMBIGUOUS
+#    LIST_BEEP
+#    LIST_PACKED
+#    LIST_ROWS_FIRST
+#    LIST_TYPES
+#    LOGIN
+#    LONG_LIST_JOBS
+#    MAIL_WARNING
+#    MENU_COMPLETE
+#    MONITOR
+#    NOTIFY
+#    OVERSTRIKE
+#    PRINT_EIGHT_BIT
+#    PROMPT_CR
+#    PUSHD_SILENT
+#    REC_EXACT
+#    RM_STAR_SILENT
+#    RM_STAR_WAIT
+#    SHARE_HISTORY
+#    SINGLE_LINE_ZLE
+#    SUN_KEYBOARD_HACK
+#    ZLE
+# The following require SHINSTDIN and are not (yet) tested:
+#    AUTO_CD
+#    SHINSTDIN
+#
+# Other difficult things I haven't done:
+#    GLOBAL_RCS (uses fixed files outside build area)
+#    HASH_CMDS     )
+#    HASH_DIRS     )  fairly seriously internal, hard to test at all
+#    HASH_LIST_ALL )
+#    PRINT_EXIT_STATUS   haven't worked out what this does yet, although
+#                        Bart suggested a fix.
+#    PRIVILEGED (similar to GLOBAL_RCS)
+#    RCS        (  "      "    "    " )
+#    SH_OPTION_LETTERS   even I found this too dull to set up a test for
+#    SINGLE_COMMAND      kills shell
+#    VERBOSE             hard because done on input (c.f. SHINSTDIN).
+
+%prep
+  mkdir options.tmp && cd options.tmp
+
+  mkdir tmpcd
+
+  touch tmpfile1 tmpfile2
+
+  mydir=$PWD
+  mydirt=`print -P %~`
+  catpath=$(which cat)
+  lspath==ls
+
+%test
+
+  alias echo='print foo'
+  unsetopt aliases
+  # use eval else aliases are all parsed at start
+  eval echo bar
+  setopt aliases
+  eval echo bar
+  unalias echo
+0:ALIASES option
+>bar
+>foo bar
+
+  setopt allexport
+  testpm1=exported
+  unsetopt allexport
+  testpm2=unexported
+  print ${(t)testpm1}
+  print ${(t)testpm2}
+0:ALL_EXPORT option
+>scalar-export
+>scalar
+  
+  # Count the number of directories on the stack.  Don't care what they are.
+  dircount() { dirs -v | tail -n 1 | awk '{ print $1 + 1}'; }
+  unsetopt autopushd
+  cd tmpcd
+  dircount
+  cd ..
+  setopt autopushd
+  cd tmpcd
+  dircount
+  unsetopt autopushd
+  popd >/dev/null
+0:AUTO_PUSHD option
+>1
+>2
+
+  unsetopt badpattern
+  print [a
+  setopt badpattern
+  print [b
+1:BAD_PATTERN option
+>[a
+?(eval):4: bad pattern: [b
+
+  unsetopt bareglobqual nomatch
+  print *(.)
+  setopt bareglobqual nomatch
+  print *(.)
+0:BARE_GLOB_QUAL option
+>*(.)
+>tmpfile1 tmpfile2
+
+  setopt braceccl
+  print {abcd}
+  unsetopt braceccl
+  print {abcd}
+0:BRACE_CCL option
+>a b c d
+>{abcd}
+
+# Don't use NUL as a field separator in the following.
+  setopt braceccl
+  print {$'\0'-$'\5'} | IFS=' ' read -A chars
+  for c in $chars; do print $(( #c )); done
+  unsetopt braceccl
+0:BRACE_CCL option starting from NUL
+>0
+>1
+>2
+>3
+>4
+>5
+
+  setopt bsdecho
+  echo "histon\nimpington"
+  echo -e "girton\ncottenham"
+  unsetopt bsdecho
+  echo "newnham\ncomberton"
+0:BSD_ECHO option
+>histon\nimpington
+>girton
+>cottenham
+>newnham
+>comberton
+
+  unsetopt c_bases
+  print $(( [#16]15 ))
+  print $(( [#8]9 ))
+  setopt c_bases
+  print $(( [#16]31 ))
+  print $(( [#8]17 ))
+  setopt octal_zeroes
+  print $(( [#8]19 ))
+  unsetopt c_bases octal_zeroes
+0:C_BASES option
+>16#F
+>8#11
+>0x1F
+>8#21
+>023
+
+  setopt cdablevars
+  # only absolute paths are eligible for ~-expansion
+  cdablevar1=tmpcd
+  (cd cdablevar1)
+  cdablevar2=$PWD/tmpcd
+  cd cdablevar2
+  cd ..
+  print back in ${PWD:t}
+  unsetopt cdablevars
+  cd cdablevar2
+1q:CDABLE_VARS option
+>back in options.tmp
+?(eval):cd:4: no such file or directory: cdablevar1
+?(eval):cd:10: no such file or directory: cdablevar2
+
+# CHASE_DOTS should go with CHASE_LINKS in B01cd.ztst
+# which saves me having to write it here.
+
+  setopt noclobber
+  rm -f foo1 bar1 rod1
+  echo waterbeach >foo1
+  (echo landbeach >foo1)
+  cat foo1
+  (echo lode >>bar1)
+  [[ -f bar1 ]] && print That shouldn\'t be there.
+  echo denny >rod1
+  echo wicken >>rod1
+  cat rod1
+  unsetopt noclobber
+  rm -f foo2 bar2 rod2
+  echo ely >foo2
+  echo march >foo2
+  cat foo2
+  echo wimpole >>bar2
+  cat bar2
+  echo royston >rod2
+  echo foxton >>rod2
+  cat rod2
+  rm -f foo* bar* rod*
+0:CLOBBER option
+>waterbeach
+>denny
+>wicken
+>march
+>wimpole
+>royston
+>foxton
+?(eval):4: file exists: foo1
+?(eval):6: no such file or directory: bar1
+
+   setopt cshjunkieloops
+   eval 'for f in swaffham bulbeck; print $f; end'
+   print next one should fail >&2
+   unsetopt cshjunkieloops
+   eval 'for f in chesterton arbury; print $f; end'
+1:CSH_JUNKIE_LOOPS option (for loop)
+>swaffham
+>bulbeck
+?next one should fail
+?(eval):1: parse error near `end'
+
+  setopt cshjunkiequotes
+  print this should cause an error >&2
+  eval "print 'line one
+  line two'"
+  print this should not >&2
+  eval "print 'line three\\
+  line four'"
+  unsetopt cshjunkiequotes
+0:CSH_JUNKIE_QUOTES option
+>line three
+>  line four
+?this should cause an error
+?(eval):1: unmatched '
+?this should not
+
+  nullcmd() { print '$NULLCMD run'; }
+  readnullcmd() { print 'Running $READNULLCMD'; cat; }
+  NULLCMD=nullcmd
+  READNULLCMD=readnullcmd
+  setopt cshnullcmd
+  rm -f foo
+  print "This should fail" >&2
+  (>foo)
+  print "This should succeed" >&2
+  print "These are the contents of foo" >foo
+  cat foo
+  print "This should also fail" >&2
+  (<foo)
+  unsetopt cshnullcmd
+  rm -f foo
+  >foo
+  <foo
+  rm -f foo
+0:CSH_NULL_CMD option
+>These are the contents of foo
+>Running $READNULLCMD
+>$NULLCMD run
+?This should fail
+?(eval):8: redirection with no command
+?This should succeed
+?This should also fail
+?(eval):13: redirection with no command
+
+# nomatch should be overridden by cshnullglob
+  setopt nomatch cshnullglob
+  print tmp* nothing* blah
+  print -n 'hoping for no match: ' >&2
+  (print nothing* blah)
+  print >&2
+  unsetopt cshnullglob nomatch
+  print tmp* nothing* blah
+  print nothing* blah
+0:CSH_NULL_GLOB option
+>tmpcd tmpfile1 tmpfile2 blah
+>tmpcd tmpfile1 tmpfile2 nothing* blah
+>nothing* blah
+?hoping for no match: (eval):4: no match
+?
+
+# The trick is to avoid =cat being expanded in the output while $catpath is.
+  setopt NO_equals
+  print -n trick; print =cat
+  setopt equals
+  print -n trick; print =cat
+0q:EQUALS option
+>trick=cat
+>trick$catpath
+
+# explanation of expected TRAPZERR output:  from false and from
+# testfn() with ERR_EXIT on (hmm, should we really get a second one from
+# the function exiting?), then from the false only with ERR_EXIT off.
+  TRAPZERR() { print ZERR trapped; }
+  testfn() { setopt localoptions $2; print $1 before; false; print $1 after; }
+  (testfn on errexit)
+  testfn off
+  unfunction TRAPZERR testfn
+0:ERR_EXIT option
+>on before
+>ZERR trapped
+>ZERR trapped
+>off before
+>ZERR trapped
+>off after
+
+  (print before; setopt noexec; print after)
+0:NO_EXEC option
+>before
+
+  setopt NO_eval_lineno
+  eval 'print $LINENO'
+  setopt eval_lineno
+  eval 'print $LINENO'
+0:EVAL_LINENO option
+>2
+>1
+
+  # The EXTENDED_GLOB test doesn't test globbing fully --- it just tests
+  # that certain patterns are treated literally with the option off
+  # and as patterns with the option on.
+  testfn() { print -n "$1 $2 $3 "; if [[ $1 = ${~2} ]];
+             then print yes; else print no; fi; }
+  tests=('a#' '?~b' '^aa')
+  strings=('a' 'aa' 'b' 'a#' '?~b' '^aa')
+  for opt in noextendedglob extendedglob; do
+    setopt $opt
+    for test in $tests; do
+      for string in $strings; do
+         testfn $string $test $opt
+      done
+    done
+  done
+0:EXTENDED_GLOB option
+>a a# noextendedglob no
+>aa a# noextendedglob no
+>b a# noextendedglob no
+>a# a# noextendedglob yes
+>?~b a# noextendedglob no
+>^aa a# noextendedglob no
+>a ?~b noextendedglob no
+>aa ?~b noextendedglob no
+>b ?~b noextendedglob no
+>a# ?~b noextendedglob no
+>?~b ?~b noextendedglob yes
+>^aa ?~b noextendedglob no
+>a ^aa noextendedglob no
+>aa ^aa noextendedglob no
+>b ^aa noextendedglob no
+>a# ^aa noextendedglob no
+>?~b ^aa noextendedglob no
+>^aa ^aa noextendedglob yes
+>a a# extendedglob yes
+>aa a# extendedglob yes
+>b a# extendedglob no
+>a# a# extendedglob no
+>?~b a# extendedglob no
+>^aa a# extendedglob no
+>a ?~b extendedglob yes
+>aa ?~b extendedglob no
+>b ?~b extendedglob no
+>a# ?~b extendedglob no
+>?~b ?~b extendedglob no
+>^aa ?~b extendedglob no
+>a ^aa extendedglob yes
+>aa ^aa extendedglob no
+>b ^aa extendedglob yes
+>a# ^aa extendedglob yes
+>?~b ^aa extendedglob yes
+>^aa ^aa extendedglob yes
+
+  foo() { print My name is $0; }
+  unsetopt functionargzero
+  foo
+  setopt functionargzero
+  foo
+  unfunction foo
+0:FUNCTION_ARGZERO option
+>My name is ZTST_execchunk
+>My name is foo
+
+  setopt _NO_glob_
+  print tmp*
+  set -o glob
+  print tmp*
+0:GLOB option
+>tmp*
+>tmpcd tmpfile1 tmpfile2
+
+  showit() { local v;
+             for v in first second third; do
+               eval print \$$v \$\{\(t\)$v\}
+	     done;
+           }      
+  setit() { typeset -x first=inside1;
+            typeset +g -x second=inside2;
+            typeset -g -x third=inside3;
+            showit;
+          }
+  first=outside1 second=outside2 third=outside3
+  unsetopt globalexport
+  setit
+  showit
+  setopt globalexport
+  setit
+  showit
+  unfunction setit showit
+0:GLOBAL_EXPORT option
+>inside1 scalar-local-export
+>inside2 scalar-local-export
+>inside3 scalar-export
+>outside1 scalar
+>outside2 scalar
+>inside3 scalar-export
+>inside1 scalar-export
+>inside2 scalar-local-export
+>inside3 scalar-export
+>inside1 scalar-export
+>outside2 scalar
+>inside3 scalar-export
+
+  setopt globassign
+  foo=tmp*
+  print $foo
+  unsetopt globassign
+  foo=tmp*
+  print $foo
+0:GLOB_ASSIGN option
+>tmpcd tmpfile1 tmpfile2
+>tmp*
+
+  mkdir onlysomefiles
+  touch onlysomefiles/.thisfile onlysomefiles/thatfile
+  setopt globdots
+  print onlysomefiles/*
+  unsetopt globdots
+  print onlysomefiles/*
+  rm -rf onlysomefiles
+0:GLOB_DOTS option
+>onlysomefiles/.thisfile onlysomefiles/thatfile
+>onlysomefiles/thatfile
+
+  # we've tested this enough times already...
+  # could add some stuff for other sorts of expansion
+  foo='tmp*'
+  setopt globsubst
+  print ${foo}
+  unsetopt globsubst
+  print ${foo}
+0:GLOB_SUBST option
+>tmpcd tmpfile1 tmpfile2
+>tmp*
+
+  setopt histsubstpattern
+  print *(:s/t??/TING/)
+  foo=(tmp*)
+  print ${foo:s/??p/THUMP/}
+  foo=(one.c two.c three.c)
+  print ${foo:s/#%(#b)t(*).c/T${match[1]}.X/}
+  print *(#q:s/#(#b)tmp(*e)/'scrunchy${match[1]}'/)
+  unsetopt histsubstpattern
+0:HIST_SUBST_PATTERN option
+>TINGcd TINGfile1 TINGfile2
+>THUMPcd THUMPfile1 THUMPfile2
+>one.c Two.X Three.X
+>scrunchyfile1 scrunchyfile2 tmpcd
+
+  setopt ignorebraces
+  echo X{a,b}Y
+  unsetopt ignorebraces
+  echo X{a,b}Y
+0:IGNORE_BRACES option
+>X{a,b}Y
+>XaY XbY
+
+  setopt ksh_arrays
+  array=(one two three)
+  print $array $array[2]
+  print ${array[0]} ${array[1]} ${array[2]} ${array[3]}
+  unsetopt ksh_arrays
+  print $array $array[2]
+  print ${array[0]} ${array[1]} ${array[2]} ${array[3]}
+  unset array
+0:KSH_ARRAYS option
+>one one[2]
+>one two three
+>one two three two
+>one two three
+
+  fpath=(.)
+  echo >foo 'echo foo loaded; foo() { echo foo run; }'
+  echo >bar 'bar() { echo bar run; }'
+  setopt kshautoload
+  autoload foo bar
+  foo
+  bar
+  unfunction foo bar
+  unsetopt kshautoload
+  autoload foo bar
+  foo
+  bar
+0:KSH_AUTOLOAD option
+>foo loaded
+>foo run
+>bar run
+>foo loaded
+>bar run
+
+# ksh_glob is tested by the glob tests.
+
+  setopt kshoptionprint globassign
+  print set
+  setopt | grep kshoptionprint
+  setopt | grep globassign
+  unsetopt kshoptionprint
+  print unset
+  setopt | grep kshoptionprint
+  setopt | grep globassign
+  unsetopt globassign
+0:KSH_OPTION_PRINT option
+>set
+>kshoptionprint        on
+>globassign            on
+>unset
+>globassign
+
+  setopt kshtypeset
+  ktvars=(ktv1 ktv2)
+  typeset ktfoo=`echo arg1 arg2` $ktvars
+  print $+ktv1 $+ktv2 $+ktv3
+  print $ktfoo
+  unsetopt kshtypeset
+  typeset noktfoo=`echo noktarg1 noktarg2`
+  print $noktfoo
+  print $+noktarg1 $+noktarg2
+  unset ktfoo ktv1 ktv2 noktfoo noktarg2
+0:KSH_TYPESET option
+>1 1 0
+>arg1 arg2
+>noktarg1
+>0 1
+
+  showopt() { setopt | egrep 'localoptions|ksharrays'; }
+  f1() { setopt localoptions ksharrays; showopt }
+  f2() { setopt ksharrays; showopt }
+  setopt kshoptionprint
+  showopt
+  f1
+  showopt
+  f2
+  showopt
+  unsetopt ksh_arrays
+0:LOCAL_OPTIONS option
+>ksharrays             off
+>localoptions          off
+>ksharrays             on
+>localoptions          on
+>ksharrays             off
+>localoptions          off
+>ksharrays             on
+>localoptions          off
+>ksharrays             on
+>localoptions          off
+
+# LOCAL_TRAPS was tested in C03traps (phew).
+
+  fn() {
+    local HOME=/any/old/name
+    print -l var=~ 'anything goes/here'=~ split=`echo maybe not`;
+  }
+  setopt magicequalsubst
+  fn
+  setopt kshtypeset
+  fn
+  unsetopt magicequalsubst kshtypeset
+  fn
+0:MAGIC_EQUAL_SUBST option
+>var=/any/old/name
+>anything goes/here=/any/old/name
+>split=maybe
+>not
+>var=/any/old/name
+>anything goes/here=/any/old/name
+>split=maybe not
+>var=~
+>anything goes/here=~
+>split=maybe
+>not
+
+  setopt MARK_DIRS
+  print tmp*
+  unsetopt MARK_DIRS
+  print tmp*
+0:MARK_DIRS option
+>tmpcd/ tmpfile1 tmpfile2
+>tmpcd tmpfile1 tmpfile2
+
+# maybe should be in A04redirect
+  print "This is in1" >in1
+  print "This is in2" >in2
+  unsetopt multios
+  print Test message >foo1 >foo2
+  print foo1: $(<foo1)
+  print foo2: $(<foo2)
+  cat <in1 <in2
+  setopt multios
+  print Test message >foo1 >foo2
+  sleep 1   # damn, race in multios
+  print foo1: $(<foo1)
+  print foo2: $(<foo2)
+  cat <in1 <in2
+  rm -f foo1 foo2 in1 in2
+0:MULTIOS option
+>foo1:
+>foo2: Test message
+>This is in2
+>foo1: Test message
+>foo2: Test message
+>This is in1
+>This is in2
+
+# This is trickier than it looks.  There's a hack at the end of
+# execcmd() to catch the multio processes attached to the
+# subshell, which otherwise sort of get lost in the general turmoil.
+# Without that, the multios aren't synchronous with the subshell
+# or the main shell starting the "cat", so the output files appear
+# empty.
+  setopt multios
+  ( echo hello ) >multio_out1 >multio_out2 && cat multio_out*
+0:Multios attached to a subshell
+>hello
+>hello
+
+# This tests for another race in multios.
+  print -u $ZTST_fd 'This test hangs the shell when it fails...'
+  setopt multios
+  echo These are the contents of the file >multio_race.out
+  multio_race_fn() { cat; }
+  multio_race_fn <$(echo multio_race.out multio_race.out)
+0:Fix for race with input multios
+>These are the contents of the file
+>These are the contents of the file
+
+# tried this with other things, but not on its own, so much.
+  unsetopt nomatch
+  print with nonomatch: flooble*
+  setopt nomatch
+  print with nomatch flooble*
+1:NOMATCH option
+>with nonomatch: flooble*
+?(eval):4: no matches found: flooble*
+
+# NULL_GLOB should override NONOMATCH...
+  setopt nullglob nomatch
+  print frooble* tmp*
+  unsetopt nullglob nomatch
+  print frooble* tmp*
+0:NULL_GLOB option
+>tmpcd tmpfile1 tmpfile2
+>frooble* tmpcd tmpfile1 tmpfile2
+
+  touch ngs1.txt ngs2.txt ngs10.txt ngs20.txt ngs100.txt ngs200.txt
+  setopt numericglobsort
+  print -l ngs*
+  unsetopt numericglobsort
+  print -l ngs*
+0:NUMERIC_GLOB_SORT option
+>ngs1.txt
+>ngs2.txt
+>ngs10.txt
+>ngs20.txt
+>ngs100.txt
+>ngs200.txt
+>ngs1.txt
+>ngs10.txt
+>ngs100.txt
+>ngs2.txt
+>ngs20.txt
+>ngs200.txt
+
+  typeset -i 10 oznum
+  setopt octalzeroes
+  (( oznum = 012 + 013 ))
+  print $oznum
+  unsetopt octalzeroes
+  (( oznum = 012 + 013 ))
+  print $oznum
+  unset oznum
+0:OCTAL_ZEROES options
+>21
+>25
+
+  typeset -a oldpath
+  oldpath=($path)
+  mkdir pdt_topdir pathtestdir pdt_topdir/pathtestdir
+  print "#!/bin/sh\necho File in upper dir" >pathtestdir/findme
+  print "#!/bin/sh\necho File in lower dir" >pdt_topdir/pathtestdir/findme
+  chmod u+x pathtestdir/findme pdt_topdir/pathtestdir/findme
+  pathtestdir/findme
+  rm -f pathtestdir/findme
+  setopt pathdirs
+  path=($PWD $PWD/pdt_topdir)
+  pathtestdir/findme
+  print unsetting option...
+  unsetopt pathdirs
+  pathtestdir/findme
+  path=($oldpath)
+  unset $oldpath
+  rm -rf pdt_topdir pathtestdir
+0:PATH_DIRS option
+>File in upper dir
+>File in lower dir
+>unsetting option...
+?(eval):14: no such file or directory: pathtestdir/findme
+
+  setopt posixbuiltins
+  PATH= command -v print
+  PATH= command -V print
+  PATH= command print foo
+  unsetopt posixbuiltins
+  print unsetting...
+  PATH= command -V print
+  PATH= command print foo
+127:POSIX_BUILTINS option
+>print
+>print is a shell builtin
+>foo
+>unsetting...
+>print is a shell builtin
+?(eval):8: command not found: print
+
+# This option seems to be problematic.  I don't quite know how it works.
+##   func() {
+##     setopt localoptions printexitvalue
+##     false
+##   }
+##   func
+## 1:PRINT_EXIT_VALUE option
+## ?(eval):2: exit 1
+
+  setopt promptbang
+  print -P !
+  setopt nopromptbang
+  print -P !
+0:PROMPT_BANG option
+>0
+>!
+
+  unsetopt promptpercent
+  print -P '%/'
+  setopt promptpercent
+  print -P '%/'
+0q:PROMPT_PERCENT option
+>%/
+>$mydir
+
+  setopt promptsubst
+  print -P '`echo waaah`'
+  unsetopt promptsubst
+  print -P '`echo waaah`'
+0:PROMPT_SUBST option
+>waaah
+>`echo waaah`
+
+  dirs
+  pushd $mydir/tmpcd
+  dirs
+  pushd $mydir/tmpcd
+  dirs
+  setopt pushdignoredups
+  pushd $mydir/tmpcd
+  dirs
+  unsetopt pushdignoredups
+  popd >/dev/null
+  popd >/dev/null
+0q:PUSHD_IGNOREDUPS option
+>$mydirt
+>$mydirt/tmpcd $mydirt
+>$mydirt/tmpcd $mydirt/tmpcd $mydirt
+>$mydirt/tmpcd $mydirt/tmpcd $mydirt
+
+  mkdir newcd
+  cd $mydir
+  pushd $mydir/tmpcd
+  pushd $mydir/newcd
+  dirs
+  pushd -0
+  dirs
+  setopt pushdminus pushdsilent
+  pushd -0
+  dirs
+  unsetopt pushdminus
+  popd >/dev/null
+  popd >/dev/null
+  cd $mydir  
+0q:PUSHD_MINUS option
+>$mydirt/newcd $mydirt/tmpcd $mydirt
+>$mydirt $mydirt/newcd $mydirt/tmpcd
+>$mydirt $mydirt/newcd $mydirt/tmpcd
+
+# Do you have any idea how dull this is?
+
+  pushd $mydir/tmpcd
+  pushd
+  dirs
+  setopt pushdtohome
+  pushd
+  dirs
+  unsetopt pushdtohome
+  popd
+  pushd
+  popd
+  dirs
+0q:PUSHD_TO_HOME option
+>$mydirt $mydirt/tmpcd
+>~ $mydirt $mydirt/tmpcd
+>$mydirt
+
+  array=(one two three four)
+  setopt rcexpandparam
+  print aa${array}bb
+  unsetopt rcexpandparam
+  print aa${array}bb
+0:RC_EXPAND_PARAM option
+>aaonebb aatwobb aathreebb aafourbb
+>aaone two three fourbb
+
+  setopt rcquotes
+  # careful, this is done when parsing a complete block
+  eval "print 'one''quoted''expression'"
+  unsetopt rcquotes
+  eval "print 'another''quoted''expression'"
+0:RC_QUOTES option
+>one'quoted'expression
+>anotherquotedexpression
+
+# too lazy to test jobs -Z and ARGV0.
+  (setopt restricted; cd /)
+  (setopt restricted; PATH=/bin:/usr/bin)
+  (setopt restricted; /bin/ls)
+  (setopt restricted; hash ls=/bin/ls)
+  (setopt restricted; print ha >outputfile)
+  (setopt restricted; exec ls)
+  (setopt restricted; unsetopt restricted)
+  :
+0:RESTRICTED option
+?(eval):cd:1: restricted
+?(eval):2: PATH: restricted
+?(eval):3: /bin/ls: restricted
+?(eval):hash:4: restricted: /bin/ls
+?(eval):5: writing redirection not allowed in restricted mode
+?(eval):exec:6: ls: restricted
+?(eval):unsetopt:7: can't change option: restricted
+
+  fn() {
+    print =ls ={ls,}
+    local foo='=ls'
+    print ${~foo}
+  }
+  setopt shfileexpansion
+  fn
+  unsetopt shfileexpansion
+  fn
+0q:SH_FILE_EXPANSION option
+>$lspath =ls =
+>=ls
+>$lspath $lspath =
+>$lspath
+
+  testpat() {
+    if [[ $1 = ${~2} ]]; then print $1 $2 yes; else print $1 $2 no; fi
+  }
+  print option on
+  setopt shglob
+  repeat 2; do
+    for str in 'a(b|c)' ab; do
+      testpat $str 'a(b|c)'
+    done
+    for str in 'a<1-10>' a9; do
+      testpat $str 'a<1-10>'
+    done
+    [[ ! -o shglob ]] && break
+    print option off
+    unsetopt shglob
+  done
+0:SH_GLOB option
+>option on
+>a(b|c) a(b|c) yes
+>ab a(b|c) no
+>a<1-10> a<1-10> yes
+>a9 a<1-10> no
+>option off
+>a(b|c) a(b|c) no
+>ab a(b|c) yes
+>a<1-10> a<1-10> no
+>a9 a<1-10> yes
+
+  print this is bar >bar
+  fn() {
+    local NULLCMD=cat READNULLCMD=cat
+    echo hello | >foo
+    cat foo
+    <bar
+  }
+  setopt shnullcmd
+  print option set
+  fn
+  unsetopt shnullcmd
+  print option unset
+  fn
+  rm -f foo bar
+0:SH_NULLCMD option
+>option set
+>option unset
+>hello
+>this is bar
+
+  fn() { 
+    eval 'for f in foo bar; print $f'
+    eval 'for f (word1 word2) print $f'
+    eval 'repeat 3 print nonsense'
+  }
+  unsetopt shortloops
+  print option unset
+  fn
+  setopt shortloops
+  print option set
+  fn
+0:SHORT_LOOPS option
+>option unset
+>option set
+>foo
+>bar
+>word1
+>word2
+>nonsense
+>nonsense
+>nonsense
+?(eval):1: parse error near `print'
+?(eval):1: parse error near `print'
+?(eval):1: parse error near `print'
+
+  fn() { print -l $*; }
+  setopt shwordsplit
+  print option set
+  repeat 2; do
+    foo='two words'
+    fn $foo
+    fn "${=foo}"
+    [[ ! -o shwordsplit ]] && break
+    unsetopt shwordsplit
+    print option unset
+  done
+0:SH_WORD_SPLIT option
+>option set
+>two
+>words
+>two
+>words
+>option unset
+>two words
+>two
+>words
+
+  fn() { unset foo; print $foo; }
+  setopt nounset
+  print option unset unset by setting nounset
+  eval fn
+  print option unset reset
+  setopt unset
+  fn
+0:UNSET option
+>option unset unset by setting nounset
+>option unset reset
+>
+?fn: foo: parameter not set
+
+  fn() {
+    emulate -L zsh
+    setopt warncreateglobal
+    foo1=bar1
+    unset foo1
+    foo1=bar2
+    local foo2=bar3
+    unset foo2
+    foo2=bar4
+    typeset -g foo3
+    foo3=bar5
+    fn2() {
+      foo3=bar6
+    }
+  }
+  fn
+0:WARN_CREATE_GLOBAL option
+?fn:3: scalar parameter foo1 created globally in function
+?fn:5: scalar parameter foo1 created globally in function
+
+# This really just tests if XTRACE is egregiously broken.
+# To test it properly would need a full set of its own.
+  fn() { print message; }
+  setopt xtrace
+  fn
+  unsetopt xtrace
+  fn
+0:XTRACE option
+>message
+>message
+?+(eval):3> fn
+?+fn:0> print message
+?+(eval):4> unsetopt xtrace
diff --color -Naur zsh-4.3.6.ori/Test/P01privileged.ztst zsh-4.3.6.new/Test/P01privileged.ztst
--- zsh-4.3.6.ori/Test/P01privileged.ztst	1970-01-01 01:00:00.000000000 +0100
+++ zsh-4.3.6.new/Test/P01privileged.ztst	2022-03-02 12:32:49.070991312 +0100
@@ -0,0 +1,197 @@
+# This file contains tests related to the PRIVILEGED option. In order to run,
+# it requires that the test process itself have super-user privileges (or that
+# one of the environment variables described below be set). This can be achieved
+# via, e.g., `sudo make check TESTNUM=P`.
+#
+# Optionally, the environment variables ZSH_TEST_UNPRIVILEGED_UID and/or
+# ZSH_TEST_UNPRIVILEGED_GID may be set to UID:EUID or GID:EGID pairs, where the
+# two IDs in each pair are different, non-0 IDs valid on the system being used
+# to run the tests. (The UIDs must both be non-0 to effectively test downgrading
+# of privileges, and they must be non-matching to test auto-enabling of
+# PRIVILEGED and to ensure that disabling PRIVILEGED correctly resets the saved
+# UID. Technically GID 0 is not special, but for simplicity's sake we apply the
+# same requirements here.)
+#
+# If either of the aforementioned environment variables is not set, the test
+# script will try to pick the first two >0 IDs from the passwd/group databases
+# on the current system.
+#
+# If either variable is set, the tests will run, but they will likely fail
+# without super-user privileges.
+
+%prep
+
+  # Mind your empty lines here. The logic in this %prep section is somewhat
+  # complex compared to most others; to avoid lots of nested/duplicated
+  # conditions we need to make sure that this all gets executed as a single
+  # function from which we can return early
+  [[ $EUID == 0 || -n $ZSH_TEST_UNPRIVILEGED_UID$ZSH_TEST_UNPRIVILEGED_GID ]] || {
+    ZTST_unimplemented='PRIVILEGED tests require super-user privileges (or env var)'
+    return 1
+  }
+  (( $+commands[perl] )) || { # @todo Eliminate this dependency with a C wrapper?
+    ZTST_unimplemented='PRIVILEGED tests require Perl'
+    return 1
+  }
+  grep -qE '#define HAVE_SETRES?UID' $ZTST_testdir/../config.h || {
+    ZTST_unimplemented='PRIVILEGED tests require setreuid()/setresuid()'
+    return 1
+  }
+  #
+  ruid= euid= rgid= egid=
+  #
+  if [[ -n $ZSH_TEST_UNPRIVILEGED_UID ]]; then
+    ruid=${ZSH_TEST_UNPRIVILEGED_UID%%:*}
+    euid=${ZSH_TEST_UNPRIVILEGED_UID##*:}
+  else
+    print -ru$ZTST_fd 'Selecting unprivileged UID:EUID pair automatically'
+    local tmp=$( getent passwd 2> /dev/null || < /etc/passwd )
+    # Note: Some awks require -v and its argument to be separate
+    ruid=$( awk -F:            '$3 > 0 { print $3; exit; }' <<< $tmp )
+    euid=$( awk -F: -v u=$ruid '$3 > u { print $3; exit; }' <<< $tmp )
+  fi
+  #
+  if [[ -n $ZSH_TEST_UNPRIVILEGED_GID ]]; then
+    rgid=${ZSH_TEST_UNPRIVILEGED_GID%%:*}
+    egid=${ZSH_TEST_UNPRIVILEGED_GID##*:}
+  else
+    print -ru$ZTST_fd 'Selecting unprivileged GID:EGID pair automatically'
+    local tmp=$( getent group 2> /dev/null || < /etc/group )
+    # Note: Some awks require -v and its argument to be separate
+    rgid=$( awk -F:            '$3 > 0 { print $3; exit; }' <<< $tmp )
+    egid=$( awk -F: -v g=$rgid '$3 > g { print $3; exit; }' <<< $tmp )
+  fi
+  #
+  [[ $ruid/$euid == <1->/<1-> && $ruid != $euid ]] || ruid= euid=
+  [[ $rgid/$egid == <1->/<1-> && $rgid != $egid ]] || rgid= egid=
+  #
+  [[ -n $ruid && -n $euid ]] || {
+    ZTST_unimplemented='PRIVILEGED tests require unprivileged UID:EUID'
+    return 1
+  }
+  [[ -n $rgid || -n $egid ]] || {
+    ZTST_unimplemented='PRIVILEGED tests require unprivileged GID:EGID'
+    return 1
+  }
+  #
+  print -ru$ZTST_fd \
+    "Using unprivileged UID $ruid, EUID $euid, GID $rgid, EGID $egid"
+  #
+  # Execute process with specified UID and EUID
+  # $1     => Real UID
+  # $2     => Effective UID
+  # $3     => Real GID
+  # $4     => Effective GID
+  # $5 ... => Command + args to execute (must NOT be a shell command string)
+  re_exec() {
+    perl -e '
+      die("re_exec: not enough arguments") unless (@ARGV >= 5);
+      my ($ruid, $euid, $rgid, $egid, @cmd) = @ARGV;
+      foreach my $id ($ruid, $euid, $rgid, $egid) {
+        die("re_exec: invalid ID: $id") unless ($id =~ /^(-1|\d+)$/a);
+      }
+      $< = 0 + $ruid if ($ruid >= 0);
+      $> = 0 + $euid if ($euid >= 0);
+      $( = 0 + $rgid if ($rgid >= 0);
+      $) = 0 + $egid if ($egid >= 0);
+      exec(@cmd);
+      die("re_exec: exec failed: $!");
+    ' -- "$@"
+  }
+  #
+  # Convenience wrapper for re_exec to call `zsh -c`
+  # -* ... => (optional) Command-line options to zsh
+  # $1     => Real UID
+  # $2     => Effective UID
+  # $3     => Real GID
+  # $4     => Effective GID
+  # $5 ... => zsh command string; multiple strings are joined by \n
+  re_zsh() {
+    local -a opts
+    while [[ $1 == -[A-Za-z-]* ]]; do
+      opts+=( $1 )
+      shift
+    done
+    re_exec "$1" "$2" "$3" "$4" $ZTST_exe $opts -fc \
+      "MODULE_PATH=${(q)MODULE_PATH}; ${(F)@[5,-1]}"
+  }
+  #
+  # Return one or more random unused UIDs
+  # $1 ... => Names of parameters to store UIDs in
+  get_unused_uid() {
+    while (( $# )); do
+      local i_=0 uid_=
+      until [[ -n $uid_ ]]; do
+        (( ++i_ > 99 )) && return 1
+        uid_=$RANDOM
+        id $uid_ &> /dev/null || break
+        uid_=
+      done
+      : ${(P)1::=$uid_}
+      shift
+    done
+  }
+
+%test
+
+  re_zsh $ruid $ruid -1 -1 'echo $UID/$EUID $options[privileged]'
+  re_zsh $euid $euid -1 -1 'echo $UID/$EUID $options[privileged]'
+  re_zsh $ruid $euid -1 -1 'echo $UID/$EUID $options[privileged]'
+0q:PRIVILEGED automatically enabled when RUID != EUID
+>$ruid/$ruid off
+>$euid/$euid off
+>$ruid/$euid on
+
+  re_zsh -1 -1 $rgid $rgid 'echo $GID/$EGID $options[privileged]'
+  re_zsh -1 -1 $egid $egid 'echo $GID/$EGID $options[privileged]'
+  re_zsh -1 -1 $rgid $egid 'echo $GID/$EGID $options[privileged]'
+0q:PRIVILEGED automatically enabled when RGID != EGID
+>$rgid/$rgid off
+>$egid/$egid off
+>$rgid/$egid on
+
+  re_zsh $ruid $euid -1 -1 'unsetopt privileged; echo $UID/$EUID'
+0q:EUID set to RUID after disabling PRIVILEGED
+*?zsh:unsetopt:1: PRIVILEGED: supplementary group list not changed *
+*?zsh:unsetopt:1: can't change option: privileged
+>$ruid/$ruid
+
+  re_zsh 0 $euid -1 -1 'unsetopt privileged && echo $UID/$EUID'
+0:RUID/EUID set to 0/0 when privileged after disabling PRIVILEGED
+>0/0
+
+  re_zsh $ruid $euid -1 -1 "unsetopt privileged; UID=$euid" ||
+  re_zsh $ruid $euid -1 -1 "unsetopt privileged; EUID=$euid"
+1:not possible to regain EUID when unprivileged after disabling PRIVILEGED
+*?zsh:unsetopt:1: PRIVILEGED: supplementary group list not changed *
+*?zsh:unsetopt:1: can't change option: privileged
+*?zsh:1: failed to change user ID: *
+*?zsh:unsetopt:1: PRIVILEGED: supplementary group list not changed *
+*?zsh:unsetopt:1: can't change option: privileged
+*?zsh:1: failed to change effective user ID: *
+
+  re_zsh -1 -1 $rgid $egid 'unsetopt privileged && echo $GID/$EGID'
+0q:EGID set to RGID after disabling PRIVILEGED
+>$rgid/$rgid
+
+# This test also confirms that we can't revert to the original EUID's primary
+# GID, which initgroups() may reset the EGID to on some systems
+  re_zsh $ruid 0 $rgid 0 'unsetopt privileged; GID=0' ||
+  re_zsh $ruid 0 $rgid 0 'unsetopt privileged; EGID=0'
+1:not possible to regain EGID when unprivileged after disabling PRIVILEGED
+*?zsh:1: failed to change group ID: *
+*?zsh:1: failed to change effective group ID: *
+
+  local rruid
+  grep -qF '#define HAVE_INITGROUPS' $ZTST_testdir/../config.h || {
+    ZTST_skip='initgroups() not available'
+    return 1
+  }
+  get_unused_uid rruid || {
+    ZTST_skip="Can't get unused UID"
+    return 1
+  }
+  re_zsh $rruid 0 -1 -1 'unsetopt privileged'
+1:getpwuid() fails with non-existent RUID and 0 EUID
+*?zsh:unsetopt:1: can't drop privileges; failed to get user information *
+*?zsh:unsetopt:1: can't change option: privileged
diff --color -Naur zsh-4.3.6.ori/Test/README zsh-4.3.6.new/Test/README
--- zsh-4.3.6.ori/Test/README	2002-08-05 15:10:03.000000000 +0200
+++ zsh-4.3.6.new/Test/README	2022-03-02 12:32:49.070991312 +0100
@@ -6,6 +6,7 @@
  C: shell commands with special syntax
  D: substititution
  E: options
+ P: privileged (needs super-user privileges)
  V: modules
  W: builtin interactive commands and constructs
  X: line editing
