summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/INIT/C+probe870
-rw-r--r--src/cmd/INIT/CONVERT.mk260
-rw-r--r--src/cmd/INIT/MAPLIB.mk45
-rw-r--r--src/cmd/INIT/MSGFUN.mk2
-rw-r--r--src/cmd/INIT/MSGKEY.mk2
-rw-r--r--src/cmd/INIT/Makefile293
-rw-r--r--src/cmd/INIT/Mamfile1332
-rw-r--r--src/cmd/INIT/PROBE.mk13
-rw-r--r--src/cmd/INIT/RELEASE918
-rw-r--r--src/cmd/INIT/TEST.mk197
-rw-r--r--src/cmd/INIT/WWW.mk450
-rwxr-xr-xsrc/cmd/INIT/ar.ibm.risc9
-rwxr-xr-xsrc/cmd/INIT/cc.darwin73
-rwxr-xr-xsrc/cmd/INIT/cc.darwin.i38673
-rwxr-xr-xsrc/cmd/INIT/cc.darwin.i386-6473
-rwxr-xr-xsrc/cmd/INIT/cc.hp.ia6413
-rwxr-xr-xsrc/cmd/INIT/cc.hp.pa13
-rwxr-xr-xsrc/cmd/INIT/cc.hp.pa6411
-rwxr-xr-xsrc/cmd/INIT/cc.ibm.risc63
-rwxr-xr-xsrc/cmd/INIT/cc.ibm.risc.gcc36
-rwxr-xr-xsrc/cmd/INIT/cc.linux.i386-64-icc22
-rwxr-xr-xsrc/cmd/INIT/cc.linux.i386-icc22
-rwxr-xr-xsrc/cmd/INIT/cc.linux.ia64-icc22
-rwxr-xr-xsrc/cmd/INIT/cc.lynxos.i38681
-rwxr-xr-xsrc/cmd/INIT/cc.lynxos.ppc85
-rwxr-xr-xsrc/cmd/INIT/cc.mvs.390279
-rwxr-xr-xsrc/cmd/INIT/cc.next.i386158
-rwxr-xr-xsrc/cmd/INIT/cc.next.m68k9
-rwxr-xr-xsrc/cmd/INIT/cc.osf.alpha9
-rwxr-xr-xsrc/cmd/INIT/cc.pentium426
-rwxr-xr-xsrc/cmd/INIT/cc.sco.i3869
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips268
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips3110
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips3-o3265
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips490
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips4-n3265
-rwxr-xr-xsrc/cmd/INIT/cc.specialize35
-rwxr-xr-xsrc/cmd/INIT/cc.unix.mc68k76
-rw-r--r--src/cmd/INIT/crossexec.sh139
-rw-r--r--src/cmd/INIT/db.c37
-rw-r--r--src/cmd/INIT/ditto.sh460
-rw-r--r--src/cmd/INIT/dl.c33
-rw-r--r--src/cmd/INIT/execrate.sh179
-rw-r--r--src/cmd/INIT/filter.sh98
-rw-r--r--src/cmd/INIT/gdbm.c37
-rw-r--r--src/cmd/INIT/gdbm1.c37
-rw-r--r--src/cmd/INIT/gdbm2.c37
-rwxr-xr-xsrc/cmd/INIT/hello.c23
-rw-r--r--src/cmd/INIT/hosttype.tst6
-rw-r--r--src/cmd/INIT/hurl.sh207
-rw-r--r--src/cmd/INIT/iconv.c29
-rw-r--r--src/cmd/INIT/iffe.sh4639
-rw-r--r--src/cmd/INIT/iffe.tst1943
-rw-r--r--src/cmd/INIT/ignore.sh43
-rw-r--r--src/cmd/INIT/intl.c29
-rwxr-xr-xsrc/cmd/INIT/ld.hp.pa5
-rwxr-xr-xsrc/cmd/INIT/ldd.cygwin.i38622
-rwxr-xr-xsrc/cmd/INIT/ldd.darwin2
-rwxr-xr-xsrc/cmd/INIT/ldd.hp.pa21
-rwxr-xr-xsrc/cmd/INIT/ldd.ibm.risc16
-rwxr-xr-xsrc/cmd/INIT/ldd.lynxos1
-rwxr-xr-xsrc/cmd/INIT/ldd.mvs.39018
-rwxr-xr-xsrc/cmd/INIT/ldd.sgi2
-rw-r--r--src/cmd/INIT/m.c34
-rw-r--r--src/cmd/INIT/m2.c36
-rw-r--r--src/cmd/INIT/m3.c36
-rw-r--r--src/cmd/INIT/m4.c32
-rw-r--r--src/cmd/INIT/m5.c32
-rw-r--r--src/cmd/INIT/m6.c34
-rw-r--r--src/cmd/INIT/make.probe2242
-rw-r--r--src/cmd/INIT/mamake.c2375
-rw-r--r--src/cmd/INIT/mamake.rt40
-rw-r--r--src/cmd/INIT/mamake.tst63
-rw-r--r--src/cmd/INIT/mamprobe.sh267
-rw-r--r--src/cmd/INIT/mkdir.sh80
-rwxr-xr-xsrc/cmd/INIT/mktest.sh641
-rw-r--r--src/cmd/INIT/mprobe.sh30
-rw-r--r--src/cmd/INIT/nsl.c31
-rw-r--r--src/cmd/INIT/p.c24
-rw-r--r--src/cmd/INIT/package.mk1537
-rw-r--r--src/cmd/INIT/package.sh7302
-rw-r--r--src/cmd/INIT/probe.win32283
-rw-r--r--src/cmd/INIT/proto.c5283
-rw-r--r--src/cmd/INIT/ratz.c5293
-rw-r--r--src/cmd/INIT/regress.sh1463
-rw-r--r--src/cmd/INIT/release.c366
-rw-r--r--src/cmd/INIT/rt.sh479
-rw-r--r--src/cmd/INIT/silent.sh42
-rw-r--r--src/cmd/INIT/socket.c33
-rw-r--r--src/cmd/INIT/w.c30
-rw-r--r--src/cmd/INIT/w2.c27
-rw-r--r--src/cmd/Makefile1
-rw-r--r--src/cmd/Mamfile7
-rw-r--r--src/cmd/ksh93/COMPATIBILITY136
-rw-r--r--src/cmd/ksh93/DESIGN170
-rw-r--r--src/cmd/ksh93/Makefile248
-rw-r--r--src/cmd/ksh93/Mamfile1527
-rw-r--r--src/cmd/ksh93/OBSOLETE152
-rw-r--r--src/cmd/ksh93/PROMO.mm141
-rw-r--r--src/cmd/ksh93/README232
-rw-r--r--src/cmd/ksh93/RELEASE2888
-rw-r--r--src/cmd/ksh93/RELEASE88422
-rw-r--r--src/cmd/ksh93/RELEASE93455
-rw-r--r--src/cmd/ksh93/TYPES182
-rw-r--r--src/cmd/ksh93/bltins/alarm.c276
-rw-r--r--src/cmd/ksh93/bltins/cd_pwd.c250
-rw-r--r--src/cmd/ksh93/bltins/cflow.c117
-rw-r--r--src/cmd/ksh93/bltins/enum.c284
-rw-r--r--src/cmd/ksh93/bltins/getopts.c199
-rw-r--r--src/cmd/ksh93/bltins/hist.c312
-rw-r--r--src/cmd/ksh93/bltins/misc.c590
-rw-r--r--src/cmd/ksh93/bltins/mkservice.c494
-rw-r--r--src/cmd/ksh93/bltins/print.c1058
-rw-r--r--src/cmd/ksh93/bltins/read.c802
-rw-r--r--src/cmd/ksh93/bltins/regress.c343
-rw-r--r--src/cmd/ksh93/bltins/sleep.c235
-rw-r--r--src/cmd/ksh93/bltins/test.c667
-rw-r--r--src/cmd/ksh93/bltins/trap.c420
-rw-r--r--src/cmd/ksh93/bltins/typeset.c1471
-rw-r--r--src/cmd/ksh93/bltins/ulimit.c216
-rw-r--r--src/cmd/ksh93/bltins/umask.c98
-rw-r--r--src/cmd/ksh93/bltins/whence.c294
-rw-r--r--src/cmd/ksh93/builtins.mm648
-rw-r--r--src/cmd/ksh93/data/aliases.c57
-rw-r--r--src/cmd/ksh93/data/bash_pre_rc.sh255
-rw-r--r--src/cmd/ksh93/data/builtins.c1902
-rw-r--r--src/cmd/ksh93/data/keywords.c62
-rw-r--r--src/cmd/ksh93/data/lexstates.c417
-rw-r--r--src/cmd/ksh93/data/limits.c62
-rw-r--r--src/cmd/ksh93/data/math.tab75
-rw-r--r--src/cmd/ksh93/data/msg.c215
-rw-r--r--src/cmd/ksh93/data/options.c149
-rw-r--r--src/cmd/ksh93/data/signals.c244
-rw-r--r--src/cmd/ksh93/data/strdata.c104
-rw-r--r--src/cmd/ksh93/data/testops.c174
-rw-r--r--src/cmd/ksh93/data/variables.c136
-rw-r--r--src/cmd/ksh93/edit/completion.c572
-rw-r--r--src/cmd/ksh93/edit/edit.c1806
-rw-r--r--src/cmd/ksh93/edit/emacs.c1571
-rw-r--r--src/cmd/ksh93/edit/hexpand.c734
-rw-r--r--src/cmd/ksh93/edit/history.c1222
-rw-r--r--src/cmd/ksh93/edit/vi.c2753
-rw-r--r--src/cmd/ksh93/features/cmds4
-rw-r--r--src/cmd/ksh93/features/dynamic12
-rw-r--r--src/cmd/ksh93/features/externs13
-rw-r--r--src/cmd/ksh93/features/locale27
-rw-r--r--src/cmd/ksh93/features/math.sh305
-rwxr-xr-xsrc/cmd/ksh93/features/options47
-rw-r--r--src/cmd/ksh93/features/poll157
-rw-r--r--src/cmd/ksh93/features/rlimits3
-rw-r--r--src/cmd/ksh93/features/setjmp18
-rw-r--r--src/cmd/ksh93/features/sigfeatures49
-rw-r--r--src/cmd/ksh93/features/time35
-rw-r--r--src/cmd/ksh93/features/ttys3
-rwxr-xr-xsrc/cmd/ksh93/fun/dirs108
-rwxr-xr-xsrc/cmd/ksh93/fun/popd111
-rwxr-xr-xsrc/cmd/ksh93/fun/pushd111
-rw-r--r--src/cmd/ksh93/include/argnod.h145
-rw-r--r--src/cmd/ksh93/include/builtins.h202
-rw-r--r--src/cmd/ksh93/include/defs.h509
-rw-r--r--src/cmd/ksh93/include/edit.h286
-rw-r--r--src/cmd/ksh93/include/env.h50
-rw-r--r--src/cmd/ksh93/include/fault.h127
-rw-r--r--src/cmd/ksh93/include/fcin.h71
-rw-r--r--src/cmd/ksh93/include/history.h75
-rw-r--r--src/cmd/ksh93/include/io.h126
-rw-r--r--src/cmd/ksh93/include/jobs.h216
-rw-r--r--src/cmd/ksh93/include/lexstates.h157
-rw-r--r--src/cmd/ksh93/include/name.h268
-rw-r--r--src/cmd/ksh93/include/national.h37
-rw-r--r--src/cmd/ksh93/include/nval.h311
-rw-r--r--src/cmd/ksh93/include/path.h147
-rw-r--r--src/cmd/ksh93/include/regress.h66
-rw-r--r--src/cmd/ksh93/include/shell.h259
-rw-r--r--src/cmd/ksh93/include/shlex.h171
-rw-r--r--src/cmd/ksh93/include/shnodes.h221
-rw-r--r--src/cmd/ksh93/include/shtable.h65
-rw-r--r--src/cmd/ksh93/include/streval.h207
-rw-r--r--src/cmd/ksh93/include/terminal.h195
-rw-r--r--src/cmd/ksh93/include/test.h72
-rw-r--r--src/cmd/ksh93/include/timeout.h30
-rw-r--r--src/cmd/ksh93/include/ulimit.h174
-rw-r--r--src/cmd/ksh93/include/variables.h111
-rw-r--r--src/cmd/ksh93/include/version.h20
-rw-r--r--src/cmd/ksh93/ksh-regress.rt71
-rw-r--r--src/cmd/ksh93/ksh-regress.tst22544
-rwxr-xr-xsrc/cmd/ksh93/mamexec307
-rw-r--r--src/cmd/ksh93/mamstate.c73
-rw-r--r--src/cmd/ksh93/nval.3688
-rw-r--r--src/cmd/ksh93/sh.18142
-rw-r--r--src/cmd/ksh93/sh.memo3248
-rw-r--r--src/cmd/ksh93/sh/args.c892
-rw-r--r--src/cmd/ksh93/sh/arith.c549
-rw-r--r--src/cmd/ksh93/sh/array.c1843
-rw-r--r--src/cmd/ksh93/sh/bash.c423
-rw-r--r--src/cmd/ksh93/sh/defs.c48
-rw-r--r--src/cmd/ksh93/sh/deparse.c603
-rw-r--r--src/cmd/ksh93/sh/env.c255
-rw-r--r--src/cmd/ksh93/sh/expand.c468
-rw-r--r--src/cmd/ksh93/sh/fault.c672
-rw-r--r--src/cmd/ksh93/sh/fcin.c214
-rw-r--r--src/cmd/ksh93/sh/init.c2238
-rw-r--r--src/cmd/ksh93/sh/io.c2647
-rw-r--r--src/cmd/ksh93/sh/jobs.c2055
-rw-r--r--src/cmd/ksh93/sh/lex.c2516
-rw-r--r--src/cmd/ksh93/sh/macro.c2814
-rw-r--r--src/cmd/ksh93/sh/main.c787
-rw-r--r--src/cmd/ksh93/sh/name.c3684
-rw-r--r--src/cmd/ksh93/sh/nvdisc.c1468
-rw-r--r--src/cmd/ksh93/sh/nvtree.c1161
-rw-r--r--src/cmd/ksh93/sh/nvtype.c1709
-rw-r--r--src/cmd/ksh93/sh/parse.c2082
-rw-r--r--src/cmd/ksh93/sh/path.c1824
-rw-r--r--src/cmd/ksh93/sh/pmain.c46
-rw-r--r--src/cmd/ksh93/sh/shcomp.c177
-rw-r--r--src/cmd/ksh93/sh/streval.c1023
-rw-r--r--src/cmd/ksh93/sh/string.c730
-rw-r--r--src/cmd/ksh93/sh/subshell.c780
-rw-r--r--src/cmd/ksh93/sh/suid_exec.c509
-rw-r--r--src/cmd/ksh93/sh/tdump.c262
-rw-r--r--src/cmd/ksh93/sh/timers.c248
-rw-r--r--src/cmd/ksh93/sh/trestore.c353
-rw-r--r--src/cmd/ksh93/sh/waitevent.c54
-rw-r--r--src/cmd/ksh93/sh/xec.c3991
-rw-r--r--src/cmd/ksh93/shell.3414
-rwxr-xr-xsrc/cmd/ksh93/tests/alias.sh102
-rwxr-xr-xsrc/cmd/ksh93/tests/append.sh86
-rwxr-xr-xsrc/cmd/ksh93/tests/arith.sh737
-rwxr-xr-xsrc/cmd/ksh93/tests/arrays.sh588
-rwxr-xr-xsrc/cmd/ksh93/tests/arrays2.sh212
-rwxr-xr-xsrc/cmd/ksh93/tests/attributes.sh418
-rwxr-xr-xsrc/cmd/ksh93/tests/basic.sh513
-rwxr-xr-xsrc/cmd/ksh93/tests/bracket.sh340
-rwxr-xr-xsrc/cmd/ksh93/tests/builtins.sh562
-rwxr-xr-xsrc/cmd/ksh93/tests/case.sh85
-rwxr-xr-xsrc/cmd/ksh93/tests/comvar.sh689
-rw-r--r--src/cmd/ksh93/tests/comvario.sh686
-rwxr-xr-xsrc/cmd/ksh93/tests/coprocess.sh360
-rwxr-xr-xsrc/cmd/ksh93/tests/cubetype.sh213
-rwxr-xr-xsrc/cmd/ksh93/tests/enum.sh68
-rwxr-xr-xsrc/cmd/ksh93/tests/exit.sh80
-rwxr-xr-xsrc/cmd/ksh93/tests/expand.sh126
-rwxr-xr-xsrc/cmd/ksh93/tests/functions.sh1157
-rwxr-xr-xsrc/cmd/ksh93/tests/glob.sh374
-rwxr-xr-xsrc/cmd/ksh93/tests/grep.sh105
-rwxr-xr-xsrc/cmd/ksh93/tests/heredoc.sh496
-rwxr-xr-xsrc/cmd/ksh93/tests/io.sh484
-rwxr-xr-xsrc/cmd/ksh93/tests/leaks.sh68
-rwxr-xr-xsrc/cmd/ksh93/tests/locale.sh319
-rw-r--r--src/cmd/ksh93/tests/math.sh202
-rwxr-xr-xsrc/cmd/ksh93/tests/nameref.sh658
-rwxr-xr-xsrc/cmd/ksh93/tests/options.sh544
-rwxr-xr-xsrc/cmd/ksh93/tests/path.sh375
-rwxr-xr-xsrc/cmd/ksh93/tests/pointtype.sh138
-rwxr-xr-xsrc/cmd/ksh93/tests/pty.sh442
-rwxr-xr-xsrc/cmd/ksh93/tests/quoting.sh369
-rwxr-xr-xsrc/cmd/ksh93/tests/quoting2.sh215
-rw-r--r--src/cmd/ksh93/tests/readcsv.sh65
-rwxr-xr-xsrc/cmd/ksh93/tests/recttype.sh70
-rwxr-xr-xsrc/cmd/ksh93/tests/restricted.sh83
-rwxr-xr-xsrc/cmd/ksh93/tests/return.sh183
-rwxr-xr-xsrc/cmd/ksh93/tests/select.sh67
-rwxr-xr-xsrc/cmd/ksh93/tests/shtests235
-rwxr-xr-xsrc/cmd/ksh93/tests/sigchld.sh160
-rwxr-xr-xsrc/cmd/ksh93/tests/signal.sh435
-rwxr-xr-xsrc/cmd/ksh93/tests/statics.sh690
-rwxr-xr-xsrc/cmd/ksh93/tests/subshell.sh582
-rwxr-xr-xsrc/cmd/ksh93/tests/substring.sh628
-rwxr-xr-xsrc/cmd/ksh93/tests/tilde.sh101
-rwxr-xr-xsrc/cmd/ksh93/tests/timetype.sh81
-rwxr-xr-xsrc/cmd/ksh93/tests/treemove.sh163
-rwxr-xr-xsrc/cmd/ksh93/tests/types.sh632
-rwxr-xr-xsrc/cmd/ksh93/tests/variables.sh665
-rwxr-xr-xsrc/cmd/ksh93/tests/vartree1.sh215
-rwxr-xr-xsrc/cmd/ksh93/tests/vartree2.sh335
275 files changed, 167154 insertions, 0 deletions
diff --git a/src/cmd/INIT/C+probe b/src/cmd/INIT/C+probe
new file mode 100644
index 0000000..f427742
--- /dev/null
+++ b/src/cmd/INIT/C+probe
@@ -0,0 +1,870 @@
+:
+### this script contains archaic constructs that work with all sh variants ###
+# Glenn Fowler
+# AT&T Research
+#
+# @(#)C probe (AT&T Research) 2012-02-29
+#
+# probe [ -d ] c-compiler-path [ attributes ]
+#
+# common C probe preamble for the tool specific probes
+#
+# NOTE: some cc -E's do syntax analysis!
+
+#
+# probe_* are first eval'd and then attempted from left to right
+#
+
+probe_binding="-dy -dn -Bdynamic -Bstatic '-Wl,-ashared -Wl,+s' -Wl,-aarchive -call_shared -non_shared -dynamic -static -bshared -bstatic '' -static"
+probe_env="CC_OPTIONS CCOPTS LD_OPTIONS LDOPTS LIBPATH LPATH"
+probe_include="stdio.h iostream.h complex.h ctype.h plot.h stdarg.h varargs.h ranlib.h hash.h sys/types.h stab.h cmath cstdio iostream string"
+probe_longlong="long 'long long'"
+probe_longlong_t="__int64_t _int64_t __int64 _int64 int64"
+probe_l="l yyreject m sin mopt sin"
+probe_lxx="C exit ++ exit g++ exit"
+probe_ppprefix="a n"
+probe_size="size"
+probe_src="cxx C cc c"
+probe_sa=".sa"
+probe_sd=".dll .lib .dll .x"
+probe_sdb=".pdb"
+probe_so=".dylib .so .sl"
+probe_symprefix="_"
+probe_verbose="'-v -v' '-# -#' '-d -d' -dryrun '-V -V'"
+probe_version="--version -V -version -v"
+
+#
+# the following are set by the preamble for the tool specific probe
+#
+
+cc=cc
+debug=
+dir=.
+dll=.dll
+dynamic=
+exe=exe
+executable="test -x"
+hosted=
+ifs=${IFS-'
+ '}
+obj=o
+ppenv=
+ppopt=
+predef=
+prepred=
+sa=
+sd=
+sdb=
+so=
+sov=
+static=
+stdlib=
+stdpp=
+suffix_command=
+if test "" != "$TMPDIR" -a -d "$TMPDIR"
+then tmpdir=$TMPDIR
+else tmpdir=/tmp
+fi
+tmpdir=$tmpdir/probe$$
+undef="define defined elif else endif error if ifdef ifndef include line pragma undef __STDC__ __STDPP__ __ARGC__ __BASE__ __BASE_FILE__ __DATE__ __FILE__ __FUNCTION__ __INCLUDE_LEVEL__ __LINE__ __PATH__ __TIME__ __TIMESTAMP__ __VERSION__"
+version_flags=
+version_stamp=
+version_string=
+
+#
+# constrain the environment
+#
+
+DISPLAY=
+LC_ALL=C
+export DISPLAY LC_ALL
+
+#
+# now the common probes
+#
+
+while :
+do case $1 in
+ -d) debug=1 ;;
+ -*) set ''; break ;;
+ *) break ;;
+ esac
+ shift
+done
+
+cc=$1
+case $cc in
+[\\/]*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\*)
+ ;;
+*) echo "Usage: $0 [ -d ] c-compiler-path [ attributes ]" >&2
+ exit 1
+ ;;
+esac
+ATTRIBUTES=
+eval $2
+_probe_PATH=$PATH
+PATH=/usr/bin:/bin:$PATH
+
+case $0 in
+*[\\/]*) dir=`echo $0 | sed -e 's,[\\/][\\/]*[^\\/]*\$,,'` ;;
+esac
+
+$executable . 2>/dev/null || executable='test -r'
+
+case $SHELL in
+[\\/]*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\*)
+ sh=$SHELL
+ ;;
+*) sh=/bin/sh
+ ;;
+esac
+
+trap 'code=$?; cd ..; rm -rf $tmpdir; exit $code' 0 1 2 3
+mkdir $tmpdir
+cd $tmpdir
+
+exec 3>&1 4>&2 </dev/null
+case $debug in
+"") exec >/dev/null 2>&1
+ (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0
+ ;;
+*) PS4='+$LINENO+ '
+ set -x
+ ;;
+esac
+
+if (xxx=xxx; unset xxx)
+then UNSET=1
+else UNSET=
+fi
+eval set x $probe_env
+while :
+do shift
+ case $# in
+ 0) break ;;
+ esac
+ eval x='$'$1
+ case $x in
+ '') continue ;;
+ esac
+ case $1 in
+ *PATH) _probe_export="$_probe_export $1='$x'" ;;
+ esac
+ case $UNSET in
+ '') eval $1=
+ export $1
+ ;;
+ *) unset $1
+ ;;
+ esac
+done
+
+if test -f "$dir/probe.ini"
+then . "$dir/probe.ini"
+ IFS=$ifs
+fi
+
+mkdir suffix
+cd suffix
+for src in $probe_src
+do echo "int main(){return 0;}" > ../test.$src
+ rm -f test*
+ if $cc -c ../test.$src
+ then set test.*
+ if test -f "$1"
+ then o="$*"
+ mv $* ..
+ for i in $o
+ do if $cc -o test.exe ../$i
+ then obj=`echo "$i" | sed -e 's,test.,,'`
+ $executable test.exe || executable="test -r"
+ set test*
+ rm *
+ if $cc -o test ../$i
+ then rm $*
+ set test.*
+ if $executable "$1"
+ then exe=`echo "$1" | sed -e 's,test.,,'`
+ suffix_command=.$exe
+ fi
+ fi
+ break 2
+ fi
+ done
+ fi
+ fi
+done
+cd ..
+
+case $src in
+c) ;;
+*) echo '// (
+int
+main()
+{
+ class { public: int i; } j;
+ j.i = 0;
+ int k = j.i + 1;
+ return k;
+}' > dialect.$src
+ if $cc -c dialect.$src && $cc -o dialect.$exe dialect.$obj && $executable dialect.$exe
+ then mv dialect.$src dialect.c
+ rm -f dialect.$obj dialect.$exe
+ if $cc -c dialect.c && $cc -o dialect.$exe dialect.$obj && $executable dialect.$exe
+ then src=c
+ else set x $cc
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *=*) continue ;;
+ esac
+ case `echo $1 | sed -e 's,.*/,,'` in
+ *CC*|*++*|*[xX][xX]*|*[pP][lL][uU][sS]*) ;;
+ *) src=c ;;
+ esac
+ break
+ done
+ fi
+ else src=c
+ fi
+ ;;
+esac
+
+set x x '(' 1 'int x;' 0
+while :
+do shift
+ shift
+ case $# in
+ [01]) break ;;
+ esac
+ rm -f test.$obj
+ echo "$1" > test.$src
+ $cc -c test.$src
+ r=$?
+ case $r in
+ 0) test -f test.$obj || r=1 ;;
+ *) r=1 ;;
+ esac
+ case $2:$r in
+ 0:0) ;;
+ 0:1) echo "$cc: not a C compiler: failed to compile \`\`$1''" >&4
+ exit 1
+ ;;
+ 1:0) echo "$cc: not a C compiler: successfully compiled \`\`$1''" >&4
+ exit 1
+ ;;
+ esac
+done
+
+hosttype=`package CC="$cc" || $SHELL -c "package CC='$cc'"`
+case $hosttype in
+*[Uu][Ss][Aa][Gg][Ee]:*)
+ hosttype=`PATH=$_probe_PATH; export PATH; package CC="$cc" || $SHELL -c "package CC='$cc'"`
+ ;;
+esac
+
+echo '#include <stdio.h>
+int main(){printf("hello");return 0;}' > dynamic.$src
+echo 'extern int sfclose() { return 0; }' > fun.$src
+if $cc -c dynamic.$src && $cc -c fun.$src
+then eval set x $probe_so
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ for i in foo junk
+ do rm -f dynamic.$exe
+ if $cc -L. -o dynamic.$exe dynamic.$obj -l$i
+ then : "there's really a -l$i"?
+ else rm -f dynamic.$exe
+ cat fun.$obj > lib$i$1
+ $cc -L. -o dynamic.$exe dynamic.$obj -l$i && $executable dynamic.$exe
+ x=$?
+ rm lib$i$1
+ case $x in
+ 0) so=$1
+ rm -f dynamic.$exe > lib$i$1.1
+ $cc -L. -o dynamic.$exe dynamic.$obj -l$i && $executable dynamic.$exe
+ x=$?
+ rm lib$i$1.1
+ case $x in
+ 0) sov=1 ;;
+ esac
+ break 2
+ ;;
+ *) break
+ ;;
+ esac
+ fi
+ done
+ k=
+ for i in "" .1 .2 .3 .4 .5 .6 .7 .8 .9
+ do rm -f dynamic.$exe > libc$1$i
+ $cc -L. -o dynamic.$exe dynamic.$obj && $executable dynamic.$exe
+ x=$?
+ (cd ..; rm $tmpdir/libc$1$i)
+ case $x in
+ 0) ;;
+ *) k=X$k
+ case $k in
+ XXX) break ;;
+ esac
+ ;;
+ esac
+ done
+ case $k in
+ XXX) so=$1
+ sov=1
+ break
+ ;;
+ ?*) so=$1
+ break
+ ;;
+ esac
+ done
+ rm -f dynamic.$exe
+ if $cc -o dynamic.$exe dynamic.$obj 2>e && $executable dynamic.$exe
+ then e=`wc -l e`
+ maybe=
+ eval set x x $probe_binding
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f dynamic.$exe
+ $cc -o dynamic.$exe $1 dynamic.$obj 2>e && $executable dynamic.$exe || continue
+ case $1 in
+ ?*) case $maybe in
+ "") maybe=$1 ;;
+ *) maybe=-- ;;
+ esac
+ ;;
+ esac
+ case `wc -l e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ d=`ls -s dynamic.$exe`
+ rm -f dynamic.$exe
+ $cc -o dynamic.$exe $2 dynamic.$obj 2>e && $executable dynamic.$exe || continue
+ case `wc -l e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case `ls -s dynamic.$exe` in
+ $d) ;;
+ *) dynamic=$1
+ static=$2
+ maybe=
+ break
+ ;;
+ esac
+ done
+ case $maybe in
+ ""|--) ;;
+ *) rm -f dynamic.$exe
+ if $cc -o dynamic.$exe $maybe dynamic.$obj 2>e && $executable dynamic.$exe
+ then e=`wc -l e`
+ if $cc -o dynamic.$exe $maybe-bogus-bogus-bogus dynamic.$obj 2>e && $executable dynamic.$exe
+ then case `wc -l e` in
+ $e) ;;
+ *) dynamic=$maybe ;;
+ esac
+ else dynamic=$maybe
+ fi
+ fi
+ ;;
+ esac
+ fi
+fi
+
+eval set x $probe_version
+shift
+for o in "$@"
+do if $cc $o > version.out 2>&1
+ then version_string=`sed -e '/ is /d' -e 's/;/ /g' version.out | sed -e 1q`
+ case $version_string in
+ ''|*[Ee][Rr][Rr][Oo][Rr]*|*[Ff][Aa][Tt][Aa][Ll]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*)
+ ;;
+ *) version_flags=$o
+ version_stamp=";VERSION;$o;$version_string;PATH;$cc"
+ break
+ ;;
+ esac
+ fi
+done
+case $version_stamp in
+'') eval set x $probe_version
+ shift
+ echo 'int main() { return 0; }' > version.i
+ for o in "$@"
+ do if $cc -c $o version.i > version.out 2>&1
+ then version_string=`sed -e '/ is /d' -e 's/;/ /g' version.out | sed -e 1q`
+ case $version_string in
+ ''|*[Ee][Rr][Rr][Oo][Rr]*|*[Ff][Aa][Tt][Aa][Ll]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*)
+ ;;
+ *) version_flags=$o
+ break
+ ;;
+ esac
+ fi
+ done
+ ;;
+esac
+
+echo 'int main(){return 0;}' > hosted.$src
+$cc -o hosted.$exe hosted.$src && ./hosted.$exe && hosted=1
+
+echo '#!'$sh'
+echo "" $@' > cpp
+chmod +x cpp
+case `./cpp -Dprobe` in
+*-Dprobe*)
+ ;;
+*) cp /bin/echo cpp
+ chmod u+w cpp
+ ;;
+esac
+for prefix in $probe_ppprefix `echo $cc | sed -e '/cc\$/!d' -e 's,cc\$,,' -e 's,.*/,,'`
+do cp cpp ${prefix}cpp
+done
+
+echo "" > flags.$src
+echo '#pragma pp:version' > libpp.$src
+
+if test `realcppC=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='realcppC=${ppcmd}'
+elif test `cppC=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='cppC=${ppcmd}'
+elif test `_CPPNAME=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='_CPPNAME=${ppcmd}'
+elif test `_CPP=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='_CPP=${ppcmd}'
+elif test `$cc -Dprobe -E -%p+. flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 && test `$cc -Dprobe -E -%p+. flags.$src | wc -l` -eq 1
+then ppopt='-%p+${ppdir}'
+elif test `$cc -Dprobe -E -Yp,. flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-Yp,${ppdir}'
+elif test `$cc -Dprobe -E -Qpath $tmpdir flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-Qpath ${ppdir}'
+elif test `$cc -Dprobe -E -tp -B./ flags.$src 2>err.out | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 -a ! -s err.out
+then ppopt='-tp -B${ppdir}/'
+elif test `$cc -Dprobe -E -B./ flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-B${ppdir}/'
+elif test `$cc -Dprobe -E -tp -h./ -B flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-tp -h${ppdir}/ -B'
+elif test `$cc -Dprobe -E -t p,./cpp flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-t p,${ppcmd}'
+else {
+ eval set x $probe_verbose
+ shift
+ for o in "$@"
+ do $cc -E $o flags.$src
+ done
+ } 2>&1 | sed -e "s/['\"]//g" > cpp.out
+fi
+
+set x `sed -e 's,[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\\\,/,g' -e 's,\\\\,/,g' cpp.out`
+def=
+definclude="-I+C -I-H"
+stdinclude=$definclude
+case $hosted in
+"") usrinclude= ;;
+esac
+cmdinclude=
+while :
+do case $# in
+ 0|1) break ;;
+ esac
+ shift
+ case $1 in
+ -A) case $2 in
+ *\(*\)) shift
+ prepred="$prepred `echo $1 | sed 's/\(.*\)(\(.*\))/\1 \2/'`"
+ ;;
+ esac
+ ;;
+ -A\(*\))
+ prepred="$prepred `echo $1 | sed 's/-A\(.*\)(\(.*\))/\1 \2/'`"
+ ;;
+ -[DI][-+][ABCDEFGHIJKLMNOPQRSTUVWXYZ]*)
+ stdpp=1
+ case $1 in
+ -I?[CH]) case $def in
+ ?*) definclude="$definclude $1" ;;
+ *) stdinclude="$stdinclude $1" ;;
+ esac
+ ;;
+ -I-S*|-YI,*) usrinclude="`echo $1 | sed 's/....//'`" ;;
+ -Y?,*) ;;
+ -Y*) usrinclude="`echo $1 | sed 's/..//'`" ;;
+ esac
+ ;;
+ -D) shift
+ case $1 in
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*=*)
+ predef="$predef
+`echo $1 | sed -e 's/=.*//'`"
+ ;;
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*)
+ predef="$predef
+$1"
+ ;;
+ esac
+ ;;
+ -Dprobe);;
+ -D*) case $1 in
+ -D[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*=*)
+ predef="$predef
+`echo $1 | sed -e 's/^-D//' -e 's/=.*//'`"
+ ;;
+ -D[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*)
+ predef="$predef
+`echo $1 | sed -e 's/^-D//'`"
+ ;;
+ esac
+ ;;
+ -I) shift
+ case $1 in
+ /*) case $def in
+ ?*) definclude="$definclude $1" ;;
+ *) stdinclude="$stdinclude $1" ;;
+ esac
+ cmdinclude="$cmdinclude $1"
+ ;;
+ esac
+ ;;
+ -I/*) f=`echo X$1 | sed 's/X-I//'`
+ case $def in
+ ?*) definclude="$definclude $f" ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ cmdinclude="$cmdinclude $f"
+ ;;
+ -U) shift
+ undef="$undef $1"
+ ;;
+ -U*) undef="$undef `echo $1 | sed 's/^-U//'`"
+ ;;
+ flags.$src)def=
+ ;;
+ esac
+done
+stdinclude="$stdinclude $definclude"
+case " $stdinclude " in
+*\ $usrinclude\ *)
+ case $usrinclude in
+ /usr/include)
+ usrinclude=
+ ;;
+ *) case " $stdinclude " in
+ *\ /usr/include\ *)
+ usrinclude=
+ ;;
+ *) usrinclude=/usr/include
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+
+tstinclude=`$cc -v -E flags.$src 2>&1 | sed -e '1,/[iI][nN][cC][lL][uU][dD][eE][ ]*<[.][.][.]>/d' -e '/^[eE][nN][dD] [oO][fF] [sS][eE][aA][rR][cC][hH]/,\$d'`
+j=$tstinclude
+case $j in
+*/*) ;;
+*) j=$cmdinclude ;;
+esac
+tstinclude=
+good=
+nogood=
+c_hdr="stdio.h ctype.h"
+C_hdr="libc.h"
+for i in $j
+do if test -d "$i"
+ then tstinclude="$tstinclude $i"
+ h=
+ for f in $c_hdr
+ do if test -f "$i/$f"
+ then case $i in
+ */CC) nogood=1 ;;
+ *) good=1 ;;
+ esac
+ else h="$h $f"
+ fi
+ done
+ c_hdr=$h
+ h=
+ for f in $C_hdr
+ do if test -f "$i/$f"
+ then case $i in
+ */CC) nogood=1 ;;
+ *) good=1 ;;
+ esac
+ else h="$h $f"
+ fi
+ done
+ C_hdr=$h
+ fi
+done
+case $nogood in
+1) good=0 ;;
+esac
+case $good in
+1) case $c_hdr in
+ ?*) bad=1
+ usrinclude=/usr/include
+ set '' $tstinclude /usr/include
+ ;;
+ *) set '' $tstinclude
+ ;;
+ esac
+ shift
+ stdinclude=$*
+ echo "#include <sys/types.h>" > include.$src
+ $cc -E include.$src | sed -e '/# 1 "[\\/]/!d' -e 's,[^"]*",,' -e 's,[\\/][^\\/]*".*,,' -e 's,[\\/]sys,,' > include.out
+ for f in `cat include.out`
+ do if test -d "$f"
+ then g=`echo $f | sed -e 's,[\\/][\\/]*[^\\/]*$,,'`
+ case " $stdinclude " in
+ *\ $f\ *|*\ $g\ *)
+ ;;
+ *) stdinclude="$stdinclude $f"
+ case $f in
+ /usr/include) usrinclude=$f ;;
+ esac
+ bad=1
+ ;;
+ esac
+ fi
+ done
+ ;;
+*) case $ppopt$ppenv in
+ ?*) echo '#!'$sh'
+ echo $VIRTUAL_ROOT | sed "s/:.*//"' > cpp
+ chmod +x cpp
+ ppcmd=cpp
+ ppdir=.
+ eval x='`'$ppenv '$'cc -E $ppopt flags.$src'`'
+ case $x in
+ ?*) tstinclude=$x/usr/include
+ ;;
+ esac
+ cp /bin/echo cpp
+ chmod u+w cpp
+ ;;
+ esac
+
+ eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ echo "#include <$1>" > include.$src
+ $cc -E include.$src
+ done > include.out
+
+ ccinclude=
+ x=$stdinclude
+ stdinclude=
+ subinclude=
+ for f in $x $tstinclude `sed -e 's,\\\\,/,g' -e 's,///*,/,g' -e 's,"[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:/,"/,g' -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[\\/]/!d' -e 's/^#[line ]*[0123456789][0123456789]*[ ][ ]*"\(.*\)[\\/].*".*/\1/' include.out | sort -u`
+ do case $f in
+ -*) ;;
+ */) f=`echo $f | sed -e 's,//*\$,,'` ;;
+ */.) f=`echo $f | sed -e 's,//*.\$,,'` ;;
+ esac
+ case $f in
+ -I*) ;;
+ */cc) ccinclude=1
+ ;;
+ */sys) continue
+ ;;
+ */include/*/*)
+ ;;
+ */include/*)
+ subinclude="$subinclude $f"
+ continue
+ ;;
+ esac
+ if test -d "$f"
+ then case " $stdinclude " in
+ *\ $f\ *) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ fi
+ done
+ rm include.out
+ case $ccinclude in
+ ?*) eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ echo "#include <cc/$1>" > include.$src
+ if $cc -E include.$src > /dev/null
+ then break
+ fi
+ done
+ case $# in
+ 0) ;;
+ *) x=$stdinclude
+ stdinclude=
+ for f in $x
+ do case $f in
+ */cc) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ case $subinclude in
+ ?*) for i in $subinclude
+ do for j in $stdinclude
+ do case $i in
+ $j/*/*) ;;
+ $j/*) both=
+ eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) for k in $both
+ do echo "#include <$k>" > include.$src
+ $cc -E include.$src > include.out
+ I=`grep -c $i/$k < include.out`
+ J=`grep -c $j/$k < include.out`
+ case $I:$J in
+ 0:*) ;;
+ *:0) stdinclude="$i $stdinclude"
+ break
+ ;;
+ esac
+ done
+ continue 3
+ ;;
+ esac
+ if test -f $i/$1
+ then if test ! -f $j/$1
+ then break 2
+ fi
+ both="$both $1"
+ fi
+ done
+ ;;
+ $j) continue 2
+ ;;
+ esac
+ done
+ stdinclude="$i $stdinclude"
+ done
+ ;;
+ esac
+
+ {
+
+ for i in $stdinclude
+ do
+ case $i in
+ $usrinclude) ;;
+ *) echo $i $i ;;
+ esac
+ done
+
+ eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ echo "#include <$1>" > t.c
+ p=
+ for j in `$cc -E t.c | grep "$1" | sed -e 's,\\\\,/,g' -e 's,"[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:/,"/,g' -e '/^#[line ]*1[ ][ ]*"[\\/]/!d' -e 's/^#[line ]*1[ ][ ]*"\(.*\)[\\/].*".*/\1/'`
+ do j=`echo $j | sed -e 's,///*,/,g' -e 's,/$,,'`
+ case $p in
+ ?*) echo $p $j ;;
+ esac
+ p=$j
+ done
+ done
+
+ case $usrinclude in
+ ?*) echo $usrinclude $usrinclude ;;
+ esac
+
+ } | tsort > tmp.tmp
+ tstinclude=`cat tmp.tmp`
+ bad=
+ for i in $stdinclude
+ do case "
+$tstinclude
+" in
+ *"
+$i
+"*) ;;
+ *) bad=1
+ break
+ ;;
+ esac
+ done
+ ;;
+esac
+
+case $bad in
+"") x=$stdinclude
+ stdinclude=
+ z=
+ for i in $tstinclude
+ do case " $x " in
+ *" $i "*)
+ stdinclude="$stdinclude $i"
+ z=$i
+ ;;
+ esac
+ done
+ case $usrinclude in
+ '') usrinclude=$z ;;
+ esac
+ ;;
+esac
+case $hosted in
+"") case $usrinclude in
+ /usr/include) usrinclude= ;;
+ esac
+ ;;
+esac
+
+case $usrinclude in
+?*) case " $stdinclude " in
+ *\ $usrinclude\ *)
+ x=$stdinclude
+ stdinclude=
+ for f in $x
+ do case $f in
+ $usrinclude) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+esac
+
+# drop dups -- they creep in somehow
+
+x=$stdinclude
+stdinclude=
+for f in $x
+do case " $stdinclude $usrinclude " in
+ *" $f "*) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+done
diff --git a/src/cmd/INIT/CONVERT.mk b/src/cmd/INIT/CONVERT.mk
new file mode 100644
index 0000000..63a60ef
--- /dev/null
+++ b/src/cmd/INIT/CONVERT.mk
@@ -0,0 +1,260 @@
+/*
+ * {automake|configure} => {nmake|iffe} conversion support
+ *
+ * The first command line target overrides the default original source
+ * directory name $(MAKEFILE:D). The hard work is in the makefile using
+ * these assertions, since it must (manually) provide the nmake makefiles
+ * and config equivalent iffe scripts. The conversion makefile is typically
+ * named lib/package/PACKAGE.cvt in an ast package $PACKAGEROOT directory,
+ * and the conversion is run from the $PACKAGEROOT directory, e.g.:
+ *
+ * nmake -I lib/package -f PACKAGE-VERSION/PACKAGE.cvt
+ *
+ * The conversion requires the ast nmake, pax and tw commands.
+ *
+ * After the conversion you will be liberated from ./configure, *.in,
+ * *.am, automake, autom4te, libtool, make depend, and makefile
+ * recursion ordering. You can build from $PACKAGEROOT using the ast
+ * package(1) (which sets up the { HOSTTYPE PATH VPATH } environment):
+ *
+ * package make
+ *
+ * or cd into any arch/$HOSTTYPE/src subdirectory and rebuild that portion
+ * of the hierarchy with the ast nmake(1) (after setting PATH and VPATH):
+ *
+ * nmake
+ *
+ * The conversion assertions are:
+ *
+ * package :CONVERT: file ...
+ *
+ * files in the original source directory are copied
+ * and converted into the ./src and ./lib subdirectories
+ * the default original source directory is ./original
+ *
+ * package package name
+ * file original source file that must exist
+ *
+ * :OMIT: pattern
+ *
+ * files matching pattern are not copied into the converted
+ * directory
+ *
+ * pattern ksh pattern of files to omit
+ *
+ * :COPY: from to [ file ... ]
+ *
+ * files in the from directory are copied to the to directory
+ * the action may contain :MOVE: exceptions to the copy
+ *
+ * from original directory subdirectory
+ * . names the original directory
+ * .. names the
+ * to converted subdirectory
+ * libNAME => src/lib/libNAME
+ * NAME => src/cmd/NAME
+ * file files or files in subdirectories to be copied;
+ * explicit files are copied to the to directory;
+ * if no files are specified then the from hierarchy
+ * is recursively copied to the converted directory
+ *
+ * :MOVE: to file ...
+ *
+ * :COPY: assertion exceptions placed in the assertion's action
+ *
+ * to files or subdirectory files are copied to this directory
+ * file file or files in subdirectories to be copied
+ *
+ * :FILE: to file <<!
+ * contents
+ * !
+ *
+ * the :FILE: action is copied to the named file in the to directory
+ * the :FILE: action is usually specified using the here syntax to
+ * avoid make comment, quote and variable expansion
+ *
+ * :EDIT: to file ... | - pattern <<!
+ * edit script
+ * !
+ *
+ * the :EDIT: action is an ed(1) script applied to each file in the
+ * to directory after it has been copied from the original source
+ * directory; if to is - then the :EDIT: action is a sed(1) script
+ * that is applied to all files matching the file pattern during the
+ * copy from the original source directory; a file may be subject to
+ * both a sed(1) and ed(1) :EDIT:; the :EDIT: action is usually
+ * specified using the here syntax to avoid make comment, quote and
+ * variable expansion
+ */
+
+.CONVERT.ID. = "@(#)$Id: CONVERT (AT&T Research) 2004-03-19 $"
+
+set nojobs noscan nowriteobject writestate=$$(MAKEFILE).ms
+
+package = $(PWD:B)
+here = !-=-=-=-=-!
+hierarchy = src src/cmd src/lib
+omit = .*|*.?(l)[ao]
+original = $(MAKEFILE:D)
+showedit = $(-debug:?p??)
+
+CPFLAGS = -u
+PAXFLAGS = -u -v
+STDEDFLAGS = -
+TW = tw
+TWFLAGS = -CP
+
+all : .VIRTUAL file
+file : .VIRTUAL edit
+edit : .VIRTUAL copy
+copy : .VIRTUAL init
+init : .VIRTUAL
+
+.MAKEINIT : .cvt.init
+
+.cvt.init : .MAKE .VIRTUAL .FORCE
+ local D
+ if D = "$(~.ARGS:O=1)"
+ if "$(D:T>FD)"
+ original := $(D)
+ .ARGS : .CLEAR $(~.ARGS:O>1)
+ end
+ end
+
+.cvt.filter =
+.cvt.package =
+
+.cvt.atom : .FUNCTION
+ local N V
+ V := $(%:O=1)
+ let .cvt.$(V) = .cvt.$(V) + 1
+ return .cvt.$(V).$(.cvt.$(V))
+
+.cvt.omit : .FUNCTION
+ return -s',^\(\(?K)?(*/)($(omit))?(/*))$,,$(showedit)'
+
+.cvt.to : .FUNCTION
+ if "$(%)" == "."
+ return src
+ end
+ if "$(%)" == "*/*"
+ return src/$(%)
+ end
+ if "$(%)" == "lib*"
+ return src/lib/$(%)
+ end
+ return src/cmd/$(%)
+
+":CONVERT:" : .MAKE .OPERATOR
+ local I
+ package := $(<)
+ I := $(hierarchy:C,$,/Makefile)
+ init : .cvt.verify $(I)
+ $(I) : .ACCEPT
+ test -d $(<:D) || $(MKDIR) -p $(<:D)
+ echo :MAKE: > $(<)
+ .cvt.verify : .MAKE .FORCE .REPEAT
+ local I
+ if I = "$(.cvt.package:T!=F)"
+ error 3 $(original): not a $(package) source directory: missing $(I)
+ end
+ .cvt.package := $(>:C,^,$$(original)/,)
+
+":COPY:" : .MAKE .OPERATOR
+ local F T I A
+ F := $(>:O=1)
+ T := $(.cvt.to $(>:O=2))
+ A := $(.cvt.atom copy)
+ copy : $(A)
+ $(A) : .VIRTUAL
+ if F == "."
+ $(A) : $(T)
+ $(T) :
+ test -d $(<) || $(MKDIR) -p $(<)
+ for I $(>:O>2)
+ eval
+ $$(A) : $(I:D=$(T):B:S)
+ $(I:D=$(T):B:S) : $$(original)/$(I)
+ $$(CP) $$(CPFLAGS) $$(*) $$(<)
+ end
+ end
+ elif "$(F:T=FF)" || "$(F:N=*.(pax|t[bg]z))"
+ eval
+ $$(A) : $$(F)
+ test -d $(T) || $$(MKDIR) -p $(T)
+ cd $(T)
+ $$(PAX) $$(PAXFLAGS) -rf $$(*:P=A) -s ',^$(>:O=2)/*,,' $(.cvt.omit) $(.cvt.filter)
+ end
+ else
+ F := $$(original)/$(F)
+ if ! "$(@:V)"
+ eval
+ $$(A) : .FORCE
+ test -d $(T) || $$(MKDIR) -p $(T)
+ cd $(F:V)
+ $$(TW) $$(TWFLAGS) | $$(PAX) $$(PAXFLAGS) -rw $(.cvt.omit) $(.cvt.filter) $(T:P=A)
+ end
+ else
+ .cvt.move =
+ : $(@:V:@R)
+ eval
+ $$(A) : .FORCE
+ test -d $(T) || $$(MKDIR) -p $(T)
+ cd $(F:V)
+ $$(TW) $$(TWFLAGS) | $$(PAX) $$(PAXFLAGS) -rw $(.cvt.omit) $(.cvt.move) $(.cvt.filter) $(T:P=A)
+ end
+ end
+ end
+
+":EDIT:" : .MAKE .OPERATOR
+ local A D F
+ D := $(>:O=1)
+ if D == "-"
+ A := ^$(>:O=2)^$$(SED) -e $(@:Q:/'\n'/ -e /G)
+ .cvt.filter += --action=$(A:@Q)
+ else
+ D := $(.cvt.to $(D))
+ F := $(>:O>1:C,^,$(D)/,)
+ edit : $(F)
+ eval
+ $$(F) :
+ $$(STDED) $$(STDEDFLAGS) $$(<) <<'$(here)'
+ $(@:V)
+ w
+ q
+ $(here)
+ end
+ end
+
+":FILE:" : .MAKE .OPERATOR
+ local ( D F ) $(>)
+ local A
+ A := $(.cvt.atom file)
+ $(A) := $(@:V)
+ D := $(.cvt.to $(D))
+ file : $(D)/$(F)
+ eval
+ $$(D)/$$(F) :
+ test -d $$(<:D) || $$(MKDIR) -p $$(<:D)
+ cat > $$(<) <<'$(here)'
+ $$($(A):V)
+ $(here)
+ end
+
+":MOVE:" : .MAKE .OPERATOR
+ local T I
+ T := ../../../$(.cvt.to $(>:O=1))
+ for I $(>:O>1)
+ if I == "*/"
+ .cvt.move += -s',^\(\(?K)$(I)),$(T)/,$(showedit)'
+ .cvt.move += -s',^\(\(?K)$(I:C%/$%%))$,,$(showedit)'
+ else
+ .cvt.move += -s',^\(\(?K)$(I))$,$(T)/$(I:B:S),$(showedit)'
+ end
+ end
+
+":OMIT:" : .MAKE .OPERATOR
+ local P
+ for P $(>)
+ omit := $(omit)|$(P)
+ end
diff --git a/src/cmd/INIT/MAPLIB.mk b/src/cmd/INIT/MAPLIB.mk
new file mode 100644
index 0000000..5761035
--- /dev/null
+++ b/src/cmd/INIT/MAPLIB.mk
@@ -0,0 +1,45 @@
+/*
+ * normalize local -l* library conventions
+ *
+ * L [ [ G11 ... G1n ] ... [ Gg1 ... Ggn ] ] :MAPLIB: T1.c ... Tn.c
+ *
+ * if Giji not specified then G11 == L
+ * the first Ti.c that compiles/links with group -lGi1 ... -lGin
+ * but does not compile/link with no libraries maps
+ * -lL to to require -lGi1 ... -lGin
+ * otherwise -lL is not required and maps to "no library required"
+ */
+
+":MAPLIB:" : .MAKE .OPERATOR
+ local L P
+ L := $(<:B:O=1)
+ if ! ( P = "$(<:B:O>1)" )
+ P := $(L)
+ end
+ $(LIBDIR)/lib/$(L) :INSTALL: $(L).req
+ eval
+ $(L).req : (CC) $$(>)
+ set -
+ r='-'
+ for i in $$(*)
+ do if $$(CC) -c $i > /dev/null
+ then g=
+ for p in $(P) -
+ do case $p in
+ -) if $$(CC) -o $$(<:B:S=.exe) $i $g > /dev/null 2>&1
+ then $$(CC) -o $$(<:B:S=.exe) $i > /dev/null 2>&1 || {
+ r="$g"
+ break 2
+ }
+ fi
+ g=
+ ;;
+ *) g="$g -l$p"
+ ;;
+ esac
+ done
+ fi
+ done 2>/dev/null
+ echo " $r" > $$(<)
+ rm -f $$(<:B:S=.exe) $$(*:B:S=$$(CC.SUFFIX.OBJECT))
+ end
diff --git a/src/cmd/INIT/MSGFUN.mk b/src/cmd/INIT/MSGFUN.mk
new file mode 100644
index 0000000..0888d00
--- /dev/null
+++ b/src/cmd/INIT/MSGFUN.mk
@@ -0,0 +1,2 @@
+/* stub for pre-2000-05-01 nmake */
+":MSGFUN:" : .MAKE .OPERATOR
diff --git a/src/cmd/INIT/MSGKEY.mk b/src/cmd/INIT/MSGKEY.mk
new file mode 100644
index 0000000..db18559
--- /dev/null
+++ b/src/cmd/INIT/MSGKEY.mk
@@ -0,0 +1,2 @@
+/* stub for pre-2000-05-01 nmake */
+":MSGKEY:" : .MAKE .OPERATOR
diff --git a/src/cmd/INIT/Makefile b/src/cmd/INIT/Makefile
new file mode 100644
index 0000000..b1af6aa
--- /dev/null
+++ b/src/cmd/INIT/Makefile
@@ -0,0 +1,293 @@
+/*
+ * initialization for all packages
+ */
+
+:PACKAGE: license=ast
+
+LICENSE = since=1994,author=gsf
+
+PACKAGEROOT = $(INSTALLROOT:T=F:P=L*:O=n)
+
+hurl :: hurl.sh LICENSE=since=2003,author=gsf
+
+iffe :: iffe.sh LICENSE=since=1994,author=gsf+kpv
+
+mktest :: mktest.sh LICENSE=since=2005,author=gsf
+
+package :: package.sh
+
+regress :: regress.sh LICENSE=since=1995,author=gsf
+
+rt :: rt.sh LICENSE=since=2005,author=gsf
+
+$(PACKAGEROOT)/bin :INSTALLDIR: execrate ignore mamprobe package silent
+
+crossexec :: crossexec.sh
+
+ditto :: ditto.sh LICENSE=since=2001,author=gsf+ek
+
+execrate :: execrate.sh LICENSE=since=2002,author=gsf
+
+filter :: filter.sh
+
+ignore :: ignore.sh
+
+silent :: silent.sh
+
+$(PACKAGEROOT)/lib/package :INSTALLDIR: package.mk CONVERT.mk
+
+$(LIBDIR)/make :INSTALLDIR: package.mk PROBE.mk TEST.mk WWW.mk \
+ MSGFUN.mk MSGKEY.mk MAPLIB.mk
+
+:TEST: iffe mamake
+
+cc ld ldd :PACKAGE_INIT: mamake.c proto.c ratz.c release.c
+
+:: RELEASE hosttype.tst p.c hello.c \
+ ar.ibm.risc \
+ cc.specialize cc.pentium4 \
+ ldd.cygwin.i386 \
+ cc.darwin.i386 cc.darwin.i386-64 cc.darwin ldd.darwin \
+ cc.hp.ia64 cc.hp.pa cc.hp.pa64 ld.hp.pa ldd.hp.pa \
+ cc.ibm.risc cc.ibm.risc.gcc ldd.ibm.risc \
+ cc.linux.ia64-icc cc.linux.i386-icc cc.linux.i386-64-icc \
+ cc.lynxos.i386 cc.lynxos.ppc ldd.lynxos \
+ cc.mvs.390 cc.next.i386 cc.next.m68k ldd.mvs.390 \
+ cc.osf.alpha \
+ cc.sco.i386 \
+ cc.sgi.mips2 cc.sgi.mips3 cc.sgi.mips3-o32 cc.sgi.mips4 \
+ cc.sgi.mips4-n32 ldd.sgi \
+ cc.unix.mc68k
+
+LICENSE : .DONTCARE
+
+if ! CC.HOSTTYPE
+ CC.HOSTTYPE := $(_hosttype_|HOSTTYPE)
+end
+
+$(BINDIR)/mkdir :INSTALL: mkdir.sh
+ if test ! -x $(<) -a -x /bin/mkdir
+ then mkdir -p 2>/dev/null || :
+ if test -d ./-p
+ then rmdir ./-p
+ cp $(*) $(<)
+ chmod +x $(<)
+ fi
+ fi
+
+/*
+ * ksh93 function search on PATH
+ * ksh93 builtin command library -lcmd
+ * ksh93 ld library path search on PATH
+ */
+
+$(BINDIR)/.paths :INSTALL: (CC.DIALECT)
+ if test ! -f $(<) -o -w $(<)
+ then nl="
+"
+ o=`cat $(<) 2>/dev/null` || :
+ v=
+ n=
+ case $nl$o in
+ *${nl}FPATH=*|*#FPATH=*|*[Nn][Oo]FPATH=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ n="${n}FPATH=../fun"
+ v="${v}FPATH"
+ ;;
+ esac
+ case $nl$o in
+ *${nl}BUILTIN_LIB=*|*#BUILTIN_LIB=*|*[Nn][Oo]BUILTIN_LIB=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ case '$(CC.DIALECT:N=*EXPORT=[AD]LL*)' in
+ ?*) p= c= ;;
+ *) p='XX' ;;
+ esac
+ n="${n}${p}BUILTIN_LIB=cmd"
+ v="${v}BUILTIN_LIB"
+ ;;
+ esac
+ set x x : $(-mam:??$(.GETCONF LIBPATH:/:/ /G:/,/ : /G:Q)?)
+ p=
+ while :
+ do while :
+ do case $# in
+ 0) break ;;
+ esac
+ x=$1
+ shift
+ case $x in
+ :) break ;;
+ esac
+ done
+ case $# in
+ 0|1) break
+ ;;
+ 2) p=$2
+ ;;
+ *) case "$(CC.HOSTTYPE)" in
+ $3) p=$2; break ;;
+ esac
+ ;;
+ esac
+ done
+ case $p in
+ '') if test -x /lib/dld.sl
+ then p=SHLIB_PATH
+ elif test -x /usr/lib/dyld
+ then p=DYLD_LIBRARY_PATH
+ else case "$(CC.HOSTTYPE)" in
+ ibm.*|mvs.*)
+ p=LIBPATH
+ ;;
+ sgi.mips3)
+ p=LD_LIBRARYN32_PATH
+ ;;
+ sgi.mips4)
+ p=LD_LIBRARYN64_PATH
+ ;;
+ *) p=LD_LIBRARY_PATH
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ case $nl$o in
+ *${nl}${p}=*|*#${p}=*|*[Nn][Oo]${p}=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ n="${n}${p}=../lib"
+ v="${v}${p}"
+ ;;
+ esac
+ case $n in
+ ?*) case $o in
+ ?*) o=`egrep -v "($v)=" $(<)`$nl ;;
+ esac
+ echo "# use { # no NO } prefix instead of XX to permanently disable #$nl$o$n" > $(<)
+ ;;
+ esac
+ fi
+
+/*
+ * probe initialization
+ */
+
+for T C+probe C+make+probe.lcl C+pp+probe.lcl
+ if T == "*.lcl"
+ $(T) : .DONTCARE
+ end
+ $(LIBDIR)/probe/$(T:C,+,/,G) :INSTALL: $(T)
+end
+
+$(LIBDIR)/probe/C/mam/probe :INSTALL: mprobe
+
+mprobe :: mprobe.sh
+
+$(LIBDIR)/probe/C/make :INSTALLDIR: probe probe.ini
+
+probe.sh : C+probe make.probe
+ cat $(*) > $(<)
+
+probe :: probe.sh
+
+probe.ini : (CC.HOSTTYPE) probe.win32
+ t=$(CC.HOSTTYPE)
+ ifs=$IFS
+ IFS=.
+ set x $t
+ IFS=$ifs
+ t=$2
+ set x $(*)
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *probe.$t)
+ break
+ esac
+ done
+ case $1 in
+ ?*) cmp -s $1 $(<) || cp $1 $(<) ;;
+ *) : > $(<)
+ esac
+
+/*
+ * proto initialization
+ */
+
+$(INCLUDEDIR) :INSTALLDIR: prototyped.h
+
+prototyped.h : $(BINDIR)/proto
+ proto -f /dev/null > h.$(tmp).h
+ if $(CMP) -s h.$(tmp).h $(<)
+ then $(RM) -f h.$(tmp).h
+ else $(MV) h.$(tmp).h $(<)
+ fi
+
+/*
+ * check if -ldl is required
+ * this allows makefiles to use -ldl on all systems
+ *
+ * NOTE: this works around the sgi botch:
+ * (1) irix 5.* made -ldl optional but warned
+ * (2) irix 6.* has no -ldl
+ * (3) dynamic progs built on irix 5.* and using -ldl fail
+ * at runtime on irix 6.* because -ldl is not there
+ */
+
+dl :MAPLIB: dl.c
+
+/*
+ * requiring these is a botch
+ */
+
+iconv :MAPLIB: iconv.c
+
+w :MAPLIB: w.c w2.c
+
+/*
+ * miscellaneous -l* checks
+ */
+
+intl :MAPLIB: intl.c
+
+m :MAPLIB: m.c m2.c m3.c m4.c m5.c m6.c
+
+nsl :MAPLIB: nsl.c
+
+/*
+ * what was sco smoking
+ * almost all of gethost* are in -lnsl except gethostbyname which
+ * is in -lsocket which isn't needed to resolve socket() but seems
+ * to do the -lnsl job
+ */
+
+socket :MAPLIB: socket.c nsl.c
+
+/*
+ * more substance abuse
+ * gdbm's ndbm "compatibility" doesn't supply <ndbm.h>, instead supplies
+ * <gdbm/ndbm.h> which provides K&R prototypes *and* it requires -lgdbm
+ * some <ndbm.h> implementations use -lndbm, others -ldbm, still others -lc
+ * this is why unix is starting to look like windows
+ * this map allows makefiles to use -ldbm on all systems
+ *
+ * and this just in: sometimes its <gdbm-ndbm.h> and possibly -lgdbm_compat
+ *
+ * at least the -l* buck stops here
+ */
+
+dbm db - gdbm_compat - gdbm - ndbm - dbm :MAPLIB: db.c gdbm.c gdbm1.c gdbm2.c
diff --git a/src/cmd/INIT/Mamfile b/src/cmd/INIT/Mamfile
new file mode 100644
index 0000000..e5826d2
--- /dev/null
+++ b/src/cmd/INIT/Mamfile
@@ -0,0 +1,1332 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make hurl
+make hurl.sh
+done hurl.sh
+meta hurl %.sh>% hurl.sh hurl
+prev hurl.sh
+setv LICENSE -DLICENSE="since=2003,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : hurl contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n hurl.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp hurl.sh hurl
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < hurl.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - hurl.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2003-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > hurl
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - hurl.sh > hurl <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2003-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w hurl -a -x hurl || chmod u+w,+x hurl
+done hurl generated
+make iffe
+make iffe.sh
+done iffe.sh
+meta iffe %.sh>% iffe.sh iffe
+prev iffe.sh
+setv LICENSE -DLICENSE="since=1994,author=gsf+kpv"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : iffe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n iffe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 241 in
+exec - 0) cp iffe.sh iffe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < iffe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - iffe.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Phong Vo <kpv@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > iffe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - iffe.sh > iffe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Phong Vo <kpv@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w iffe -a -x iffe || chmod u+w,+x iffe
+done iffe generated
+make mktest
+make mktest.sh
+done mktest.sh
+meta mktest %.sh>% mktest.sh mktest
+prev mktest.sh
+setv LICENSE -DLICENSE="since=2005,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : mktest contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n mktest.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp mktest.sh mktest
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < mktest.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - mktest.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > mktest
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - mktest.sh > mktest <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w mktest -a -x mktest || chmod u+w,+x mktest
+done mktest generated
+make package
+make package.sh
+done package.sh
+meta package %.sh>% package.sh package
+prev package.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : package contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n package.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp package.sh package
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < package.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - package.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > package
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - package.sh > package <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w package -a -x package || chmod u+w,+x package
+done package generated
+make regress
+make regress.sh
+done regress.sh
+meta regress %.sh>% regress.sh regress
+prev regress.sh
+setv LICENSE -DLICENSE="since=1995,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : regress contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n regress.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp regress.sh regress
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < regress.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - regress.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1995-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > regress
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - regress.sh > regress <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1995-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w regress -a -x regress || chmod u+w,+x regress
+done regress generated
+make rt
+make rt.sh
+done rt.sh
+meta rt %.sh>% rt.sh rt
+prev rt.sh
+setv LICENSE -DLICENSE="since=2005,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : rt contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n rt.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp rt.sh rt
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < rt.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - rt.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > rt
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - rt.sh > rt <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w rt -a -x rt || chmod u+w,+x rt
+done rt generated
+make crossexec
+make crossexec.sh
+done crossexec.sh
+meta crossexec %.sh>% crossexec.sh crossexec
+prev crossexec.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : crossexec contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n crossexec.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp crossexec.sh crossexec
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < crossexec.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - crossexec.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > crossexec
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - crossexec.sh > crossexec <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w crossexec -a -x crossexec || chmod u+w,+x crossexec
+done crossexec generated
+make ditto
+make ditto.sh
+done ditto.sh
+meta ditto %.sh>% ditto.sh ditto
+prev ditto.sh
+setv LICENSE -DLICENSE="since=2001,author=gsf+ek"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : ditto contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n ditto.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 248 in
+exec - 0) cp ditto.sh ditto
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < ditto.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - ditto.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Lefty Koutsofios <ek@research.att.com>][-copyright?Copyright (c) 2001-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > ditto
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - ditto.sh > ditto <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Lefty Koutsofios <ek@research.att.com>][-copyright?Copyright (c) 2001-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w ditto -a -x ditto || chmod u+w,+x ditto
+done ditto generated
+make execrate
+make execrate.sh
+done execrate.sh
+meta execrate %.sh>% execrate.sh execrate
+prev execrate.sh
+setv LICENSE -DLICENSE="since=2002,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : execrate contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n execrate.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp execrate.sh execrate
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < execrate.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - execrate.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2002-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > execrate
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - execrate.sh > execrate <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2002-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w execrate -a -x execrate || chmod u+w,+x execrate
+done execrate generated
+make filter
+make filter.sh
+done filter.sh
+meta filter %.sh>% filter.sh filter
+prev filter.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : filter contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n filter.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp filter.sh filter
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < filter.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - filter.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > filter
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - filter.sh > filter <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w filter -a -x filter || chmod u+w,+x filter
+done filter generated
+make ignore
+make ignore.sh
+done ignore.sh
+meta ignore %.sh>% ignore.sh ignore
+prev ignore.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : ignore contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n ignore.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp ignore.sh ignore
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < ignore.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - ignore.sh <<'!'
+exec -
+exec - !
+exec - } > ignore
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - ignore.sh > ignore <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w ignore -a -x ignore || chmod u+w,+x ignore
+done ignore generated
+make silent
+make silent.sh
+done silent.sh
+meta silent %.sh>% silent.sh silent
+prev silent.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : silent contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n silent.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp silent.sh silent
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < silent.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - silent.sh <<'!'
+exec -
+exec - !
+exec - } > silent
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - silent.sh > silent <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w silent -a -x silent || chmod u+w,+x silent
+done silent generated
+make mamake
+make mamake.o
+make mamake.c
+make shlib-compat.h implicit
+done shlib-compat.h dontcare virtual
+make ast.h implicit
+done ast.h dontcare virtual
+done mamake.c
+meta mamake.o %.c>%.o mamake.c mamake
+prev mamake.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"\" -c mamake.c
+done mamake.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o mamake mamake.o
+done mamake generated
+make proto
+make proto.o
+make proto.c
+done proto.c
+meta proto.o %.c>%.o proto.c proto
+prev proto.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c proto.c
+done proto.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o proto proto.o
+done proto generated
+make ratz
+make ratz.o
+make ratz.c
+make unix.h implicit
+done unix.h dontcare virtual
+make alloc.h implicit
+done alloc.h dontcare virtual
+make unixio.h implicit
+done unixio.h dontcare virtual
+make ast_std.h implicit
+done ast_std.h dontcare virtual
+make windows.h implicit
+done windows.h dontcare virtual
+make io.h implicit
+done io.h dontcare virtual
+make direct.h implicit
+done direct.h dontcare virtual
+prev ast.h implicit
+done ratz.c
+meta ratz.o %.c>%.o ratz.c ratz
+prev ratz.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c ratz.c
+done ratz.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o ratz ratz.o
+done ratz generated
+make release
+make release.o
+make release.c
+prev ast.h implicit
+done release.c
+meta release.o %.c>%.o release.c release
+prev release.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"\" -c release.c
+done release.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o release release.o
+done release generated
+make mprobe
+make mprobe.sh
+done mprobe.sh
+meta mprobe %.sh>% mprobe.sh mprobe
+prev mprobe.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : mprobe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n mprobe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp mprobe.sh mprobe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < mprobe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - mprobe.sh <<'!'
+exec -
+exec - !
+exec - } > mprobe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - mprobe.sh > mprobe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w mprobe -a -x mprobe || chmod u+w,+x mprobe
+done mprobe generated
+make probe
+make probe.sh
+make C+probe
+done C+probe
+make make.probe
+done make.probe
+exec - cat C+probe make.probe > probe.sh
+done probe.sh generated
+meta probe %.sh>% probe.sh probe
+prev probe.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : probe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n probe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp probe.sh probe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < probe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - probe.sh <<'!'
+exec -
+exec - !
+exec - } > probe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - probe.sh > probe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w probe -a -x probe || chmod u+w,+x probe
+done probe generated
+make ${INSTALLROOT}/bin
+exec - if silent test ! -d ${INSTALLROOT}/bin
+exec - then mkdir -p ${INSTALLROOT}/bin
+exec - fi
+done ${INSTALLROOT}/bin generated
+make ${INSTALLROOT}/bin/hurl
+prev ${INSTALLROOT}/bin
+prev hurl
+exec - test '' = 'hurl' || ${STDCMP} 2>/dev/null -s hurl ${INSTALLROOT}/bin/hurl || { ${STDMV} ${INSTALLROOT}/bin/hurl ${INSTALLROOT}/bin/hurl.old 2>/dev/null || true; ${STDCP} hurl ${INSTALLROOT}/bin/hurl ;}
+done ${INSTALLROOT}/bin/hurl generated
+make ${INSTALLROOT}/bin/iffe
+prev iffe
+exec - test '' = 'iffe' || ${STDCMP} 2>/dev/null -s iffe ${INSTALLROOT}/bin/iffe || { ${STDMV} ${INSTALLROOT}/bin/iffe ${INSTALLROOT}/bin/iffe.old 2>/dev/null || true; ${STDCP} iffe ${INSTALLROOT}/bin/iffe ;}
+done ${INSTALLROOT}/bin/iffe generated
+make ${INSTALLROOT}/bin/mktest
+prev mktest
+exec - test '' = 'mktest' || ${STDCMP} 2>/dev/null -s mktest ${INSTALLROOT}/bin/mktest || { ${STDMV} ${INSTALLROOT}/bin/mktest ${INSTALLROOT}/bin/mktest.old 2>/dev/null || true; ${STDCP} mktest ${INSTALLROOT}/bin/mktest ;}
+done ${INSTALLROOT}/bin/mktest generated
+make ${INSTALLROOT}/bin/package
+prev package
+exec - test '' = 'package' || ${STDCMP} 2>/dev/null -s package ${INSTALLROOT}/bin/package || { ${STDMV} ${INSTALLROOT}/bin/package ${INSTALLROOT}/bin/package.old 2>/dev/null || true; ${STDCP} package ${INSTALLROOT}/bin/package ;}
+done ${INSTALLROOT}/bin/package generated
+make ${INSTALLROOT}/bin/regress
+prev regress
+exec - test '' = 'regress' || ${STDCMP} 2>/dev/null -s regress ${INSTALLROOT}/bin/regress || { ${STDMV} ${INSTALLROOT}/bin/regress ${INSTALLROOT}/bin/regress.old 2>/dev/null || true; ${STDCP} regress ${INSTALLROOT}/bin/regress ;}
+done ${INSTALLROOT}/bin/regress generated
+make ${INSTALLROOT}/bin/rt
+prev rt
+exec - test '' = 'rt' || ${STDCMP} 2>/dev/null -s rt ${INSTALLROOT}/bin/rt || { ${STDMV} ${INSTALLROOT}/bin/rt ${INSTALLROOT}/bin/rt.old 2>/dev/null || true; ${STDCP} rt ${INSTALLROOT}/bin/rt ;}
+done ${INSTALLROOT}/bin/rt generated
+make ${PACKAGEROOT}/bin
+exec - if silent test ! -d ${PACKAGEROOT}/bin
+exec - then mkdir -p ${PACKAGEROOT}/bin
+exec - fi
+done ${PACKAGEROOT}/bin generated
+make ${PACKAGEROOT}/bin/execrate
+prev ${PACKAGEROOT}/bin
+prev execrate
+exec - test '' = 'execrate' || ${STDCMP} 2>/dev/null -s execrate ${PACKAGEROOT}/bin/execrate || { ${STDMV} ${PACKAGEROOT}/bin/execrate ${PACKAGEROOT}/bin/execrate.old 2>/dev/null || true; ${STDCP} execrate ${PACKAGEROOT}/bin/execrate ;}
+done ${PACKAGEROOT}/bin/execrate generated
+make ${PACKAGEROOT}/bin/ignore
+prev ignore
+exec - test '' = 'ignore' || ${STDCMP} 2>/dev/null -s ignore ${PACKAGEROOT}/bin/ignore || { ${STDMV} ${PACKAGEROOT}/bin/ignore ${PACKAGEROOT}/bin/ignore.old 2>/dev/null || true; ${STDCP} ignore ${PACKAGEROOT}/bin/ignore ;}
+done ${PACKAGEROOT}/bin/ignore generated
+make ${PACKAGEROOT}/bin/mamprobe
+make mamprobe
+meta mamprobe %.sh>% mamprobe.sh mamprobe
+make mamprobe.sh
+done mamprobe.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : mamprobe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n mamprobe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp mamprobe.sh mamprobe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < mamprobe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - mamprobe.sh <<'!'
+exec -
+exec - !
+exec - } > mamprobe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - mamprobe.sh > mamprobe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w mamprobe -a -x mamprobe || chmod u+w,+x mamprobe
+done mamprobe generated
+exec - test '' = 'mamprobe' || ${STDCMP} 2>/dev/null -s mamprobe ${PACKAGEROOT}/bin/mamprobe || { ${STDMV} ${PACKAGEROOT}/bin/mamprobe ${PACKAGEROOT}/bin/mamprobe.old 2>/dev/null || true; ${STDCP} mamprobe ${PACKAGEROOT}/bin/mamprobe ;}
+done ${PACKAGEROOT}/bin/mamprobe generated
+make ${PACKAGEROOT}/bin/package
+prev package
+exec - test '' = 'package' || ${STDCMP} 2>/dev/null -s package ${PACKAGEROOT}/bin/package || { ${STDMV} ${PACKAGEROOT}/bin/package ${PACKAGEROOT}/bin/package.old 2>/dev/null || true; ${STDCP} package ${PACKAGEROOT}/bin/package ;}
+done ${PACKAGEROOT}/bin/package generated
+make ${PACKAGEROOT}/bin/silent
+prev silent
+exec - test '' = 'silent' || ${STDCMP} 2>/dev/null -s silent ${PACKAGEROOT}/bin/silent || { ${STDMV} ${PACKAGEROOT}/bin/silent ${PACKAGEROOT}/bin/silent.old 2>/dev/null || true; ${STDCP} silent ${PACKAGEROOT}/bin/silent ;}
+done ${PACKAGEROOT}/bin/silent generated
+make ${INSTALLROOT}/bin/crossexec
+prev crossexec
+exec - test '' = 'crossexec' || ${STDCMP} 2>/dev/null -s crossexec ${INSTALLROOT}/bin/crossexec || { ${STDMV} ${INSTALLROOT}/bin/crossexec ${INSTALLROOT}/bin/crossexec.old 2>/dev/null || true; ${STDCP} crossexec ${INSTALLROOT}/bin/crossexec ;}
+done ${INSTALLROOT}/bin/crossexec generated
+make ${INSTALLROOT}/bin/ditto
+prev ditto
+exec - test '' = 'ditto' || ${STDCMP} 2>/dev/null -s ditto ${INSTALLROOT}/bin/ditto || { ${STDMV} ${INSTALLROOT}/bin/ditto ${INSTALLROOT}/bin/ditto.old 2>/dev/null || true; ${STDCP} ditto ${INSTALLROOT}/bin/ditto ;}
+done ${INSTALLROOT}/bin/ditto generated
+make ${INSTALLROOT}/bin/filter
+prev filter
+exec - test '' = 'filter' || ${STDCMP} 2>/dev/null -s filter ${INSTALLROOT}/bin/filter || { ${STDMV} ${INSTALLROOT}/bin/filter ${INSTALLROOT}/bin/filter.old 2>/dev/null || true; ${STDCP} filter ${INSTALLROOT}/bin/filter ;}
+done ${INSTALLROOT}/bin/filter generated
+make ${PACKAGEROOT}/lib/package
+exec - if silent test ! -d ${PACKAGEROOT}/lib/package
+exec - then mkdir -p ${PACKAGEROOT}/lib/package
+exec - fi
+done ${PACKAGEROOT}/lib/package generated
+make ${PACKAGEROOT}/lib/package/package.mk
+prev ${PACKAGEROOT}/lib/package
+make package.mk
+done package.mk
+exec - test '' = 'package.mk' || ${STDCMP} 2>/dev/null -s package.mk ${PACKAGEROOT}/lib/package/package.mk || { ${STDMV} ${PACKAGEROOT}/lib/package/package.mk ${PACKAGEROOT}/lib/package/package.mk.old 2>/dev/null || true; ${STDCP} package.mk ${PACKAGEROOT}/lib/package/package.mk ;}
+done ${PACKAGEROOT}/lib/package/package.mk generated
+make ${PACKAGEROOT}/lib/package/CONVERT.mk
+make CONVERT.mk
+done CONVERT.mk
+exec - test '' = 'CONVERT.mk' || ${STDCMP} 2>/dev/null -s CONVERT.mk ${PACKAGEROOT}/lib/package/CONVERT.mk || { ${STDMV} ${PACKAGEROOT}/lib/package/CONVERT.mk ${PACKAGEROOT}/lib/package/CONVERT.mk.old 2>/dev/null || true; ${STDCP} CONVERT.mk ${PACKAGEROOT}/lib/package/CONVERT.mk ;}
+done ${PACKAGEROOT}/lib/package/CONVERT.mk generated
+make ${INSTALLROOT}/lib/make
+exec - if silent test ! -d ${INSTALLROOT}/lib/make
+exec - then mkdir -p ${INSTALLROOT}/lib/make
+exec - fi
+done ${INSTALLROOT}/lib/make generated
+make ${INSTALLROOT}/lib/make/package.mk
+prev ${INSTALLROOT}/lib/make
+prev package.mk
+exec - test '' = 'package.mk' || ${STDCMP} 2>/dev/null -s package.mk ${INSTALLROOT}/lib/make/package.mk || { ${STDMV} ${INSTALLROOT}/lib/make/package.mk ${INSTALLROOT}/lib/make/package.mk.old 2>/dev/null || true; ${STDCP} package.mk ${INSTALLROOT}/lib/make/package.mk ;}
+done ${INSTALLROOT}/lib/make/package.mk generated
+make ${INSTALLROOT}/lib/make/PROBE.mk
+make PROBE.mk
+done PROBE.mk
+exec - test '' = 'PROBE.mk' || ${STDCMP} 2>/dev/null -s PROBE.mk ${INSTALLROOT}/lib/make/PROBE.mk || { ${STDMV} ${INSTALLROOT}/lib/make/PROBE.mk ${INSTALLROOT}/lib/make/PROBE.mk.old 2>/dev/null || true; ${STDCP} PROBE.mk ${INSTALLROOT}/lib/make/PROBE.mk ;}
+done ${INSTALLROOT}/lib/make/PROBE.mk generated
+make ${INSTALLROOT}/lib/make/TEST.mk
+make TEST.mk
+done TEST.mk
+exec - test '' = 'TEST.mk' || ${STDCMP} 2>/dev/null -s TEST.mk ${INSTALLROOT}/lib/make/TEST.mk || { ${STDMV} ${INSTALLROOT}/lib/make/TEST.mk ${INSTALLROOT}/lib/make/TEST.mk.old 2>/dev/null || true; ${STDCP} TEST.mk ${INSTALLROOT}/lib/make/TEST.mk ;}
+done ${INSTALLROOT}/lib/make/TEST.mk generated
+make ${INSTALLROOT}/lib/make/WWW.mk
+make WWW.mk
+done WWW.mk
+exec - test '' = 'WWW.mk' || ${STDCMP} 2>/dev/null -s WWW.mk ${INSTALLROOT}/lib/make/WWW.mk || { ${STDMV} ${INSTALLROOT}/lib/make/WWW.mk ${INSTALLROOT}/lib/make/WWW.mk.old 2>/dev/null || true; ${STDCP} WWW.mk ${INSTALLROOT}/lib/make/WWW.mk ;}
+done ${INSTALLROOT}/lib/make/WWW.mk generated
+make ${INSTALLROOT}/lib/make/MSGFUN.mk
+make MSGFUN.mk
+done MSGFUN.mk
+exec - test '' = 'MSGFUN.mk' || ${STDCMP} 2>/dev/null -s MSGFUN.mk ${INSTALLROOT}/lib/make/MSGFUN.mk || { ${STDMV} ${INSTALLROOT}/lib/make/MSGFUN.mk ${INSTALLROOT}/lib/make/MSGFUN.mk.old 2>/dev/null || true; ${STDCP} MSGFUN.mk ${INSTALLROOT}/lib/make/MSGFUN.mk ;}
+done ${INSTALLROOT}/lib/make/MSGFUN.mk generated
+make ${INSTALLROOT}/lib/make/MSGKEY.mk
+make MSGKEY.mk
+done MSGKEY.mk
+exec - test '' = 'MSGKEY.mk' || ${STDCMP} 2>/dev/null -s MSGKEY.mk ${INSTALLROOT}/lib/make/MSGKEY.mk || { ${STDMV} ${INSTALLROOT}/lib/make/MSGKEY.mk ${INSTALLROOT}/lib/make/MSGKEY.mk.old 2>/dev/null || true; ${STDCP} MSGKEY.mk ${INSTALLROOT}/lib/make/MSGKEY.mk ;}
+done ${INSTALLROOT}/lib/make/MSGKEY.mk generated
+make ${INSTALLROOT}/lib/make/MAPLIB.mk
+make MAPLIB.mk
+done MAPLIB.mk
+exec - test '' = 'MAPLIB.mk' || ${STDCMP} 2>/dev/null -s MAPLIB.mk ${INSTALLROOT}/lib/make/MAPLIB.mk || { ${STDMV} ${INSTALLROOT}/lib/make/MAPLIB.mk ${INSTALLROOT}/lib/make/MAPLIB.mk.old 2>/dev/null || true; ${STDCP} MAPLIB.mk ${INSTALLROOT}/lib/make/MAPLIB.mk ;}
+done ${INSTALLROOT}/lib/make/MAPLIB.mk generated
+make ${INSTALLROOT}/bin/mamake
+prev mamake
+exec - test '' = 'mamake' || ${STDCMP} 2>/dev/null -s mamake ${INSTALLROOT}/bin/mamake || { ${STDMV} ${INSTALLROOT}/bin/mamake ${INSTALLROOT}/bin/mamake.old 2>/dev/null || true; ${STDCP} mamake ${INSTALLROOT}/bin/mamake ;}
+done ${INSTALLROOT}/bin/mamake generated
+make ${INSTALLROOT}/bin/proto
+prev proto
+exec - test '' = 'proto' || ${STDCMP} 2>/dev/null -s proto ${INSTALLROOT}/bin/proto || { ${STDMV} ${INSTALLROOT}/bin/proto ${INSTALLROOT}/bin/proto.old 2>/dev/null || true; ${STDCP} proto ${INSTALLROOT}/bin/proto ;}
+done ${INSTALLROOT}/bin/proto generated
+make ${INSTALLROOT}/bin/ratz
+prev ratz
+exec - test '' = 'ratz' || ${STDCMP} 2>/dev/null -s ratz ${INSTALLROOT}/bin/ratz || { ${STDMV} ${INSTALLROOT}/bin/ratz ${INSTALLROOT}/bin/ratz.old 2>/dev/null || true; ${STDCP} ratz ${INSTALLROOT}/bin/ratz ;}
+done ${INSTALLROOT}/bin/ratz generated
+make ${INSTALLROOT}/bin/release
+prev release
+exec - test '' = 'release' || ${STDCMP} 2>/dev/null -s release ${INSTALLROOT}/bin/release || { ${STDMV} ${INSTALLROOT}/bin/release ${INSTALLROOT}/bin/release.old 2>/dev/null || true; ${STDCP} release ${INSTALLROOT}/bin/release ;}
+done ${INSTALLROOT}/bin/release generated
+make ${INSTALLROOT}/bin/mkdir
+make mkdir.sh
+done mkdir.sh
+exec - if test ! -x ${INSTALLROOT}/bin/mkdir -a -x /bin/mkdir
+exec - then mkdir -p 2>/dev/null || :
+exec - if test -d ./-p
+exec - then rmdir ./-p
+exec - cp mkdir.sh ${INSTALLROOT}/bin/mkdir
+exec - chmod +x ${INSTALLROOT}/bin/mkdir
+exec - fi
+exec - fi
+done ${INSTALLROOT}/bin/mkdir generated
+make ${INSTALLROOT}/bin/.paths
+exec - if test ! -f ${INSTALLROOT}/bin/.paths -o -w ${INSTALLROOT}/bin/.paths
+exec - then nl="
+exec - "
+exec - o=`cat ${INSTALLROOT}/bin/.paths 2>/dev/null` || :
+exec - v=
+exec - n=
+exec - case $nl$o in
+exec - *${nl}FPATH=*|*#FPATH=*|*[Nn][Oo]FPATH=*)
+exec - ;;
+exec - *) case $n in
+exec - '') ;;
+exec - *) n="$n$nl" v="$v|" ;;
+exec - esac
+exec - n="${n}FPATH=../fun"
+exec - v="${v}FPATH"
+exec - ;;
+exec - esac
+exec - case $nl$o in
+exec - *${nl}BUILTIN_LIB=*|*#BUILTIN_LIB=*|*[Nn][Oo]BUILTIN_LIB=*)
+exec - ;;
+exec - *) case $n in
+exec - '') ;;
+exec - *) n="$n$nl" v="$v|" ;;
+exec - esac
+exec - case '' in
+exec - ?*) p= c= ;;
+exec - *) p='XX' ;;
+exec - esac
+exec - n="${n}${p}BUILTIN_LIB=cmd"
+exec - v="${v}BUILTIN_LIB"
+exec - ;;
+exec - esac
+exec - set x x :
+exec - p=
+exec - while :
+exec - do while :
+exec - do case $# in
+exec - 0) break ;;
+exec - esac
+exec - x=$1
+exec - shift
+exec - case $x in
+exec - :) break ;;
+exec - esac
+exec - done
+exec - case $# in
+exec - 0|1) break
+exec - ;;
+exec - 2) p=$2
+exec - ;;
+exec - *) case "${mam_cc_HOSTTYPE}" in
+exec - $3) p=$2; break ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - done
+exec - case $p in
+exec - '') if test -x /lib/dld.sl
+exec - then p=SHLIB_PATH
+exec - elif test -x /usr/lib/dyld
+exec - then p=DYLD_LIBRARY_PATH
+exec - else case "${mam_cc_HOSTTYPE}" in
+exec - ibm.*|mvs.*)
+exec - p=LIBPATH
+exec - ;;
+exec - sgi.mips3)
+exec - p=LD_LIBRARYN32_PATH
+exec - ;;
+exec - sgi.mips4)
+exec - p=LD_LIBRARYN64_PATH
+exec - ;;
+exec - *) p=LD_LIBRARY_PATH
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - case $nl$o in
+exec - *${nl}${p}=*|*#${p}=*|*[Nn][Oo]${p}=*)
+exec - ;;
+exec - *) case $n in
+exec - '') ;;
+exec - *) n="$n$nl" v="$v|" ;;
+exec - esac
+exec - n="${n}${p}=../lib"
+exec - v="${v}${p}"
+exec - ;;
+exec - esac
+exec - case $n in
+exec - ?*) case $o in
+exec - ?*) o=`egrep -v "($v)=" ${INSTALLROOT}/bin/.paths`$nl ;;
+exec - esac
+exec - echo "# use { # no NO } prefix instead of XX to permanently disable #$nl$o$n" > ${INSTALLROOT}/bin/.paths
+exec - ;;
+exec - esac
+exec - fi
+done ${INSTALLROOT}/bin/.paths generated
+make ${INSTALLROOT}/lib/probe/C
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C
+exec - fi
+done ${INSTALLROOT}/lib/probe/C generated
+make ${INSTALLROOT}/lib/probe/C/probe
+prev ${INSTALLROOT}/lib/probe/C
+prev C+probe
+exec - test '' = 'C+probe' || ${STDCMP} 2>/dev/null -s C+probe ${INSTALLROOT}/lib/probe/C/probe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/probe ${INSTALLROOT}/lib/probe/C/probe.old 2>/dev/null || true; ${STDCP} C+probe ${INSTALLROOT}/lib/probe/C/probe ;}
+done ${INSTALLROOT}/lib/probe/C/probe generated
+make ${INSTALLROOT}/lib/probe/C/make
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C/make
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C/make
+exec - fi
+done ${INSTALLROOT}/lib/probe/C/make generated
+prev ${INSTALLROOT}/lib/probe/C/make
+make ${INSTALLROOT}/lib/probe/C/pp
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C/pp
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C/pp
+exec - fi
+done ${INSTALLROOT}/lib/probe/C/pp generated
+prev ${INSTALLROOT}/lib/probe/C/pp
+make ${INSTALLROOT}/lib/probe/C/mam
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C/mam
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C/mam
+exec - fi
+done ${INSTALLROOT}/lib/probe/C/mam generated
+make ${INSTALLROOT}/lib/probe/C/mam/probe
+prev ${INSTALLROOT}/lib/probe/C/mam
+prev mprobe
+exec - test '' = 'mprobe' || ${STDCMP} 2>/dev/null -s mprobe ${INSTALLROOT}/lib/probe/C/mam/probe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/mam/probe ${INSTALLROOT}/lib/probe/C/mam/probe.old 2>/dev/null || true; ${STDCP} mprobe ${INSTALLROOT}/lib/probe/C/mam/probe ;}
+done ${INSTALLROOT}/lib/probe/C/mam/probe generated
+make ${INSTALLROOT}/lib/probe/C/mam/mprobe
+prev mprobe
+exec - test '' = 'mprobe' || ${STDCMP} 2>/dev/null -s mprobe ${INSTALLROOT}/lib/probe/C/mam/mprobe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/mam/mprobe ${INSTALLROOT}/lib/probe/C/mam/mprobe.old 2>/dev/null || true; ${STDCP} mprobe ${INSTALLROOT}/lib/probe/C/mam/mprobe ;}
+done ${INSTALLROOT}/lib/probe/C/mam/mprobe generated
+make ${INSTALLROOT}/lib/probe/C/make/probe
+prev probe
+exec - test '' = 'probe' || ${STDCMP} 2>/dev/null -s probe ${INSTALLROOT}/lib/probe/C/make/probe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/make/probe ${INSTALLROOT}/lib/probe/C/make/probe.old 2>/dev/null || true; ${STDCP} probe ${INSTALLROOT}/lib/probe/C/make/probe ;}
+done ${INSTALLROOT}/lib/probe/C/make/probe generated
+make ${INSTALLROOT}/lib/probe/C/make/probe.ini
+make probe.ini
+make probe.win32
+done probe.win32
+exec - t=${mam_cc_HOSTTYPE}
+exec - ifs=$IFS
+exec - IFS=.
+exec - set x $t
+exec - IFS=$ifs
+exec - t=$2
+exec - set x probe.win32
+exec - while :
+exec - do shift
+exec - case $# in
+exec - 0) break ;;
+exec - esac
+exec - case $1 in
+exec - *probe.$t)
+exec - break
+exec - esac
+exec - done
+exec - case $1 in
+exec - ?*) cmp -s $1 probe.ini || cp $1 probe.ini ;;
+exec - *) : > probe.ini
+exec - esac
+done probe.ini generated
+exec - test '' = 'probe.ini' || ${STDCMP} 2>/dev/null -s probe.ini ${INSTALLROOT}/lib/probe/C/make/probe.ini || { ${STDMV} ${INSTALLROOT}/lib/probe/C/make/probe.ini ${INSTALLROOT}/lib/probe/C/make/probe.ini.old 2>/dev/null || true; ${STDCP} probe.ini ${INSTALLROOT}/lib/probe/C/make/probe.ini ;}
+done ${INSTALLROOT}/lib/probe/C/make/probe.ini generated
+make ${INSTALLROOT}/include
+exec - if silent test ! -d ${INSTALLROOT}/include
+exec - then mkdir -p ${INSTALLROOT}/include
+exec - fi
+done ${INSTALLROOT}/include generated
+make ${INSTALLROOT}/include/prototyped.h
+prev ${INSTALLROOT}/include
+make prototyped.h
+prev ${INSTALLROOT}/bin/proto
+exec - proto -f /dev/null > h.${COTEMP}.h
+exec - if cmp 2>/dev/null -s h.${COTEMP}.h prototyped.h
+exec - then rm -f h.${COTEMP}.h
+exec - else mv h.${COTEMP}.h prototyped.h
+exec - fi
+done prototyped.h generated
+exec - test '' = 'prototyped.h' || ${STDCMP} 2>/dev/null -s prototyped.h ${INSTALLROOT}/include/prototyped.h || { ${STDMV} ${INSTALLROOT}/include/prototyped.h ${INSTALLROOT}/include/prototyped.h.old 2>/dev/null || true; ${STDCP} prototyped.h ${INSTALLROOT}/include/prototyped.h ;}
+done ${INSTALLROOT}/include/prototyped.h generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/dl
+prev ${INSTALLROOT}/lib/lib
+make dl.req
+make dl.c
+done dl.c
+exec - set -
+exec - r='-'
+exec - for i in dl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in dl -
+exec - do case $p in
+exec - -) if ${CC} -o dl.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o dl.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > dl.req
+exec - rm -f dl.exe dl
+done dl.req generated
+exec - test '' = 'dl.req' || ${STDCMP} 2>/dev/null -s dl.req ${INSTALLROOT}/lib/lib/dl || { ${STDMV} ${INSTALLROOT}/lib/lib/dl ${INSTALLROOT}/lib/lib/dl.old 2>/dev/null || true; ${STDCP} dl.req ${INSTALLROOT}/lib/lib/dl ;}
+done ${INSTALLROOT}/lib/lib/dl generated
+make ${INSTALLROOT}/lib/lib/iconv
+make iconv.req
+make iconv.c
+done iconv.c
+exec - set -
+exec - r='-'
+exec - for i in iconv.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in iconv -
+exec - do case $p in
+exec - -) if ${CC} -o iconv.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o iconv.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > iconv.req
+exec - rm -f iconv.exe iconv
+done iconv.req generated
+exec - test '' = 'iconv.req' || ${STDCMP} 2>/dev/null -s iconv.req ${INSTALLROOT}/lib/lib/iconv || { ${STDMV} ${INSTALLROOT}/lib/lib/iconv ${INSTALLROOT}/lib/lib/iconv.old 2>/dev/null || true; ${STDCP} iconv.req ${INSTALLROOT}/lib/lib/iconv ;}
+done ${INSTALLROOT}/lib/lib/iconv generated
+make ${INSTALLROOT}/lib/lib/w
+make w.req
+make w.c
+done w.c
+make w2.c
+done w2.c
+exec - set -
+exec - r='-'
+exec - for i in w.c w2.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in w -
+exec - do case $p in
+exec - -) if ${CC} -o w.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o w.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > w.req
+exec - rm -f w.exe w w2
+done w.req generated
+exec - test '' = 'w.req' || ${STDCMP} 2>/dev/null -s w.req ${INSTALLROOT}/lib/lib/w || { ${STDMV} ${INSTALLROOT}/lib/lib/w ${INSTALLROOT}/lib/lib/w.old 2>/dev/null || true; ${STDCP} w.req ${INSTALLROOT}/lib/lib/w ;}
+done ${INSTALLROOT}/lib/lib/w generated
+make ${INSTALLROOT}/lib/lib/intl
+make intl.req
+make intl.c
+done intl.c
+exec - set -
+exec - r='-'
+exec - for i in intl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in intl -
+exec - do case $p in
+exec - -) if ${CC} -o intl.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o intl.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > intl.req
+exec - rm -f intl.exe intl
+done intl.req generated
+exec - test '' = 'intl.req' || ${STDCMP} 2>/dev/null -s intl.req ${INSTALLROOT}/lib/lib/intl || { ${STDMV} ${INSTALLROOT}/lib/lib/intl ${INSTALLROOT}/lib/lib/intl.old 2>/dev/null || true; ${STDCP} intl.req ${INSTALLROOT}/lib/lib/intl ;}
+done ${INSTALLROOT}/lib/lib/intl generated
+make ${INSTALLROOT}/lib/lib/m
+make m.req
+make m.c
+done m.c
+make m2.c
+done m2.c
+make m3.c
+done m3.c
+make m4.c
+done m4.c
+make m5.c
+done m5.c
+make m6.c
+done m6.c
+exec - set -
+exec - r='-'
+exec - for i in m.c m2.c m3.c m4.c m5.c m6.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in m -
+exec - do case $p in
+exec - -) if ${CC} -o m.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o m.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > m.req
+exec - rm -f m.exe m m2 m3 m4 m5 m6
+done m.req generated
+exec - test '' = 'm.req' || ${STDCMP} 2>/dev/null -s m.req ${INSTALLROOT}/lib/lib/m || { ${STDMV} ${INSTALLROOT}/lib/lib/m ${INSTALLROOT}/lib/lib/m.old 2>/dev/null || true; ${STDCP} m.req ${INSTALLROOT}/lib/lib/m ;}
+done ${INSTALLROOT}/lib/lib/m generated
+make ${INSTALLROOT}/lib/lib/nsl
+make nsl.req
+make nsl.c
+done nsl.c
+exec - set -
+exec - r='-'
+exec - for i in nsl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in nsl -
+exec - do case $p in
+exec - -) if ${CC} -o nsl.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o nsl.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > nsl.req
+exec - rm -f nsl.exe nsl
+done nsl.req generated
+exec - test '' = 'nsl.req' || ${STDCMP} 2>/dev/null -s nsl.req ${INSTALLROOT}/lib/lib/nsl || { ${STDMV} ${INSTALLROOT}/lib/lib/nsl ${INSTALLROOT}/lib/lib/nsl.old 2>/dev/null || true; ${STDCP} nsl.req ${INSTALLROOT}/lib/lib/nsl ;}
+done ${INSTALLROOT}/lib/lib/nsl generated
+make ${INSTALLROOT}/lib/lib/socket
+make socket.req
+make socket.c
+done socket.c
+prev nsl.c
+exec - set -
+exec - r='-'
+exec - for i in socket.c nsl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in socket -
+exec - do case $p in
+exec - -) if ${CC} -o socket.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o socket.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > socket.req
+exec - rm -f socket.exe socket nsl
+done socket.req generated
+exec - test '' = 'socket.req' || ${STDCMP} 2>/dev/null -s socket.req ${INSTALLROOT}/lib/lib/socket || { ${STDMV} ${INSTALLROOT}/lib/lib/socket ${INSTALLROOT}/lib/lib/socket.old 2>/dev/null || true; ${STDCP} socket.req ${INSTALLROOT}/lib/lib/socket ;}
+done ${INSTALLROOT}/lib/lib/socket generated
+make ${INSTALLROOT}/lib/lib/dbm
+make dbm.req
+make db.c
+done db.c
+make gdbm.c
+done gdbm.c
+make gdbm1.c
+make gdbm-ndbm.h implicit
+done gdbm-ndbm.h dontcare virtual
+done gdbm1.c
+make gdbm2.c
+make ndbm.h implicit
+done ndbm.h dontcare virtual
+done gdbm2.c
+exec - set -
+exec - r='-'
+exec - for i in db.c gdbm.c gdbm1.c gdbm2.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in db - gdbm_compat - gdbm - ndbm - dbm -
+exec - do case $p in
+exec - -) if ${CC} -o dbm.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o dbm.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > dbm.req
+exec - rm -f dbm.exe db gdbm gdbm1 gdbm2
+done dbm.req generated
+exec - test '' = 'dbm.req' || ${STDCMP} 2>/dev/null -s dbm.req ${INSTALLROOT}/lib/lib/dbm || { ${STDMV} ${INSTALLROOT}/lib/lib/dbm ${INSTALLROOT}/lib/lib/dbm.old 2>/dev/null || true; ${STDCP} dbm.req ${INSTALLROOT}/lib/lib/dbm ;}
+done ${INSTALLROOT}/lib/lib/dbm generated
+done install virtual
+make test
+make test.iffe
+prev iffe
+make iffe.tst
+done iffe.tst
+exec - regress iffe.tst iffe
+done test.iffe virtual
+make test.mamake
+prev mamake
+make mamake.tst
+meta mamake.tst %.rt>%.tst mamake.rt mamake
+make mamake.rt
+done mamake.rt
+exec - if [[ "1" || "mamake.rt" -nt "mamake.tst" ]]
+exec - then mktest --style=regress mamake.rt > mamake.tst
+exec - fi
+done mamake.tst generated
+exec - regress mamake.tst mamake
+done test.mamake virtual
+done test dontcare virtual
diff --git a/src/cmd/INIT/PROBE.mk b/src/cmd/INIT/PROBE.mk
new file mode 100644
index 0000000..9a8553f
--- /dev/null
+++ b/src/cmd/INIT/PROBE.mk
@@ -0,0 +1,13 @@
+/*
+ * @(#)probe (AT&T Bell Laboratories) 11/11/91
+ *
+ * <lang> <tool> :PROBE: *.probe *.sh *
+ *
+ * common probe script installation
+ * generates probe.sh and probe in .
+ */
+
+":PROBE:" : .MAKE .OPERATOR
+ probe.sh : $(LIBDIR)/probe/$(<:O=1)/probe $(>:N=*.(probe|sh))
+ cat $(*) > $(<)
+ $(LIBDIR)/probe/$(<:O=1)/$(<:O=2) :INSTALLDIR: probe $(>:N!=*.(probe|sh))
diff --git a/src/cmd/INIT/RELEASE b/src/cmd/INIT/RELEASE
new file mode 100644
index 0000000..ebed09f
--- /dev/null
+++ b/src/cmd/INIT/RELEASE
@@ -0,0 +1,918 @@
+12-02-29 cc.darwin.i386*: handle default cc vs kernel bittedness
+12-02-29 C+probe: add __TIMESTAMP__ to the nopredefined list
+12-02-29 package.sh: don't assume grep -q or /usr/local/lib in LD_LIBRARY_PATH
+12-02-29 package.sh: fix ksh vs -lcmd compatibility checks
+12-02-23 iffe.sh: checkcc() before checkread() for sensible diagnostics
+12-02-14 package.mk: { --clobber --compare --link=lib*.a* } for --mam=static
+12-02-14 package.mk: export LICENSEFILEDEFAULT instead of LICENSEFILE
+12-02-14 package.sh: handle @(cc|ld).${HOSTTYPE}* intercepts
+12-02-07 package.sh: add { clean clobber } actions
+12-02-02 regress.sh: fix ulimit -c defaults for --nokeep
+12-01-18 regress.sh: add INPUT|OUTPUT|ERROR -e 'filter' to filter before comparison
+12-01-21 package.sh: fix `admin make' bug that created unused $INSTALLROOT/lib
+12-01-21 Makefile: :PACKAGE: license=ast -- oops
+12-01-20 cc.darwin,cc.mvs.390: tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+12-01-12 package.sh: add admin make share closure to handle alternate HOSTTYPEs
+11-12-13 iffe.sh: add /*<NOSTDIO>*/ test code comment to disable default #include <stdio.h>
+11-11-11 C+probe: test for .so before .sl
+11-10-26 package.sh: don't forget about *.pkg for admin update
+11-10-18 cc.*-icc: update and add more
+11-10-11 package.sh: handle package make|view when no source installed
+11-09-11 package.sh: count admin '*** termination code' errors
+11-08-31 mamake.c: add -e, ignore use recursive prereq timestamps
+11-08-29 iffe.sh: add ``set stdio try1.h - try2.h ...''
+11-08-29 iffe.sh: trap EXIT => trap 0 for ancient sh
+11-08-11 iffe.sh: handle ancient sort that doesn't have -k
+11-06-01 make.probe: add more /lib64 logic
+11-05-01 package.sh: fix admin ditto to sync LICENSES too
+11-03-25 package.sh: initialize { $SED $TR } before first use!
+11-03-21 package.sh: fix vpath probes
+11-03-17 iffe.sh: fix cleanup to rm $tmp* instead of $tmp*.*
+11-02-24 package.sh: change curl usage to "curl -L ..."
+11-02-11 package.sh,C+probe,make.probe,mamprobe.sh: add ###.*archiac.*###
+11-02-02 Makefile: add :MAPLIB: check for ancient -lw
+11-02-02 make.probe: handle -print-multi-directory => 64 => /usr/lib64 /lib64
+11-02-02 package.sh: HOSTTYPE=*,*cc*[,-*,...] sets CC [ and CCFLAGS ]
+11-02-02 make.probe: handle gcc $ORIGIN link but exec failure -- gee thanks
+11-01-25 cc.hp.ia64: bundled cc is a pile of shaving cream
+11-01-07 iffe.sh: check debug==3 for is_hdr() failure
+10-11-22 ditto.sh: fix timing problem between |& and exec &p
+10-11-10 package.sh: fix cc cross compile check to use checkcc absolute path
+10-10-10 package.sh: list main env vars at start of make action
+10-10-10 ratz.c: tweak widnows delays
+10-09-10 ratz.c: add _SEAR_ARGS for _SEAR_EXEC
+10-09-01 package.sh: fix ratz from source logic
+10-08-25 package.mk: consolidate license file search in .package.licenses.
+10-08-22 ratz.c: run sear bootstrap command detached
+10-08-20 C+probe: version_stamp only if version_flags works
+10-08-17 package.sh: unset makerules *DIR variables in env
+10-08-15 package.sh: "make" action now lists some env values
+10-08-11 mktest.sh: add "DO command ..."
+10-07-27 rt.sh: handle "rt X=Y ..."
+10-06-29 ratz.c: non-option sear args passed to sear_exec()
+10-06-25 iffe.sh: "api" op chanegd to not do "map-libc" type mappings
+10-06-25 package.sh: "force admin ditto" => no ditto --update option
+10-06-22 C+probe: handle cc that require .[ci] input for version info
+10-06-21 ditto.sh: change default remote access to ssh (about time)
+10-06-12 regress.sh: DISGNOSTICS [ 1 | 0 | pattern ] and fix EXIT for all
+10-06-09 package.sh: add AT&T to usable nmake check
+10-06-06 iffe.sh,iffe.tst: add { api ver } ops
+10-04-22 package.sh: update "html binary|source" NAME/PASSWORD info
+10-04-15 iffe.sh: don't forget candidate headers for hdr|sys!
+10-04-11 WWW.mk: disable man page metarule -- now done by admin-man(1)
+10-02-14 package.sh: $CC verification needs $INSTALLROOT/bin in PATH
+10-02-11 package.sh: fix package admin make report error count
+10-02-02 package.sh: fix write binary bug that did scp on local fs
+10-02-02 package.mk: up to date binary targets must still be in PACKAGE.*.lst
+10-01-01 package.sh: fix premature $INSTALLROOT/bin during cross compile check
+10-01-01 make.probe: handle ['"] in CC.VERSION.STRING
+09-12-04 iffe.sh: add "opt name" to check for name in $PACKAGE_OPTIONS
+09-11-30 mktest.sh: change RESET to STATE.RESET to make it global
+09-11-14 make.probe: use gcc { -print-multi-directory -print-search-dirs }
+09-11-11 package.sh: re-order and combine cc checks
+09-10-27 C+probe,make.probe,probe.win32: add CC.SUFFIX.DEBUG
+09-10-21 iffe.sh,Makefile: test -e is not in ksh88!
+09-10-06 iffe.sh: handle cc -E #error with 0 exit status (sgi)
+09-10-06 package.sh: stub in ar intercept checks -- not used yet
+09-10-06 ar.ibm.risc: add ar intercept because some aix require -Xfoo first!!
+09-09-24 regress.sh: fix UMASK logic to create test support files before umask
+09-08-28 release.c: change docs to mention stdin if no file operands
+09-08-24 package.sh: fix isascii() bug that failed on od(1) trailing space
+09-08-20 make.probe: add CC.SHARED.NAME
+09-08-20 regress.sh: add { JOB CONTINUE EXITED KILL FIFO }
+09-08-11 package.sh: filter lines containing : for package results
+09-07-31 make.probe: add CC.AR.ARFLAGS (for aix ar -xany)
+09-07-31 package.sh,cc.*: fix -dumpmachine to handle 32/64/* bit options
+09-06-24 package.sh: fix admin.db output formatting
+09-05-05 package.sh: export dll hackery environment vars
+09-05-05 package.sh: handle non-identifier hostnames
+09-05-05 mamake.c: pass undefined ${...} identifiers to the shell
+09-05-05 mamake.rt: add macro expansion regression tests
+09-05-01 iffe.sh: fix output initialization *again*
+09-04-28 package.sh: handle admin.db contact field $9
+09-04-15 iffe.sh: add implicit "ini" op to initialize io for subsequent ops
+09-03-31 regress.sh: EXPORT before test => global ENVIRON[]
+09-03-26 package.sh: test fail pattern is 'fail[es]'
+09-03-26 UNIT - ... appends (options) to command line
+09-03-19 TEST.mk: x.tst => x only if x is command target
+09-03-15 regress.sh: add ${MAIN} for base name of main unit
+09-03-10 TEST.mk: add .SOURCE:tests if tests is a dir
+09-03-03 regress.sh: allow command line unit to override UNIT
+09-03-03 mktest.sh: handle IO == $'\n'
+09-02-02 package.sh: delay $INSTALLROOT/bin/.paths generation until mamprobe runs
+09-01-30 cc.mvs.390: c89 balks at [ ()] in -Dname="..."!
+09-01-27 package.sh: add isascii() to use ratz instead of tar
+09-01-20 hurl.sh: add --size=bytes option
+09-01-08 TEST.mk: add test.* prereqs, multiple arg lists with :T=*: binding
+09-01-03 regress.sh: fix UNIT to allow command line override
+09-01-03 mktest.sh: handle TWD
+08-12-24 package.sh: fix cross-compile HOSTTYPE logic
+08-12-15 package.sh,hurl.sh: handle http codes { 301 302 303 }
+08-10-16 make.probe '-fno-stack-protector -fno-stack-protector-all' to cop out!!
+08-09-30 rt.sh: fix ksh93 regression test signal count
+08-09-26 regress.sh: ignore SIGPIPE for SET pipe-input
+08-09-24 package.sh: package only test foo => make --recurse=only recurse tests foo
+08-09-20 make.probe: handle another /usr/bin/file shared lib description
+08-09-20 regress.sh: add --pipefail for SET pipe-input ...
+08-09-17 Makefile: add gdbm1.c for <gdbm-ndbm.h>
+08-09-10 make.probe: add CC.NOPROTECT
+08-08-08 mktest.sh: add --width=width
+08-08-05 dbm.req: favor sleepycat ndbm compatibility
+08-08-04 C+probe: fix stdlib initialization logic
+08-06-24 package.sh: fix $INSTALLROOT/bin/cc intercept time stamp file typo
+08-06-20 TEST.mk: make the localyunit before *.rt => *.tst -- doh
+08-06-20 mktest.sh: prepend $PWD onto PATH for local units -- doh^2
+08-06-11 regress.sh: fix bug that skipped the last test
+08-05-20 regress.sh: add --local to put *.tmp dir in local fs
+08-05-05 regress.sh: add IF command ... ELIF command ... ELSE ... FI
+08-05-01 package.sh: package test => ulimit -c 0
+08-04-28 regress.sh: fix EXPORT quoting
+08-04-28 regress.sh: fix UNIT set check args too
+08-04-24 rt.sh: exit code > 256 => signal termination
+08-04-10 C+probe: change probe_so order to check .so last (macos ld workaround)
+08-04-01 package.sh: handle multiple admin HOSTTYPEs per HOST
+08-03-28 C+probe: add C++ #include <iostream> (no extension) dir probes
+08-03-17 regress.sh: fix trap on EXIT, add terminated note to final tally
+08-02-28 make.probe: fix probe_warn to include ld!
+08-02-02 make.probe: add CC.RUNPATH to match default -L order
+08-01-31 package.sh: check lib64 for LD_LIBRARY_PATH
+08-01-31 iffe.sh: tweak ancient /bin/sh workarounds
+08-01-28 make.probe: darwin ld export dynamic is -force_flat_namespace
+08-01-28 C+probe: handle sgi cc error message but exit 0 botch(es)
+08-01-23 package.sh: fix checksum doc typo
+08-01-09 C+probe: add __FUNCTION__ to the undef (don't check) list
+07-12-14 iffe.sh: add set nooptimize
+07-12-03 package.sh: add LC_ALL=C
+07-11-27 package.sh: fix overaggressive *.md5 cleanup
+07-11-20 iffe.sh: treat exit status >= 250 as normal error with no signal
+07-11-05 package.sh: fix write op error count pattern
+07-11-05 package.mk: fix $(~req) .ver binding
+07-08-11 probe.win32: add cl.exe setuid workaround, CC.VERSION[.STRING]
+07-08-01 package.sh: handle 'package read lcl|tgz'
+07-05-08 regress.sh: execute basename instead of absolute path for short $0
+07-04-27 cc.sgi.mips[34]: for #error to exit non-zero -- a no brainer
+07-04-20 mktest.sh: defer to systems without 'grep -q' -- sigh
+07-04-11 mamprobe.sh: handle $(CC.*) => ${mam_cc_*}, $(...) => ${...}
+07-04-11 make.probe: fix CC.PICBIG probe, default { CC.PIC CC.DLL } to BIG
+07-04-04 iffe.sh: prepend ${tst}${ext} to each .c probe
+07-03-28 package.sh: fix binary tgz architecture type duplication
+07-03-28 package.mk: add binary write PACKAGE.$HOSTTYPE.lst
+07-03-28 iffe.sh: add -F header to mac test
+07-03-23 make.probe: handle file(1) that returns 'archive' for .so
+07-03-22 mamprobe.sh: fix STDED probe for implementations that ignore EOF
+07-03-11 package.sh: add nocopyright and tst => nocopyright
+07-03-11 package.mk: add copyright=0
+07-03-08 C+probe: restore IFS after probe.ini
+07-02-26 mamake.c: expand first of ${mam_lib*} for ${AR}
+07-01-05 package.sh: fix "admin write binary" logic
+07-01-01 iffe.sh: add "cmd" --verbose trace
+07-01-01 iffe.sh: sort => LC_ALL=C sort
+07-01-01 C+probe: LC_ALL=C
+06-12-22 make.probe: lean on gcc -v for stdlib, but preserve /usr/local!
+06-11-23 package.sh: *.md5 are not tarballs -- doh
+06-11-23 iffe.sh: add -F, --features=feature-test-header
+06-11-11 make.probe: favor lib64 over lib for hosttype==*64
+06-10-31 make.probe: add "-ignore-source-dir -iquote" test
+06-10-31 iffe.sh: add status{...} code block
+06-10-11 regress.sh: fix DO to handle {...} (time for regress.tst?)
+06-10-11 package.sh: handle already gunzip'd *.tgz
+06-10-06 iffe.sh: add reference for header content tests
+06-09-27 regress.sh: fix UMASK to do DO too (duh)
+06-09-22 iffe.sh: drop -O for npt tests (for msvc intrinsics)
+06-09-14 cc.darwin: drop -O until gcc 4.* gets its act together
+06-09-11 package.sh: { cc ld ldd } intercepts check ${HOSTTYPE%.*} too
+06-09-08 regress.sh: add PIPE INPUT|OUTPUT for pipe io
+06-09-05 C+probe: add { probe_version version_stamp version_string }
+06-09-05 make.probe: add version stamp comment, CC.VERSION[.STRING]
+06-08-27 regress.sh,mktest.sh: add UMASK
+06-08-25 regress.sh: add -b,--ignore-space,IGNORESPACE
+06-08-25 mktest.sh: add IGNORESPACE
+06-08-24 mktest.sh: handle \000 in data
+06-08-24 regress.sh: handle -f* for INPUT|OUTPUT|ERROR
+06-08-16 package.sh: fix 'install flat' logic
+06-08-11 rt.sh: handle style=shell %K date format
+06-07-17 ratz.c: fix __MVS__ FAR definition
+06-07-17 iffe.sh: "header x.h" -- deprecate "include x.h" for .SCAN.iffe
+06-07-17 package.sh: differentiate urls vs. assignments
+06-06-27 rt.sh: add --failed, --heading
+06-06-27 C+probe,TEST.mk,make.probe,mktest.sh,regress.sh: 'ulimit -c 0'
+06-06-26 cc.darwin.ppc: handle -lcc_dynamic disappearance
+06-06-25 mktest.sh: implement PROG
+06-06-11 Makefile: add -ldbm :MAPLIB:, provide public MAPLIB.mk
+06-05-06 package.sh: add PACKAGE_admin_tail_timeout
+06-05-22 ratz.c: upgrade to zlib-1.2.3
+06-05-09 package.sh: fix admin.db docs
+06-03-11 package.sh: fix `package use - command ...'
+06-03-05 make.probe: work around pedantic bash 3.1 mismatched " in `.`
+06-02-14 package.sh: "results failed test" == "results test failed"
+ cc.sgi.*: add _AST_cc_OPTIONS parameterization, -OPT:Olimit=0
+ cc.linux.ia64-icc: add for intel cc
+06-02-02 package.sh: freebsd stuck with os version for all arch
+06-02-01 package.mk: fix locale logic (tw -d requires dir arg)
+06-01-31 package.sh: require $CC only for make|test
+06-01-30 package.sh,hurl.sh: use the backwards-compatible --http-passwd
+ package.sh: add more pdksh => /bin/sh checks
+06-01-26 package.sh: wget --http-pass => --http-password
+ package.sh: fix wget error logic
+ hurl.sh: wget --http-pass => --http-password
+06-01-11 package.mk: pass package.license.class to make --mam too
+ package.mk: variants=pattern => --variants=pattern
+ package.sh: darwin rel<=7 => darwin7.ppc
+ package.sh: freebsd rel<=4 => freebsd4
+ package.sh: freebsd rel<=5 => freebsd5
+05-12-07 iffe.sh: don't emit <stdio.h> if <sfio.h>|<ast.h> (XXX)
+05-12-05 make.probe: disable readonly.exe core dump via ulimit -c 0
+05-09-22 mktest.sh: add EXEC [ ++NOOUTPUT ++NOERROR ++NOEXIT ]
+05-09-21 mktest.sh: fix --style=shell compare to ignore \r
+05-09-12 TEST.mk: all --force to force %.rt regeneration
+05-09-05 TEST.mk: regenerate from %.rt only if newer, :SAVE: %.tst
+05-08-25 mktest.sh: add
+ TEST.mk: add %.rt=>%.tst for mktest
+05-08-18 package.sh: 'package host cpu' now checks $NPROC first
+05-07-17 iffe.sh: add { define extern include print } ops
+ iffe.sh: accept output{...}end output on success only -- doh
+05-07-01 package.sh: add TARPROBE for tar B flag probe
+05-06-24 package.sh: fix binary read chmod via *.sum
+05-06-06 package.sh: fix KEEP_HOSTTYPE logic to handle synthesized types
+05-06-01 make.probe: verify that cc_pic works for hosted cc
+ cc.lynxos.ppc: make -mshared the default
+ package.sh: note $INSTALLROOT/bin/@(cc|ld|ldd) installation
+05-05-25 make.probe: add CC.INCLUDE.LOCAL instead of -I- in CC.DIALECT
+05-05-24 iffe.sh: really fix grouping logic -- with tests this time
+ package.sh: pipe/socket configuration mismatches => use /bin/sh
+05-04-28 TEST.mk: add $(TESTS)
+05-04-19 package.sh: package results test uses rt if possible
+ iffe.sh: fix 'op var - ... - ...' grouping logic
+05-04-15 rt.sh: handle autom4ate style
+05-04-11 regress.sh: fix unit name when command line unit also specified
+ rt.sh: handle all ast package test output formats
+ package.sh: fix make docs for options passed to underlying make
+05-04-08 package.sh: cp -p makerules.mo to $OK to preserve mtime
+ regress.sh: add "TITLE name" to change TEST output title
+05-04-01 rt.sh: add pretty make test + regress.sh wrapper
+05-03-29 package.sh: test -e path => test -f path -o -d path
+05-03-24 make.probe: fix CC.PICBIG probe to prefer -fPIC over -fpic -- doh
+05-03-19 mamake.c: command line name=var also defines name.FORCE=var
+05-03-11 regress.sh: unset LC_ALL when LC_* EXPORT'd
+ package.sh: old make.out saved in circular make.out.[1-9]
+ mamake.c: sync with nmake :W=O:
+05-03-01 package.sh: fix flat hierarchy initialization
+ package.sh: admin action now properly resets sibling remote logs
+ package.mk: relax unknown/unwritten package messages to warnings
+ package.sh: handle space in command line name=value
+ make.probe: add mvs -Wc,dll,exportall,longname,rent to CC.DLL probe
+05-02-24 package.sh: hosttype *.powerpc => *.ppc
+ cc.lynxos.ppc,ldd.lynxos.ppc: add
+05-02-22 mamake.c: fix { -G --debug-symbols -S --strip-symbols } MAMAKEFLAGS bug
+05-02-20 probe.win32: handle /platformsdk mount
+05-02-19 package.sh,package.mk: add write tst for tgz in tst subdir
+05-02-18 package.sh: accept cc -dumpmachine with 0 or 1 -
+05-02-14 package.sh: handle mutiple architectures per host in admin.db
+ Makefile,package.sh: honor $INSTALLROOT/bin/.paths overrides
+ package.sh: normalize trailing [-_]bits in host type
+ iffe.sh: some ksh-compatible shells don't do *(pattern)
+05-02-11 iffe.sh: back out 05-01-11 child process stdin hijack
+ cc.lynxos.i386: -dynamic instead of -static default
+05-02-10 package.sh: cyg usr/doc => usr/share/doc
+05-02-08 package.sh: drop -m with pax -- delta bug fixed 2005-02-08
+ iffe.sh: work around old bash 0<... redirection bug
+05-02-06 package.mk: source.tgz: update generated files only when they change
+05-02-02 *.sh,*probe: IFS may be unset and { ash bsh } don't on startup -- wow
+05-01-11 package.sh: update setup docs to include authorize+password
+ package.mk: fix .source.cyg final directory edit
+ package.mk: notice=1 for conspicuous empty NOTICE file
+ WWW.mk: fix *-index.html installation
+ filter.sh: retain input file suffix in tmp copy
+ mamexec.c: fix non-contiguous "exec" bug that skipped lines
+ iffe.sh: fix candidate lib test to try grouping subsequent libs
+ iffe.sh: fix child process stdin hijack that skipped input lines
+ iffe.sh: --shell=osh to force read -r compatibility command
+ iffe.sh: chop iffe input leading space before # for KnR compatibility
+05-01-05 package.sh: add ${TAR} ${TARFLAGS} and tar B flag for pipes
+ mamake.c: fix makefile scan to ignore lib*.[hH]
+ iffe.sh: immunize function/symbol tests from aggressive -O
+04-12-28 WWW.mk: add :WWWPAGE: faq.*.mm index generator
+04-12-21 ratz.c: make sure tmp dir is writable -- doh
+04-12-08 iffe.sh: fix dat test for aggressive -O
+04-12-01 iffe.sh: add `include file' to pull in #define's for `exp'
+04-11-11 package.sh: default MAKESKIP is "*[-.]*"
+04-10-22 ratz.c: change docs to note zlib license
+ mamake.c: handle --debug-symbols and --strip-symbols
+ package.sh: make (debug|strip)=1 => --(debug|strip)-symbols
+ package.mk: add :LICENSE: => package.license.class
+ mamake.c: fix recursive order logic
+04-10-18 package.mk: add :LICENSE:, :OMIT: to omit package subdirs
+04-10-11 package.sh: add 'authorize name' and 'password password'
+04-10-01 iffe.sh: double check $static link with ! $static
+ Makefile: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+ make.probe: add CC.DIALECT EXPORT={ALL,REF,EXT,DLL}
+ package.sh: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+04-09-21 package.mk: $(init)$(name) is now an implicit prereq
+04-09-09 package.sh: copy makerules.mo to $INSTALLROOT/bin/ok
+04-09-01 package.mk,package.sh: rename *.txt => *.README
+ package.mk: add the runtime package type (no *.[ah])
+ iffe.sh: fix key test reports
+04-08-26 Makefile: { add m2.c m3.c } -lm tests for { frexp[l] ldexp[l] }
+04-08-11 package.mk: handle HOSTTYPE for solaris > 9
+ package.sh: add `checkaout proto' for { make view }
+ package.sh: check for { md5sum md5 }
+ iffe.sh: add {if|elif|else|endif} test ...
+ iffe.sh: add 'exp - expression' and '( expression )'
+ iffe.sh: add 'name = test ...' user defined macros
+ iffe.sh: add '! test ...' negation
+ TEST.mk: add implied { .c .sh } generated prereq
+ cc.darwin.ppc: handle 10.3 -dylib mess
+04-08-01 package.mk: let include handle nested requirements -- duh
+04-07-31 package.sh: attempt a second ping before admin assumes host down
+04-07-26 package.sh: fix hp.ia64 HOSTTYPE
+04-07-23 probe.win32: generalize #include dir order search
+04-07-17 regress.sh: add INPUT -x for chmod +x
+04-07-01 regress.sh: TMP => TWD
+04-06-29 regress.sh: put COMMAND in $TWD too
+04-06-21 regress.sh: mkdir -p INPUT and OUTPUT intermediate dirs
+ TEST.mk: add :TEST: -- to disable .c .sh search
+04-06-18 TEST.mk: add .SCAN.tst
+04-06-17 regress.sh: TEST returns true if active, false otherwise
+ regress.sh: add CD to change test pwd from $TWD
+04-06-16 regress.sh: add TWD for ./unit.tmp override
+ regress.sh: DO now flushes previous test
+ regress.sh: INPUT and OUTPUT handle -f for printf instead of print
+04-06-11 package.sh: make sure $INSTALLROOT/bin is in front of $PATH
+ package.sh: skip nmake if older than 2000-10-31
+04-05-20 package.sh: fix arg vs. package parse with - or '' to disambuguate
+04-05-11 package.sh: package verbose update lists closure for package setup
+ package.sh: add src/lib/libardir to nmake proto bootstrap
+ regress.sh: probe for rm -u vs. chmod -R u+rwx
+04-05-01 package.sh: $CC must be C, not C++; allow release command on $PATH
+04-04-15 make.probe: check probe_libdir false positives
+ package.sh: add lib/package/*.lic src package subdirs
+ package.mk: add mamfile=0 to inhibit Mamfile generation
+ iffe.sh: config name_DECLARED => HAVE_name_DECL
+ iffe.sh: fix mac to handle default value
+04-04-11 iffe.sh: normalize sed [\\\\/] quoting
+04-04-04 package.mk: only checksum generated tarballs
+ mamprobe.sh: add STDCHMOD
+04-04-01 C+probe: set export LANG=C for uniform error messages
+ make.probe: another CC.STDLIB tweak
+ package.sh: fix regress core dump pattern, expand [a-z] match ranges
+04-03-31 Makefile: add intl :MAPLIB: test
+ make.probe: fix CC.STDLIB search; drop CC.* path duplicates
+04-03-28 iffe.sh: drop unused exec $stdin<&0 dup
+04-03-25 Makefile: add iconv :MAPLIB:
+ package.sh: use ${PING:-ping -c 1 -w 4}, allowing admin.db override
+04-03-24 package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: update base change on md5 sum instead of size
+ iffe.sh: adjust case label \ and keyword quoting for ancient /bin/sh
+04-03-22 probe.win32: ncc => nld
+04-03-19 CONVERT.mk: change the instructions and old source dir default
+ package.mk: fix recurse=list check
+ package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: fix update base/delta/sync existence check
+04-03-18 iffe.sh: -d2 does not remove core dumps on exit
+04-03-17 package.sh: fix make recurse arg/action order
+04-02-29 package.sh: add regress action to compare current and previous tests
+ package.sh: fix sgi.mips[23] HOSTTYPE test for old irix cc
+ package.sh: add `export variable ...'
+ package.sh: admin action now handles host name with non-id chars
+ package.sh: non-numeric M T W in admin.db disables that action
+ package.sh: fix admin write binary local vs. shared clash
+ cc.hp.pa: add _AST_CC_hp_pa_DEFAULT=+DAportable
+ cc.hp.pa64: sync with cc.hp.pa
+ cc.ibm.risc: -bnolibpath => -blibpath:/usr/lib:/lib
+ probe.win32: sync with make.probe
+ make.probe: fix last chance dynamic test
+ make.probe: add hp.pa CC.EXPORT.DYNAMIC -Wl,-E
+ make.probe: add ibm.risc CC.EXPORT.DYNAMIC -bexpall
+ make.probe: move probe_dll_def to the end of probe_dll
+ package.mk: capture subcomponent mamfile recursion
+04-02-24 make.probe: strip "..." from cc/ld traces
+ iffe.sh: add ``set [no]define'' to disable macro #define/#undef
+04-02-23 make.probe: rework CC.LD search
+04-02-14 make.probe: add CC.EXPORT.DYNAMIC for main dynamic sym export
+ make.probe: resurrect CC.PIC with separate semantics from CC.DLL
+ make.probe: add CC.SHARED.LD for CC.SHARED linker
+ C+probe: clear DISPLAY to stifle interactive windows
+04-02-11 iffe.sh: handle ``siz void*'', add cross{ ... }end
+ make.probe: add { CC.AR CC.SIZE }, fix cross command search
+ cc.darwin.ppc: change $cc => $CC for old ksh + libast conf bug
+04-02-09 make.probe: drop -nostartfiles from CC.SHARED for C++
+04-02-04 package.sh: fix cross compilation bug that mixed binary formats
+04-02-02 package.sh: package admin now ditto's bin/package too
+04-01-30 cc.sgi.mips3: drop warning 3421
+04-01-11 regress.sh: output label#count for tests in loops
+04-01-05 regress.sh: fix bug that ignored the first SAME
+04-01-04 crossexec.sh: fix typo that did not recognize rcp
+03-12-19 mamake.c: add `foolib:foo:libfoo' to recurse()
+03-10-11 regress.sh: add EXPORT, export COLUMNS=80 for message consistency
+03-09-23 ratz.c: fix tar header number parse bug that skipped to next number
+ regress.sh: rm cleanup now handles files matching -*
+03-09-11 iffe.sh: add unnamed { ... } blocks
+ regress.sh: add COPY from to, like MOVE but comprison still done
+ regress.sh: rm -rfu to handle test dirs w/o u+rwx
+03-08-14 Makfile: add hello.c to the manifest
+03-08-11 package.sh: fix `html binary' generation
+03-06-21 package.sh: fix INITROOT initialization bug
+ package.sh: make sure admin logs exists before tail'ing
+03-06-11 probe.win32: fix $(BINDIR) typo that expanded in sh instead of make
+ cc.mvs.390: return code 4 yields exit code 3 but its *really* ok
+ package.sh: fix onpath function global var conflict
+ make.probe: add CC.DIALECT { GNU -dD }
+ package.mk: add Mamfile to lcl manifest
+03-06-10 package.sh: fix setup action typo that only checked the INIT package
+ package.sh: *.s390x => *.s390-64
+03-06-09 package.mk: add cyg :POSTINSTALL:
+03-06-08 make.probe: fix CC.STDLIB logic
+ hurl.sh: add User-Agent identification
+ package.sh: tweak source and binary installation instructions
+ cc.hp.pa,ld.hp.pa: +-Wl,+cdp,${INSTALLROOT}/lib/: drops abs lib paths
+ ldd.hp.pa: add
+03-06-06 package.sh: fix $INSTALLROOT/bin/ldd check
+ make.probe: add CC.STDLIB verification
+03-06-04 make.probe: add +forceread +noforceread
+03-05-11 hurl.sh: handle http://host:port/path
+03-05-06 package.sh: fix setup action PACKAGEROOT and INIT logic
+03-05-05 package.mk: fix cygwin tarball names
+03-04-30 package.sh: move (cc|ld|ldd).$HOSTTYPE updates from Makefile
+03-04-27 make.probe: fix mvs CC.PREFIX.SHARED "lib" => ""
+ make.probe: add CC.DLL.DIR = $(BINDIR) or $(LIBDIR)
+ make.probe: add { CC.LD.LAZY CC.LD.NOLAZY CC.LD.RECORD CC.LD.NORECORD }
+ probe.win32: sync with latest CC.*
+03-04-25 mamprobe.sh: add args to `. $makeprobe' for ancient sh
+03-04-23 package.mk: fix dup "covered by" licenses
+03-04-22 probe.win32: CC.DIALECT += "LIBPP -I-" for all cc's
+ package.sh: fix admin write binary tarball snarf
+03-04-21 package.mk: package covered *.@(pkg|lic) too
+03-04-15 package.mk: don't generate incremental archives for lcl
+ package.mk: add incremental=[source:1 binary:0] archive control
+ package.sh: generate $INSTALLROOT/bin/cc wrapper for CC != cc
+ package.sh: admin must ditto lib/package/*.@(pkg|lic) too
+ mamake.c: ignore time of ignore prereqs
+ mamake.c: -D2 lists propagated times
+03-04-11 package.mk: tidy up cyg tarballs
+ package.sh: fix old shell clash between get() and $get
+03-04-05 package.mk: restore *.inx generation somehow lost during cyg additions
+ package.sh: add pthread_num_processors_np() last resort for cpu count
+ package.sh: use `make believe' to accept mamake generated files
+ package.sh: handle `make [make-flags] [target ...]'
+ mamake.c: ignore -e
+03-03-21 package.mk: fix cyg old make typo
+ package.sh: switch to `package setup' instructions
+03-03-19 package.sh: add registry checks for `host cpu'
+ package.sh: `results failed' now lists core dump messages
+03-03-17 package.sh: on cygwin verify 'ntsec binmode' in $CYGWIN or die
+ Makefile: install gcc wrapper if no cc
+ package.mk: add :DETAILS: { :README: :EXPORT: :INSTALL: :TEST: } ops
+03-03-12 package.mk: add :DETAILS: for style-specific details
+03-03-11 package.sh: add beta setup/update support
+ TEST.mk: add (TESTCC) prereq for .sh tests
+03-03-07 hurl.sh: add
+03-03-06 iffe.sh: fix lib win32 test cygwin vs native incompatibility
+ iffe.sh: change internal stdio.h guard to handle C++ inline vs. macro
+03-03-03 package.sh: check for curl or wget for update
+ package.sh: add setup action == update read make
+ package.sh: fix packageroot() typo that showed up in non ~user shells
+ mamake.c: treat name+=value args like name=value
+ mamake.c: add ${var?*|value?match?no-match?}
+ mamake.c: fix archive vs. dynamic bind logic
+03-02-28 package.sh: add the "cyg" (cygwin) package type
+ package.mk: add "cyg" stubs, :CATEGORY: for category name(s)
+03-02-25 mamake.c: add -D4 system(3) debug trace
+03-02-24 package.mk: change --mismatch to --corrupt=accept
+03-02-14 ratz.c: add _WIN32 setmode([01],O_BINARY) and fopen "rb"/"wb"
+03-02-12 Makefile: handle getconf LIBPATH with host pattern
+03-01-31 package.mk: fix .lic search
+03-01-30 package.sh: handle { INIT ksh nmake } already installed elsewhere
+ package.sh: admin handles command outside of $PACKAGEROOT/bin
+ Makefile: install $(INSTALLROOT)/lib/make/package.mk
+03-01-28 package.sh: admin remote commands on one line to please syslog
+03-01-23 probe.win32: borland and mingw32 tweaks
+03-01-22 package.sh: fix $CC test to ignore set -x trace -- duh
+03-01-16 ditto.sh: tw --chop on by default
+03-01-14 package.sh: use /bin/cp to copy previous binaries to bin/ok/
+ package.sh: admin now initiates remote exec and copy from local host
+03-01-12 package.sh: handle admin "xxx:" default root
+03-01-03 probe.win32: add /usr/include/borland path truncation workaround
+02-12-10 iffe.sh: add <&$nullin >&$nullout to checkread() $cc
+02-12-06 probe.win32: fix inlcude => include typo, add lcc lib
+ probe.win32: CC.MAKE.OPTIONS = nativepp=0
+02-12-04 mamake.c: fix ${foo-bar} to expand foo if defined
+02-11-28 probe.win32: add C++ and -I- CC.DIALECT checks
+02-11-26 package.sh: package release now checks for second level files
+02-11-22 package.sh: update action now uses HTTP/1.0
+02-11-21 probe.win32: update the vc include dir test
+02-11-20 make.probe: fix CC.LD.ORIGIN typo that expanded make var
+02-11-13 packahe.mk: fix list.install => list.installed typo
+02-11-12 make.probe: add CC.LD.ORIGIN for a.out origin dir relative dll search
+ make.probe: add CC.LD.STRIP for link time a.out strip
+ package.sh: fix package_use vs. PACKAGE_USE check
+02-10-24 WWW.mk: fix bug that required a :WWWBIN: assertion to post
+02-10-23 mamake.c: fix unuinitialized time in make()
+ ratz.c: fix meter buffer overflow
+02-10-20 package.sh: fix lib/probe/C/make/probe update test
+02-10-18 probe.win32: update for mingw
+ make.probe: add bash workaround to SHELLMAGIC test
+ package.sh: work around yet another cygwin hassle
+02-10-17 iffe.sh: short circuit id check for *[-+/\\]*
+02-10-08 regress.sh: unset FIGNORE to avoid rm . errors
+ package.sh: unset FIGNORE to avoid rm . errors
+ package.sh: $CC must at least compile and executable hello world
+02-10-04 package.sh: $INSTALLROOT/lib/package/tgz=>$PACKAGEROOT/lib/package/tgz
+ package.mk: $(ED) => $(STDED), $(EDFLAGS) => $(STDEDFLAGS)
+ iffe.sh: add identifier checks for tests that (implicitly) require them
+ iffe.sh: disambiguate a few --config macros
+02-10-02 iffe.sh: fix shell=bsh `hdr a/b'
+02-09-30 package.sh: handle chmod of -* files
+ package.sh: verify that $SHELL is Bourne compatible
+ package.sh: tighten PACKAGE_USE logic PATH,LIBPATH,etc. validation
+ iffe.sh: fix bug that didn't define mac variable on success
+02-09-22 package.sh: handle admin_action=ditto
+ iffe.sh: --config sizeof(foo) macro is SIZEOF_foo
+ iffe.sh: fix long.long test so it doesn't defeat uwin "typ long.long"
+ mamprobe.sh: convert $("foo") nmake string constants
+02-09-21 mamprobe.sh: "-" info-path writes probe info to stdout
+02-09-11 make.probe: move from nmake src to be part of mamprobe.sh
+ mamprobe: generate from mamprobe.beg C.probe make.probe mamprobe.end
+ mamake.c: pass cc absolute path to mamprobe
+ package.sh: generate mamprobe -- yuk (at least its confined to INIT)
+ iffe.sh: lcl,nxt: drop default sys/ check
+ ditto.sh: tw --logical by default; add --physical
+02-09-10 package.sh: SHELLMAGIC creeps into package too -- duh and fooey
+02-09-09 ditto.sh: test that remote .profile exists before sourcing
+02-09-06 package.sh: don't ditto nfs junk
+ ditto.sh: --show now lists directory ops instead of enumerating all
+02-09-05 ditto.sh: add --remote={rsh|ssh}
+ package.sh: add admin [[{rsh|ssh|-}]:]directory
+02-09-02 iffe.sh: change 'print -r --' to 'print -r -' for ksh86 compatibility
+02-09-01 cc.unix.mc68k: add for ancient 3b1
+02-08-22 package.sh: fix component() to test for components -- duh
+ Makefile: add LICENSE:.DONTCARE to workaround mam
+02-08-11 iffe.sh: provide defaults for LD_* additions
+02-08-07 ratz.c: change -m to use * instead of non-portable inverse video
+02-07-17 mamprobe.sh: close tmp file in trap before rm for cygwin
+ package.sh: fix "type" to handle i1586 (P4)
+ package.sh: add the view action
+02-06-28 package.sh: handle multiple packages for release action
+02-06-27 package.sh: catch sol*.sparc=>sol*.sun4 when CC=gcc
+02-06-14 package.sh: fix admin_action to not include qualifiers
+ package.sh: fix help/html doc typo
+02-06-11 package.sh: fix ditto update doc to `PACKAGEROOT field matching *:*'
+02-06-07 WWW.mk: change substitute $("\n") to \n
+02-06-06 package.sh: clarify output streams for help/html
+02-05-22 mamake.c: fix executable file check to use (S_IXUSR|S_IXGRP|S_IXOTH)
+02-04-04 package.sh: fix update to differentiate *.sun4 and sun4
+02-03-27 package.sh: yacc/bison warning only if both missing
+02-03-24 mamake.c: all shell actions wrapped with -c to avoid #! problems
+02-03-23 package.sh: recover $PACKAGEROOT/bin/package if not in INIT package
+ package.sh: precheck $CC, not `cc'
+ package.sh: fix install to use pax -ps to preserve set-uid/gid
+ package.sh: fix install to use list.installed for existing files only
+02-03-17 package.sh: fix PAX initialization that was sometimes omitted for read
+ package.sh: fix update delta sync fetch
+02-02-14 iffe.sh: fix macro{ }end docs to include "
+ iffe.sh: add dfn to extract #define from headers
+ iffe.sh: handle nxt #include ok but no line sync
+ iffe.sh: drop local header clash logic
+ iffe.sh: add -X, --exclude=dir to exclude -I dirs
+ iffe.sh: lcl,nxt now generate <...> headers instead of "..."
+ package.sh: admin.db root dir matching -* disables host
+ package.mk: fix package.src.pat typo -- too many )
+ package.mk: add { :COVERS: :DESCRIPTION: :REQUIRES: }
+ package.sh: handle { :COVERS: :DESCRIPTION: :REQUIRES: }
+ Makefile: move proto.c generation to the proto component dir
+02-02-02 execrate.sh: add for .exe challenged win32 systems/commands
+ mamprobe.sh: add STD* commands/flags
+ mamake.c: update mamprobe info when older than mamprobe executable
+ package.sh: move ed/ex workaround to mamprobe.sh
+ package.sh: fix `host type' bug that incorrectly assumed sun4 for sol
+ package.sh: add execrate(1) hooks for challenged systems
+ package.sh: add check for { cc ar nm yacc/bison } before make
+ ratz.c: fix "rb" vs. "r" macro tests
+ iffe.sh: add nxt, similar to lcl but defines _nxt_foo for #include
+ iffe.sh,package.sh: remove vaibale from sccs,cvs ident strings -- duh
+02-01-24 C+probe: check CC.DYNAMIC to handle cc that accept but ignore -B*
+ iffe.sh: handle 'mem struct.a.b'
+02-01-22 iffe.sh: cache (internal) `foo vs. struct foo' test results
+ package.sh: uts.370 => uts.390
+02-01-18 package.sh: fix uts hosttype
+02-01-17 package.sh: add 'results failed ...' to list failures only
+ package.sh: change ARCH internal var to all_types to avoid env conflict
+ iffe.sh: fix hdr/lib precheck that missed some -- ouch
+ iffe.sh: fix noexecute test that forgot to check compile first!
+02-01-15 ratz.c: fix path[] type typo
+02-01-01 package.mk: tighten license search
+02-01-08 package.sh: `pwd` => ${PWD:-`pwd`}
+ package.mk: expand license file pattern match
+02-01-04 iffe.sh: fix `exp name "value"' bug that duped "value"
+ iffe.sh: fix initial <sys/types.h> check to honor --config
+01-12-25 iffe.sh: fix bug where -o file restored old file
+01-12-23 package.mk: uniq the closure lists
+01-12-07 ratz.c: fix --meter to retain paths containing " -- "
+01-11-30 ratz.c: use sear_system() to execute; should work on all windows
+01-11-28 ratz.c: fix sear_rm_r() to check SetCurrentDirectory() status
+01-11-26 ditto.sh: drop n+=v for ksh compatibility
+01-11-21 ditto.sh: add rsync script replacement [hey, it works!]
+ package.sh: add [ditto]:directory notation to admin.db
+01-10-31 package.sh: handle *.sum paths with embedded space
+ package.sh: change executable() to onpath()
+ package.sh: executable([!] foo) replaces test [!] -x foo (.exe hack)
+ package.sh: add os2 fix to `host type'
+ mamake.c: add .exe hack
+ iffe.sh: fix intrinsic function lib test
+ mamprobe.sh: update pic probe to match make.probe for linux.ia64
+01-10-30 package.sh: make action skeleton view now checks subdirs
+01-10-20 package.sh: don't recurse into leaf dirs matching $MAKESKIP
+ package.mk: tarball package.notice replaces `license accepted' prompt
+ package.sh: eliminate `license accepted' prompt
+ package.sh: add update to download latest from a url
+ package.sh: use builtin arithmetic when we know its ksh
+ iffe.sh: unkown -> unknown
+01-10-18 package.sh: convert to YYYY-MM-DD delta releases instead of NNNN
+ package.mk: convert to YYYY-MM-DD delta releases instead of NNNN
+ ratz.c: fix -m for paths containing \f\n\r\v
+01-10-16 ratz.c: _SEA_* => SEAR_*
+ ratz.c: preserve stdin for sear_exec()
+ ratz.c: add recursive sear_rm_r() to sear_exec() tmp dir cleanup
+01-10-10 mamprobe.sh: add mam_cc_SHELLMAGIC
+ package.sh: add nfs wakeup call to admin to avoid stale file handles
+01-10-04 cc.darwin.ppc: -flat_namespace is not longer the default (huh)
+01-10-01 package make: prepend $INSTALLROOT/bin/ok to PATH
+ package read: save cpy of bin/package when reading the INIT package
+ mamprobe.sh: allow cc path with optional arguments
+01-09-24 Makefile,package.sh: add $INSTALLROOT/bin/.paths initialization
+01-09-19 package.mk: add recurse to list.package.*
+ package.sh: bootstrap build nmake with _BLD_STATIC for _WIN32
+01-09-11 ratz.c: add _SEA_SKIP & _SEA_COMMAND for self extracting archives
+01-09-07 package.mk: fix output capture to not generate files names with spaces
+01-09-07 package.mk: fix delta release number search
+01-08-11 package.mk: handle single gz executable packages (e.g., for ksh)
+ package.sh: fix package install to require nmake only if no *.sum
+ iffe.sh: drop ancient menu and prompt actions; check ./hdr.h clash
+01-07-17 package: fix use cross compile test to generate files in /tmp
+01-06-27 ratz: handle hard and soft links if possible
+01-06-07 Makefile: fix :MAPLIB: for sco
+01-05-31 crossexec.sh: add
+ iffe.sh: add -x crosstype to run crossexec
+ iffe.sh: exp test now handles pass{}end fail{}end yes{}end no{}end
+ package.sh: add package host canon external-host-type-name
+ package.sh: fix `use USER' lookup for shells that support ~USER
+ cc.*: add -dumpmachine to dump target HOSTTYPE
+01-05-18 iffe.sh: drop $HOME/tmp/t.sh debug trace -- oops
+01-05-01 mamake.c: scan() now handles :PACKAGE: foo:command
+01-04-26 *.sh: expand [a-z][A-Z][0-9] for non-contiguous character codes
+ iffe.sh: fix run *.sh for shells that don't $* across . command
+ cc.mvs.390: recode for /bin/sh
+01-04-25 package.mk: include non cc-g variants by default
+ package.sh: *[._]* => *?[_.]* for mvs.390 /bin/sh
+01-04-24 TEST.mk: no tests for VARIANT=="DLL"
+01-04-22 package.mk,package.sh: tarball text members are ascii encoded
+01-04-18 package.mk: allow package name to be the same as one of its components
+ cc.mvs.390: handle .C .cpp .cxx
+ cc.mvs.390: compensate for -o that does not overwrite
+01-04-01 regress: fix SAME that just skipped it -- we should regress regress!
+ iffe: fix bug that didn't emit _hdr_foo for internal hdr tests
+ iffe: fix lcl bug for cc -E that doesn't emit line syncs
+ ratz: add ascii=>ebcdic conversion for text archive members
+ mamake: fix buffer overlap bug that clobbered the probe file path
+01-03-17 iffe: handle : separator as first arg
+01-03-15 mamake.c,ratz.c,release.c: add <stdlib.h> and <string.h>
+01-02-26 iffe.sh: fix bug that omitted runtime #define for `mac' op
+01-02-22 cc.ibm.risc: handle SF_CLOSE clash in <sfio.h>
+01-02-14 cc.sgi.mips3,cc.sgi.mips4: handle -mips2 -mips3 -mips4 for cross cc
+ C+probe: quote "$cc" when its an argument!
+ mamake: execute actions with $SHELL, ignored signals back to default
+ package.sh: nmake check error output to /dev/null
+ package.sh: fix INIT a.out updates for knr cc
+ package.sh: package list now handles large tgz dirs
+ package.sh: *-ok executables moved to ok/* for *.dll systems
+ iffe.sh: change "exec >&-" to "exec >/dev/null" else linux mkdir fails!
+ mamake: handle `bind -lx [dontcare]'
+01-02-12 ratz.c: fix _PACKAGE_ast includes
+ package.sh: $HOSTTYPE env overrides if $PACKAGEROOT/arch/$HOSTTYPE/
+ package.sh: $CC ^HOSTTYPE=[A-Za-z_0-9.]*$ overrides HOSTTYPE
+ iffe.sh: fix dat code that used previous $tmp.exe
+ iffe.sh: fix dat code for _DLL imports
+01-02-09 iffe.sh: add copy() for shells with the dissappearing here doc bug
+01-02-08 Makefile: guard against null $(CC.HOSTTYPE)
+01-02-06 Makefile: separate out cc,ld,ldd workarounds (so they will be packaged)
+01-02-02 package.sh: fix package use for $INSTALLROOT != */$HOSTTYPE
+ package.sh: create intermediate recursion makefiles when needed
+ package.sh: add $SECONDS to the DEBUG trace prompt
+01-01-01 ratz.c: #ifdef for uwin ncc
+ iffe.sh,package.sh: check PACKAGE_PATH for local installations
+ package.sh: add psrinfo for osf.alpha host cpu
+ package.sh: change pax --meter probe; some hang on /dev/tty
+ package.sh: fix `install flat ARCH'
+ mamake: eliminate loops from scan order
+ C+probe: add probe_verbose -V for aix cc=xlc
+ cc.ibm.risc,ldd.ibm.risc: add
+ package.mk: list refs to top-level licenses only
+ package.mk: add local link table to change log html
+00-12-25 package.sh: `no package archives' is a hard error, duh
+ package.sh: reorder host type logic for lame shells
+ mamake.c: getcwd => getwd for NeXT -- how about posix==default guys
+ iffe.sh: really gross workaround for NeXT -lposix stdout null's
+ iffe.sh: handle cc -E that insists on compiling
+00-12-15 iffe.sh: ancient sh function call blows $*; call only when $# == 0
+ *.sh: `getopts 2>/dev/null` => `(getopts)2>/dev/null` for ancient sh
+ package.sh: fix LD_LIBRARY*_PATH initialization
+ cc.next.m68k: add for _POSIX_SOURCE and linker multiply defined syms
+00-12-12 ratz: add --meter
+ package.sh: a few VPATH fixes
+ Makefile: don't override *.mips* cc if -version not accepted
+00-12-11 package.mk: *.inx now contains name=value
+00-12-07 package.sh: handle PC netscape . => _ pathname mangle
+ WWW.mk: .tar.gz => .tgz
+00-11-27 package.sh: add checklicense() to do license checks at read time
+ package.mk: change component list from preformat to table
+00-10-31 package.mk: *.pkg must assert closure
+ package.mk: add cc- variants to list.package.binary
+ package.sh: omit dups from package list
+ package.sh: invalid arg gives one line Usage
+ package.sh: relax checkaout checks for non-owners
+ package.sh: package use sets NPROC if not already set or [01]
+ proto.c: add $(INSTALLROOT)/include/ast hack
+00-10-26 WWW.mk: add .SOURCE rhs to :WWWPAGE:
+00-10-25 package: fix install
+ package.mk: add list.install
+00-10-22 regress: fix VIEW to skip empty dirs
+00-10-19 package.mk: $(PACKAGEROOT)/bin/nmake => $(PACKAGEROOT)/bin/manmake
+ iffe: validate #define identifiers
+00-10-18 C+probe: mac os10 additions
+ package: add DYLD_LIBRARY_PATH initialization
+ add ldd.$(CC.HOSTTYPE)
+00-10-01 iffe: handle -I* -L* options
+00-09-21 mamake: add libxxx and xxx to makefile ordered prereqs
+00-09-19 C+probe: add probe_longlong
+00-09-11 package: drop manmake and $PACKAGEROOT/bin/nmake
+00-09-08 iffe: verfiy that $cc is a C compiler
+00-06-14 mamprobe: fix win32.* probe
+ mamake: fix bug that used lower view path for generation
+ package: don't clobber $PACKAGEROOT/bin/nmake
+00-06-01 C+probe: fix stdinclude *again*
+ package: fix write delta source to use default pax format
+ package: add disambiguating bias for sgi.mips3 over sgi.mips4
+ package.mk: fix for directory content packages lib ast-locale
+00-05-01 iffe: fix invalid _LIB_ macro identifier
+00-04-11 C+probe: uniq stdinclude and stdlib, fix usrinclude
+00-04-01 regress: fix explicit OUTPUT bug that didn't compare with expected
+00-03-17 package: all archives are .tgz for binary download
+ package: $(PACKAGEROOT)/LICENSES/* in source and binary archives
+ package: implement install and verify actions
+ iffe: add exp, pth file dir ..., fix lib - -lfoo, fix lib - - -la -lb
+ iffe: -L* must affect LD_LIBRARY* hacks for .exe tests -- yuk
+ package.mk: add *.pkg :INDEX:
+00-03-07 package: add admin action
+00-03-06 makefile: install optional make probe override script C+make+probe.lcl
+00-02-14 --- release 1.0 ---
+ ratz: treat "foo/" as a dir, not a regular file
+ package: clarify source and binary installation instructions
+ package: fix so binary packages can install without cc
+ package: "ratz" now a non-archive package (the only one) for bootstrap
+ package: handle VPATH=a:b arg
+ package.mk: "ratz" package adjustments
+ Makefile: use :PACKAGE_INIT: to support binary INIT packages
+ WWW.mk: add :WWWALL:
+ C.probe: fix .so check that let .dll slip through
+ iffe: fix config sh var assignment for HAVE_member_IN_struct
+ iffe: fix config sh var assignment for symbol_DECLARED
+ package: delay PATH export until dll hack exports complete
+ package: don't forget binary package $(INSTALLROOT)/lib(32|64)
+ package: add delta change log for source packages
+00-02-10 mamprobe: add mam_cc_DLLBIG
+ package: fix spelling typos
+ package: add html help output
+ package.mk: beef up source and binary help => html
+00-02-08 package: mkdir man/man[138] in the new arch to cover MAM bug
+00-01-28 package,release: add -rcount to release
+ package: fix linux "host cpu" and "host rating"
+ package: copy *.lic to $PACKAGEBIN for "make" and "write binary"
+ package: fix 'release change log' case match
+00-01-24 package: add copyright action
+ mamprobe: add -D_BLD_DLL to mam_cc_DLL
+00-01-11 package: tsort for package write
+ package: early verification that $CC works
+ package: add non-interactive command arg for use action
+ proto: fix -C intermediate mkdir()
+ mamprobe: unixware.i386 ksh workaround
+ C.probe: move hosttype to C.probe (with unixware.i386 workaround)
+ WWW.mk: fix mm2html option quoting
+ WWW.mk: add .SCAN.mm
+ WWW.mk: don't force static=1; grab dll's instead
+ *.sh: fix getopts test to handle botched implementations like osf.alpha
+ iffe.sh: fix read -r test
+99-12-25 iffe: tweak verbose messages
+ iffe: hand code non-optget getopts parse
+ iffe: fix bash quoting bug again
+ iffe: do test -w . after option parse
+ package: fix PACKAGEROOT search
+99-11-19 --- release 0.2 ---
+99-11-19 first working package & friends
+99-10-31 change from lib0ast to INIT; add MAM and package bootstrap
+ hostinfo: gobbled by package
+99-10-01 iffe: add --config, yes{...}end no{...}end, fix read -r workaround
+99-09-27 iffe: add --all --verbose, --* set options
+99-09-22 regress: -v disables long line truncation
+99-09-11 WWW.mk: WWWDIR and MM2HTMLINFO are now lists searched in $(HOME)
+99-08-11 hostinfo: fix type sgi.mips4
+99-06-24 WWW.mk: add
+99-06-08 hostinfo.sh: ${TMPDIR:-/tmp}
+99-06-07 TEST.mk: add
+99-06-01 iffe: add `siz type' for _siz_type == sizeof(type)
+99-05-11 hostinfo,iffe,regress,use: long options
+99-05-01 C.probe: fix over aggressive stdinclude, e.g., /usr/include/machine
+99-04-01 hostinfo: sgi.mips? -o32 and -n32 checks
+ iffe: check that . is writable
+99-03-17 hostinfo: fix for cc not found
+ dl.c,hello.c,m.c: headers in conditionals to force .DONTCARE
+ C.probe: extra check for include dirs pulled in by <sys/types.h>
+99-03-03 regress: add `UNIT - ...' for extra args
+ Makefile: add (_hosttype_) prereq for cc
+99-01-23 hostinfo: tweak rating, use /proc/cpuinfo if there
+99-01-11 C.probe: shlib before lib, /usr before /
+98-12-25 iffe: work around win32.alpha intrinsic clash with -O
+98-11-11 regress: fix UNIT PATH lookup
+98-11-01 regress: add PROG
+98-10-01 hostinfo: add unixware.*
+ use: export PACKAGE_*
+98-08-11 C.probe: add /usr/include check (for sco CC)
+ hostinfo: handle uwin uname update
+98-05-01 regress: fix bug sometimes didn't list last test
+98-04-01 hostinfo: add cc path arg
+ hostinfo: now works with /bin/sh
+ Makefile: strengthed -lm probe
+98-01-23 Makefile: check for -ldl -lm
+ C.probe: handle gcc -v -E phony include dirs
+ iffe: fix lcl by dropping sort -u -- we need the real first
+ iffe: `mem x' to test if x is a non-opaque struct
+98-01-11 $(INSTALLROOT)/lib32 for sgi.mips3
+ $(INSTALLROOT)/lib64 for sgi.mips4
+ add cc.hp.pa
+98-01-01 cc.sgi.mips*: turn off ld library multiply defined
+97-10-11 regress: add VIEW function for locating data
+97-10-01 Makefile: -ldl test moved to libdll Makefile
+97-08-11 regress: add MOVE
+ regress: add SAME
+ regress: use getopts
+ regress: `EXEC' repeats previous test
+97-07-17 use: tweak PATH and LIBPATH bootstrap order
+ iffe: fix lcl bug that botched pathnames with embedded spaces
+97-06-12 iffe: add npt `needs prototype' test
+97-05-09 hostinfo: mvs.* => mvs.390
+ Makefile: cc.$(_hosttype_) workaround installed here
+ iffe: fix nolink{ ... }end
+ iffe: add [no]static{ ... }end for static link test
+ C.probe: _probe_PATH => _probe_export which must be eval'd
+97-04-01 use: _RLD_ROOT set too
+97-03-17 mm2html: changed inner loop
+ mm2html: handle .if|.ie|.el, .so
+ mm2html: handle different man styles
+ mm2html: differentiate mm/man in some non-obvious cases
+ hostinfo: r5000 is not mips4
+97-02-14 hostinfo: validate type with cc
+96-12-25 C.probe: uwin tweaks
+ iffe: use `...` instead of $(...) for alpha /bin/sh
+ iffe: fix `typ' divide by 0
+ iffe: `lcl' now drops X: prefix
+ iffe: +l* -> -l*
+ iffe: eval around ${...#%...} for bsd /bin/sh
+ use: add sgi.mips LD_LIBRARY<abi>_PATH variants
+ use: add -e to list exports
+ iffe: lcl leaves leading [a-zA-Z]: for dos
+ iffe: fix no{link|output|execute} logic
+ C.probe: don't automatically add /usr/include for non-hosted compilers
+ C.probe: don't automatically place /usr/include last
+ C.probe: check gcc style -v -E for stdinclude usrinclude
+96-11-28 iffe: check BASH_VERSION for IFS botch
+ iffe: typ long.xxx only if sizeof(long xxx) != sizeof(xxx)
+ hostinfo: fix sgi.mips[234] tests
+ hostinfo: fix ncr.i386 tests
+96-10-31 iffe: work around old bsh here doc bug by running separate sh
+96-10-11 iffe: *.iffe and *.iff for iffe src files
+ hostinfo: tighten sgi.mips cpu type check
+96-10-01 C.probe: add probe_libdir to catch alpha /usr/shlib
+96-09-17 iffe: fix typ bug that failed for single id types!
+96-08-31 hostinfo: handle recent sgi hinv cpu changes
+96-07-17 make sure sizeof(long xxx)>sizeof(xxx) for typ long.xxx
+96-05-09 C.probe: drop multiple / in stdinclude
+96-02-29 use: package root must have bin and lib subdir
+ mm2html: add
+ C.probe: probe_members += -whole-archive for gcc
+ iffe: add + fix the blasted `...'...\\...'...`
+96-01-31 use: add pkg dir
+ hostinfo: add tandem
+96-01-01 hostinfo: windows_nt|windows[0-9][0-9] -> win32
+95-11-24 hostinfo: linux-aout.* for non-elf linux
+95-11-11 use: add aix LIBPATH
+95-10-11 hostinfo: no args prints type
+95-08-11 use: add
+95-05-09 save original PATH in _probe_PATH
+ beef up library dir probe
+95-04-01 use c source suffix if it still preserves the dialect
+ add hostinfo
+ add lib/hostinfo/typemap user type map
+ add sol.sun4 cpu count
+ fix C.probe to properly handle C/C++ combined compiler drivers
+ add NeXT to hostinfo
+ bummer: mach has /usr/bin/hostinfo
+95-03-19 fix dialect executable test
+95-03-19 --- release 0.0 ---
diff --git a/src/cmd/INIT/TEST.mk b/src/cmd/INIT/TEST.mk
new file mode 100644
index 0000000..adc4390
--- /dev/null
+++ b/src/cmd/INIT/TEST.mk
@@ -0,0 +1,197 @@
+/*
+ * regression test support
+ *
+ * @(#)TEST.mk (AT&T Research) 2010-05-19
+ *
+ * test management is still in the design phase
+ */
+
+/*
+ * three forms for :TEST:
+ *
+ * :TEST: xxx yyy ...
+ *
+ * $(REGRESS) $(REGRESSFLAGS) xxx.tst
+ * $(REGRESS) $(REGRESSFLAGS) yyy.tst
+ *
+ * :TEST: xxx.tst yyy ...
+ *
+ * $(REGRESS) $(REGRESSFLAGS) xxx.tst yyy ...
+ *
+ * :TEST: xxx.c [ :: test-prereq ... :: ] [ args [ : args ... ] ]
+ *
+ * :TEST: xxx.sh [ :: test-prereq ... :: ] [ args [ : args ... ] ]
+ *
+ * xxx :TEST: prereq ...
+ * [ action ]
+ *
+ * $(*) if no action
+ */
+
+":TEST:" : .MAKE .OPERATOR
+ local B G P S T
+ test : .INSERT .TESTINIT
+ if "$("tests":T=FD)"
+ .SOURCE : tests
+ end
+ P := $(>:O=1)
+ if "$(P:N=*.tst)" && ! "$(@:V)"
+ B := $(P:B)
+ if ! ( T = "$(<:V)" )
+ T := $(B)
+ end
+ test : - test.$(T)
+ eval
+ test.$$(T) : $$(B).tst
+ $$(REGRESS) $$(REGRESSFLAGS) $$(*) $(>:V:O>1)
+ :SAVE: $$(B).tst
+ end
+ elif "$(P:N=*@(.sh|$(.SUFFIX.c:/ /|/G)|$(.SUFFIX.C:/ /|/G)))"
+ B := $(P:B)
+ if ! ( T = "$(<:V)" )
+ T := $(B)
+ end
+ :INSTALLDIR: $(B)
+ $(B) :: $(P) $(*:-l*|*$(CC.SUFFIX.ARCHIVE))
+ if "$(P:N=*.sh)"
+ TESTCC == $(CC)
+ $(B) : (TESTCC)
+ end
+ test : - test.$(T)
+ if "$(@:V)"
+ eval
+ test.$$(T) : $$(B) $(>:V:O>1)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(@:V)
+ end
+ elif "$(>:V:O>1)"
+ local I A V X S R=0
+ for A $(>:V:O>1)
+ if A == "::"
+ let R = !R
+ elif A == ":"
+ let I = I + 1
+ test.$(T).$(I) := $(V:V)
+ V =
+ X := $(X:V)$(S)$$(*) $$(test.$(T).$(I):T=*)
+ S = $("\n")
+ elif A != "-l*|*$(CC.SUFFIX.ARCHIVE)"
+ if R
+ test.$(A) : .VIRTUAL .FORCE
+ test.$(T) : test.$(A)
+ else
+ V += $(A:V)
+ end
+ end
+ end
+ if V
+ let I = I + 1
+ test.$(T).$(I) := $(V:V)
+ X := $(X:V)$(S)$$(*) $$(test.$(T).$(I):T=*)
+ end
+ eval
+ test.$$(T) : $$(B)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(X:V)
+ end
+ else
+ eval
+ test.$$(T) : $$(B)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $$(*)
+ end
+ end
+ elif ! "$(<:V)"
+ G = 1
+ for B $(>)
+ if B == "-|--"
+ let G = !G
+ else
+ if ! G
+ T =
+ elif ! ( T = "$(B:A=.COMMAND)" ) && ! "$(B:A=.TARGET)"
+ for S .c .sh
+ if "$(B:B:S=$(S):T=F)"
+ :INSTALLDIR: $(B)
+ $(B) :: $(B:B:S=$(S))
+ T := $(B)
+ break
+ end
+ end
+ end
+ test : - test.$(B)
+ test.$(B) : $(T) - $(B).tst
+ $(REGRESS) $(REGRESSFLAGS) $(*:N=*.tst) $(*:N!=*.tst)
+ :SAVE: $(B).tst
+ end
+ end
+ else
+ if "$(>:V)" || "$(@:V)"
+ P := $(>)
+ T := $(P:O=1)
+ B := $(T:B)
+ if "$(T)" != "$(B)" && "$(T:G=$(B))"
+ :INSTALLDIR: $(B)
+ $(B) :: $(T) $(P:O>1:N=-*)
+ T := $(B)
+ P := $(B) $(P:O>1:N!=-*)
+ end
+ if "$(<:V)"
+ T := $(<:V)
+ end
+ test : - test.$(T)
+ if "$(@:V)"
+ eval
+ test.$$(T) : $$(P) $(>:V:O>1)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(@:V)
+ end
+ else
+ test.$(T) : $(P)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(*)
+ end
+ else
+ test : - test.$(<)
+ test.$(<) : $(<).tst $(<:A=.COMMAND)
+ $(REGRESS) $(REGRESSFLAGS) $(*)
+ end
+ end
+
+.TESTINIT : .MAKE .VIRTUAL .FORCE .REPEAT
+ if VARIANT == "DLL"
+ error 1 :DLL: tests skipped
+ exit 0
+ end
+ set keepgoing
+ REGRESSFLAGS &= $(TESTS:@/ /|/G:/.*/--test=&/:@Q)
+
+.SCAN.tst : .SCAN
+ $(@.SCAN.sh)
+ I| INCLUDE@ % |
+
+.ATTRIBUTE.%.tst : .SCAN.tst
+
+MKTEST = mktest
+MKTESTFLAGS = --style=regress
+
+/*
+ * test scripts are only regenerated from *.rt when --force
+ * is specified or the .rt file is newer than the script
+ * otherwise the script is accepted if it exists
+ *
+ * this avoids the case where a fresh build with no state
+ * would regenerate the test script and capture current
+ * behavior instead of expected behavior
+ */
+
+%.tst : %.rt
+ if [[ "$(-force)" || "$(>)" -nt "$(^|<)" ]]
+ then $(MKTEST) $(MKTESTFLAGS) $(>) > $(<)
+ fi
+
+test%.sh test%.out : %.rt
+ if [[ "$(-force)" || "$(>)" -nt "$(^|<:O=1)" ]]
+ then $(MKTEST) --style=shell $(>) > $(<:N=*.sh)
+ $(SHELL) $(<:N=*.sh) --accept > $(<:N=*.out)
+ fi
diff --git a/src/cmd/INIT/WWW.mk b/src/cmd/INIT/WWW.mk
new file mode 100644
index 0000000..4542dae
--- /dev/null
+++ b/src/cmd/INIT/WWW.mk
@@ -0,0 +1,450 @@
+/*
+ * post stuff to WWWDIR for web access
+ * index generated from *.mm
+ */
+
+WWWDIR = wwwfiles public_html
+WWWSAVE =
+WWWSTYLE =
+WWWTYPES =
+
+.WWW.semaphore : .SEMAPHORE
+
+.EXPORT : WWWSTYLE WWWTYPES
+
+/*
+ * item :WWW: [style=frame] [save=pattern] file ...
+ *
+ * `item'.mm generates index.html
+ * other files copied to $(WWWDIR)/`item'
+ * sets up www.bin
+ */
+
+":WWW:" : .MAKE .OPERATOR
+ local A B D I J L X E P R M
+ .WWW.LOCAL .WWW.REMOTE : .DO.NOTHING
+ WWWDIR := $(HOME:X=$(WWWDIR):T=F:O=1)
+ B := $(*:N=*.mm::O=1:B)
+ D := $(WWWDIR)/$(B)
+ M := $(WWWDIR)/man/man1
+ R := $(>:N!=*=*)
+ for I $(>:N=*=*)
+ A := WWW$(I:/=.*//:F=%(upper)s)
+ $(A) := $(I:/.*=//)
+ end
+ (html_info) : $$(MM2HTMLINFO) $$(MM2HTMLINIT)
+ if WWWSTYLE == "frame"
+ %.html %-index.html : %.mm (html_info)
+ $(MM2HTML) $(MM2HTMLFLAGS) $(%:N=faq.*:?> $(<:O=1)?-f $(%) -x?) -o WWWTYPES=$(WWWTYPES:@Q:@Q) $(WWWSOURCE.$(%)) $(>)
+ else
+ %.html : %.mm (html_info)
+ $(MM2HTML) $(MM2HTMLFLAGS) -o WWWTYPES=$(WWWTYPES:@Q:@Q) $(>) $(WWWSOURCE.$(%)) > $(<)
+ end
+ %.html : %.1 (html_info)
+ $(MM2HTML) $(MM2HTMLFLAGS) $(>) $(WWWSOURCE.$(%)) > $(<)
+ %-man.html : $(BINDIR)/% (html_info)
+ ignore $(>) --html 2> $(<)
+ .DO.WWW.MAN : .USE
+ if { test '' = '$(*)' || { strings $(*) | egrep -q '\[\+NAME\?|libcmd\.|cmd[0-9][0-9]\.' ;} ;} && [[ "$( $(<:B) '--???html' -- 2>&1 )" == version=[1-9]* ]]
+ then ( $(<:B) '--??html' -- 2>$(<) ) || true
+ fi
+ if 0
+ $(M)/%.html : .DONTCARE $(INSTALLROOT)/bin/%
+ $(@.DO.WWW.MAN)
+ end
+ if "$(<)"
+ D := $(<)
+ elif ! "$(R)"
+ return
+ end
+ .WWW .WWW.BIN : $(D) $(M) -
+ $(D) $(M) :
+ $(SILENT) test -d $(<) || mkdir $(<)
+ if ( J = "$(R:N=*.mm)" )
+ for I $(J:G=%.html)
+ if I == "*-index.html"
+ O := $(D)/index.html
+ else
+ O := $(I:D=$(D):B:S)
+ end
+ .WWW : $(O)
+ $(O) :COPY: $(I)
+ end
+ end
+ .WWW.req : .FUNCTION
+ return $(*$(%:T=SR):N=-l*:T=F:P=B:N!=-l*|/*)
+ A = 0
+ for I $(R:N!=*.mm)
+ if I == "-"
+ let A = ! A
+ elif I == "-l*"
+ L := $(I:/-l//)
+ if J = "$(.DLL.NAME. $(L) $($(L).VERSION):T=F)"
+ X += $(J)
+ end
+ elif A || "$(I:A=.COMMAND|.ARCHIVE)" || "$(I:D:D:N=$(INSTALLROOT))" || "$(I:N=*-www)"
+ X += $(I)
+ if "$(I:A=.COMMAND)"
+ X += $$(.WWW.req $(I))
+ J := $(I:/-www$//)
+ eval
+ .WWW : $(J:D=$(M):B:S=.html)
+ $(J:D=$(M):B:S=.html) : $(I) $(I:B:S=.1:T=F:?$(I:B:S=.1)??)
+ if strings $$(*:O=1) | egrep -q '\[\+NAME\?|libcmd\.|cmd[0-9][0-9]\.'
+ then $$(IGNORE) $$(*:O=1) '--??html' -- 2>&1
+ elif test '' != '$$(*:N=*.1)'
+ then $$(MM2HTML) $$(*:N=*.1)
+ fi > $$(<)
+ end
+ end
+ else
+ if I == "*.html"
+ $(I) : .TERMINAL
+ end
+ .WWW : $(D)/$(I)
+ $(D)/$(I) :COPY: $(I)
+ end
+ end
+ if "$(X:V)"
+ .WWW.EDIT. : .FUNCTION
+ local E I J
+ for I $(.INSTALL.LIST.:C,^$(INSTALLROOT)/,,:N!=lib/lib/*)
+ for J $(%)
+ if "$(I:B:S)" == "$(J:B:S)"
+ E += -s ',^$(J)$,$(I),'
+ end
+ end
+ end
+ return $(E)
+ .WWW.LIST. : .FUNCTION
+ local E I J
+ for I $(.INSTALL.LIST.:C,^$(INSTALLROOT)/,,:N!=lib/lib/*)
+ for J $(%)
+ if "$(I:B:S)" == "$(J:B:S)"
+ E += $(I)
+ end
+ end
+ end
+ return $(E)
+ .WWW .WWW.BIN : $(D)/$(B)-$(CC.HOSTTYPE).tgz
+ $(D)/$(B)-$(CC.HOSTTYPE).tgz : $(X:V)
+ cat > X.$(tmp).X <<!
+ This archive contains $(CC.HOSTTYPE) binaries for
+ $(.WWW.LIST. $(*))
+ Add the bin directory to PATH and the lib directory
+ to LD_LIBRARY_PATH or its equivalent for your system.
+ Use the --?help and --man options for online help,
+ documentation and contact info.
+ !
+ $(PAX) -wvf $(<) -x tar:gzip -s "/X.$(tmp).X/README/" $(.WWW.EDIT. $(*)) -s ',\(.*\)-www$,bin/\1,' -s ',.*/lib/,lib/,' X.$(tmp).X $(*:N!=-l*)
+ $(RM) -f X.$(tmp).X
+ end
+
+/*
+ * item ... :WWWBIN: index.mm file ... host:arch ...
+ *
+ * home page control
+ * `host' of type `arch' for www.bin files
+ */
+
+":WWWBIN:" : .MAKE .OPERATOR
+ local HOST ITEM ARCH BINS DIRS G
+ .WWW.NOMAN. += $(<)
+ for HOST $(>)
+ TYPE := $(HOST:/.*://)
+ HOST := $(HOST:/:.*//)
+ WWWTYPES += $(TYPE)
+ ARCH := $(PWD:D:C,/$(CC.HOSTTYPE)/,/$(TYPE)/)
+ BINS :=
+ DIRS :=
+ for ITEM $(<)
+ if TYPE == "$(CC.HOSTTYPE)"
+ G := $("index.mm":G=%.html:D=$(WWWDIR)/$(ITEM):B:S)
+ .WWW.LOCAL : $(G)
+ eval
+ $(G) : .JOINT $(ARCH)/$(ITEM)/$(ITEM).mm (html_info) .WWW.semaphore .FORCE
+ cd $$(*:D)
+ $$(MAKE) $$(-) $$(=) www
+ end
+ else
+ BINS += $(WWWDIR)/$(ITEM)/$(ITEM)-$(TYPE).tgz
+ DIRS += $(ARCH)/$(ITEM)
+ end
+ end
+ .WWW.REMOTE : $(BINS)
+ ARCH := $(ARCH:C,/src/.*,,)
+ eval
+ $(BINS) :JOINT: .FORCE .WWW.semaphore
+ rsh $(HOST) "
+ eval \"\`bin/package debug use\`\"
+ PATH=\$PATH:$(PATH):/usr/ccs/bin
+ umask 022
+ for dir in $(DIRS)
+ do cd \$dir
+ $(MAKE) $(-) $(=) --errorid=\$dir www.bin
+ done
+ "
+ end
+ end
+
+/*
+ * :WWWPOST: [ host [ dir [ tmp ] ] ]
+ *
+ * post local $(WWWDIR) to host:dir putting archives in host:tmp/www-*.pax
+ * defaults: host=www dir=$(WWWDIR) tmp=tmp
+ */
+
+":WWWPOST:" : .MAKE .OPERATOR
+ local ( host dir tmp ignore ... ) $(>) www $(WWWDIR:B:S) tmp ignore
+ :ALL: delta.pax
+ .WWW.ALL : .WWW.REMOTE - .WWW.LOCAL
+ eval
+ .POST : .VIRTUAL base.pax delta.pax
+ case "$$(>)" in
+ '') ;;
+ *) $$(>:C,.*,rcp & $(host):$(tmp)/$(dir)-&;,)
+ rsh $(host) '
+ umask 022
+ PATH=$HOME/bin:$PATH
+ cd $(dir)
+ pax -rvf $HOME/$(tmp)/$(dir)-delta.pax -z $HOME/$(tmp)/$(dir)-base.pax
+ '
+ ;;
+ esac
+ end
+ base.pax :
+ cd $(WWWDIR)
+ pax -wvf $(<:P=A) .
+ .base.list. : .FUNCTION
+ local X
+ X := $(sh pax -f $(%:N=*.pax):C,\n, ,G:C,^,$$(WWWDIR)/,)
+ $(X) : .DONTCARE
+ return $(X)
+ delta.pax : .WWW.ALL base.pax $$(.base.list. $$(*))
+ cd $(WWWDIR)
+ pax -wvf $(<:P=A) -z $(*:N=*.pax:P=A) .
+
+.WWW.FAQ : .USE
+ {
+ set -o noglob
+ print .xx title=\"$(<:B:/\..*//) FAQ index\"
+ print .MT 4
+ print .TL
+ print
+ print .H 1 \"$(<:B:/\..*//) FAQ index\"
+ print .BL
+ for i in $(*)
+ do exec < $i || exit 1
+ e=0 l=0 x=y
+ while read -r op a1 a2
+ do case $op in
+ .H) case $e in
+ 0) e=1 ;;
+ 1) print .LE ;;
+ esac
+ print .sp
+ print .LI
+ a2=${a2//\"/}
+ a2=${a2%\ [Ff][Aa][Qq]}
+ f=${i%.*}.html
+ f=${f#*/}
+ print .xx link=\"$f' '$a2\"
+ print .sp
+ print .NL
+ ;;
+ .AL|.BL|.NL)
+ case $x in
+ y) x=x ;;
+ *) x=xx$x ;;
+ esac
+ ;;
+ .LE) x=${x%xx}
+ ;;
+ .LI) case $x in
+ x) x=
+ print .LI
+ ;;
+ esac
+ ;;
+ .sp) case $x in
+ '') x=x ;;
+ esac
+ ;;
+ *) case $x in
+ '') print -r -- $op $a1 $a2 ;;
+ esac
+ ;;
+ esac
+ done
+ case $e in
+ 1) print .LE ;;
+ esac
+ done
+ print .LE
+ } > $(<)
+
+/*
+ * [ dir ] :WWWPAGE: [ source ... ] file.mm file
+ *
+ * *.mm generates *.html
+ * faq.*.mm generates faq.mm
+ * other files copied to $(WWWDIR)[/dir]
+ * files after - (toggle) are just asserted on ::
+ */
+
+":WWWPAGE:" : .MAKE .OPERATOR
+ local B D I J O P Q S X G A
+ A = 0
+ D := $(<:O=1)
+ P := $(>:N!=*=*)
+ S := $(>:N=*=*)
+ if X = "$(P:B:S:N=faq.*.mm)"
+ Q := $(D:+$(D).)faq.mm
+ $(Q) : .WWW.FAQ $(X)
+ P += $(Q)
+ end
+ if D
+ B := $(D:B)
+ if D != "/*"
+ D := $(WWWDIR)/$(D)
+ $(D) :INSTALLDIR:
+ .WWW.LOCAL : $(D)
+ end
+ for I $(<:B)
+ .WWW.LOCAL : $(WWWDIR)/man/man1/$(I).html
+ $(WWWDIR)/man/man1/$(I).html : .DONTCARE
+ end
+ for I $(P)
+ if I == "-"
+ let A = !A
+ continue
+ end
+ if A || I == "$(WWWSAVE)"
+ :: $(I)
+ continue
+ end
+ if "$(I:T=FD)"
+ .SOURCE : $(I)
+ if "$(<)"
+ WWWSOURCE.$(<:O=1) += $(I:T=F:P=L=*)
+ end
+ continue
+ end
+ if I == "*.html"
+ $(I) : .TERMINAL
+ O := $(I)
+ X := $(I)
+ elif ( G = "$(I:G=%.html)" )
+ $(G) : .IMPLICIT $(S) $(I)
+ if $(G:O) > 1
+ for J $(G)
+ if J == "*-index.html"
+ if J == "faq.*.*"
+ continue
+ end
+ O := index.html
+ else
+ O := $(J)
+ end
+ .WWW.LOCAL : $(D)/$(O)
+ $(D)/$(O) :INSTALL: $(J)
+ end
+ continue
+ end
+ if X
+ X := $(I)
+ else
+ X := index
+ end
+ I := $(I:B:S=.html)
+ O := $(X:B:S=.html)
+ else
+ O := $(I)
+ end
+ $(D)/$(O) :INSTALL: $(I)
+ .WWW.LOCAL : $(D)/$(O)
+ end
+ else
+ for I $(P)
+ if I == "-"
+ let A = !A
+ continue
+ end
+ if A || I == "$(WWWSAVE)"
+ :: $(I)
+ continue
+ end
+ if "$(I:T=FD)"
+ .SOURCE : $(I)
+ continue
+ end
+ if I == "*.html"
+ $(I) : .TERMINAL
+ O := $(I)
+ elif ( O = "$(I:G=%.html)" )
+ $(O) : $(S) .IMPLICIT $(I)
+ end
+ for J $(O)
+ if J == "*-index.html"
+ X := index.html
+ else
+ X := $(J)
+ end
+ X := $(WWWDIR)/$(X)
+ .WWW.LOCAL : $(X)
+ $(X) :COPY: $(J)
+ end
+ end
+ end
+
+/*
+ * rhs done by default
+ */
+
+":WWWALL:" : .MAKE .OPERATOR
+ .WWW.ALL : $(>)
+
+":WWWMAN:" : .MAKE .OPERATOR
+ .INIT : .WWW.MAN
+ .WWW.MAN. := $(>)
+ .WWW.MAN : .MAKE .FORCE
+ local H I
+ for I $(.WWW.MAN.)
+ .WWW.LOCAL : $(WWWDIR)/man/man1/$(I:B).html
+ $(WWWDIR)/man/man1/$(I:B).html : .DO.WWW.MAN $(I)
+ end
+ for I $(sh builtin:B)
+ .WWW.LOCAL : $(WWWDIR)/man/man1/$(I).html
+ $(WWWDIR)/man/man1/$(I).html : .DO.WWW.MAN -
+ end
+ for I $("$(BINDIR)/*([!-.])":P=G:B)
+ if I != "*_*"
+ H := $(WWWDIR)/man/man1/$(I).html
+ if ! "$(*$(H))" && I != "$(.WWW.NOMAN.:/ /|/G)"
+ .WWW.LOCAL : $(H)
+ end
+ elif "$(PATH:/:/ /G:X=$(I:/.*_//):T=F:O=1)"
+ H := $(WWWDIR)/man/man1/$(I:/.*_//).html
+ .WWW.LOCAL : $(H)
+ $(H) : .DO.WWW.MAN $(BINDIR)/$(I)
+ end
+ end
+
+.WWW.SED. : .FUNCTION
+ local E T
+ E = s/^\(\.xx.link=.*\)%HOSTTYPE%\(.*\)%HOSTTYPE%\(.*\)/
+ for T $(%)
+ E := $(E:V)\$$("\n").LI\$$("\n")\1$(T)\2$(T)\3
+ end
+ return $(E:V)/
+
+/*
+ * mm scan support
+ */
+
+.SCAN.mm : .SCAN
+ O|S|
+ I|.sn %|A.DONTCARE|M$$(%)|
+ I|.so %|A.DONTCARE|M$$(%)|
+
+.ATTRIBUTE.%.mm : .SCAN.mm
diff --git a/src/cmd/INIT/ar.ibm.risc b/src/cmd/INIT/ar.ibm.risc
new file mode 100755
index 0000000..0247643
--- /dev/null
+++ b/src/cmd/INIT/ar.ibm.risc
@@ -0,0 +1,9 @@
+: stupid stupid stupid to require a non-standard option for ar to work : 2009-10-06 :
+
+op=$1
+shift
+case $op in
+-*) ;;
+*) op=-$op ;;
+esac
+/usr/bin/ar -Xany "$op" "$@"
diff --git a/src/cmd/INIT/cc.darwin b/src/cmd/INIT/cc.darwin
new file mode 100755
index 0000000..081bd43
--- /dev/null
+++ b/src/cmd/INIT/cc.darwin
@@ -0,0 +1,73 @@
+: unix wrapper for mac osx cc : 2012-01-20 :
+
+HOSTTYPE=darwin.generic
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+CC=/usr/bin/cc
+op=init
+for arg
+do case $op in
+ init) op=ld
+ set ''
+ ;;
+ esac
+ case $arg in
+ -c) op=cc
+ ;;
+ -E) op=cpp
+ continue
+ ;;
+ -G) op=dll
+ continue
+ ;;
+ -lc) continue
+ ;;
+ -lm) continue
+ ;;
+ -O) continue
+ ;;
+ esac
+ set "$@" "$arg"
+done
+case $# in
+0) ;;
+*) shift ;;
+esac
+case $* in
+-v) $CC "$@"; exit ;;
+esac
+case $op in
+init) echo "cc: arguments expected" >&2
+ exit 1
+ ;;
+cpp) $CC -E "$@"
+ ;;
+cc) $CC -DCLK_TCK=100 "$@"
+ ;;
+dll) # what a compatibility mess -- surely they can get the apis to play nice
+ tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ case `MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup 2>&1` in
+ *undefined*dynamic_lookup*)
+ ld -m -flat_namespace -undefined suppress -dylib -dynamic \
+ -ldylib1.o "$@" -lcc_dynamic -framework System >$tmp 2>&1
+ status=$?
+ ;;
+ *) MACOSX_DEPLOYMENT_TARGET=10.3 $CC -Wl,-flat_namespace -dynamiclib -undefined dynamic_lookup "$@" >$tmp 2>&1
+ status=$?
+ ;;
+ esac
+ egrep -v ' (warning .*multiple definitions|definition) of ' $tmp >&2
+ exit $status
+ ;;
+ld) tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ $CC -Wl,-m -DCLK_TCK=100 "$@" >$tmp 2>&1
+ status=$?
+ egrep -v ' (warning .*multiple definitions of|definition of|as lazy binding|not from earlier dynamic) ' $tmp >&2
+ exit $status
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.darwin.i386 b/src/cmd/INIT/cc.darwin.i386
new file mode 100755
index 0000000..9afde8d
--- /dev/null
+++ b/src/cmd/INIT/cc.darwin.i386
@@ -0,0 +1,73 @@
+: unix wrapper for mac osx cc : 2012-02-29 :
+
+HOSTTYPE=darwin.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+CC='/usr/bin/cc -m32'
+op=init
+for arg
+do case $op in
+ init) op=ld
+ set ''
+ ;;
+ esac
+ case $arg in
+ -c) op=cc
+ ;;
+ -E) op=cpp
+ continue
+ ;;
+ -G) op=dll
+ continue
+ ;;
+ -lc) continue
+ ;;
+ -lm) continue
+ ;;
+ -O) continue
+ ;;
+ esac
+ set "$@" "$arg"
+done
+case $# in
+0) ;;
+*) shift ;;
+esac
+case $* in
+-v) $CC "$@"; exit ;;
+esac
+case $op in
+init) echo "cc: arguments expected" >&2
+ exit 1
+ ;;
+cpp) $CC -E "$@"
+ ;;
+cc) $CC -DCLK_TCK=100 "$@"
+ ;;
+dll) # what a compatibility mess -- surely they can get the apis to play nice
+ tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ case `MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup 2>&1` in
+ *undefined*dynamic_lookup*)
+ ld -m -flat_namespace -undefined suppress -dylib -dynamic \
+ -ldylib1.o "$@" -lcc_dynamic -framework System >$tmp 2>&1
+ status=$?
+ ;;
+ *) MACOSX_DEPLOYMENT_TARGET=10.3 $CC -Wl,-flat_namespace -dynamiclib -undefined dynamic_lookup "$@" >$tmp 2>&1
+ status=$?
+ ;;
+ esac
+ egrep -v ' (warning .*multiple definitions|definition) of ' $tmp >&2
+ exit $status
+ ;;
+ld) tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ $CC -Wl,-m -DCLK_TCK=100 "$@" >$tmp 2>&1
+ status=$?
+ egrep -v ' (warning .*multiple definitions of|definition of|as lazy binding|not from earlier dynamic) ' $tmp >&2
+ exit $status
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.darwin.i386-64 b/src/cmd/INIT/cc.darwin.i386-64
new file mode 100755
index 0000000..9010d96
--- /dev/null
+++ b/src/cmd/INIT/cc.darwin.i386-64
@@ -0,0 +1,73 @@
+: unix wrapper for mac osx cc : 2012-02-29 :
+
+HOSTTYPE=darwin.i386-64
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+CC=/usr/bin/cc
+op=init
+for arg
+do case $op in
+ init) op=ld
+ set ''
+ ;;
+ esac
+ case $arg in
+ -c) op=cc
+ ;;
+ -E) op=cpp
+ continue
+ ;;
+ -G) op=dll
+ continue
+ ;;
+ -lc) continue
+ ;;
+ -lm) continue
+ ;;
+ -O) continue
+ ;;
+ esac
+ set "$@" "$arg"
+done
+case $# in
+0) ;;
+*) shift ;;
+esac
+case $* in
+-v) $CC "$@"; exit ;;
+esac
+case $op in
+init) echo "cc: arguments expected" >&2
+ exit 1
+ ;;
+cpp) $CC -E "$@"
+ ;;
+cc) $CC -DCLK_TCK=100 "$@"
+ ;;
+dll) # what a compatibility mess -- surely they can get the apis to play nice
+ tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ case `MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup 2>&1` in
+ *undefined*dynamic_lookup*)
+ ld -m -flat_namespace -undefined suppress -dylib -dynamic \
+ -ldylib1.o "$@" -lcc_dynamic -framework System >$tmp 2>&1
+ status=$?
+ ;;
+ *) MACOSX_DEPLOYMENT_TARGET=10.3 $CC -Wl,-flat_namespace -dynamiclib -undefined dynamic_lookup "$@" >$tmp 2>&1
+ status=$?
+ ;;
+ esac
+ egrep -v ' (warning .*multiple definitions|definition) of ' $tmp >&2
+ exit $status
+ ;;
+ld) tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ $CC -Wl,-m -DCLK_TCK=100 "$@" >$tmp 2>&1
+ status=$?
+ egrep -v ' (warning .*multiple definitions of|definition of|as lazy binding|not from earlier dynamic) ' $tmp >&2
+ exit $status
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.hp.ia64 b/src/cmd/INIT/cc.hp.ia64
new file mode 100755
index 0000000..204bd0e
--- /dev/null
+++ b/src/cmd/INIT/cc.hp.ia64
@@ -0,0 +1,13 @@
+: hp.ia64 cc wrapper for reasonable ansi C defaults : 2011-01-25 :
+
+[ /usr/bin/cc -ef /usr/ccs/bin/cc ] || exit 1
+
+: bundled cc -- really, in the face of gcc you ship a sub-par /usr/bin/cc? :
+
+HOSTTYPE=hp.ia64
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/usr/bin/cc -D_HPUX_SOURCE -D_INCLUDE__STDC_A1_SOURCE -D_INCLUDE_XOPEN_SOURCE_500 "$@"
diff --git a/src/cmd/INIT/cc.hp.pa b/src/cmd/INIT/cc.hp.pa
new file mode 100755
index 0000000..cd5f576
--- /dev/null
+++ b/src/cmd/INIT/cc.hp.pa
@@ -0,0 +1,13 @@
+: hp.pa cc wrapper for reasonable ansi C defaults : 2004-02-29 :
+
+HOSTTYPE=hp.pa
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+_AST_CC_hp_pa_DEFAULT=${_AST_CC_hp_pa_DEFAULT-"+DAportable"}
+
+/opt/ansic/bin/cc -Ae +e -Wl,+s $_AST_CC_hp_pa_DEFAULT \
+ ${INSTALLROOT:+-Wl,+cdp,${INSTALLROOT}/lib/:} \
+ -Wl,+vnocompatwarnings "$@"
diff --git a/src/cmd/INIT/cc.hp.pa64 b/src/cmd/INIT/cc.hp.pa64
new file mode 100755
index 0000000..49f2395
--- /dev/null
+++ b/src/cmd/INIT/cc.hp.pa64
@@ -0,0 +1,11 @@
+: hp.pa64 cc wrapper for reasonable ansi C defaults : 2001-02-11 :
+
+HOSTTYPE=hp.pa64
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/opt/ansic/bin/cc +D2.0W -Ae +e -Wl,+s \
+ ${INSTALLROOT:+-Wl,+cdp,${INSTALLROOT}/lib/:} \
+ -Wl,+vnocompatwarnings "$@"
diff --git a/src/cmd/INIT/cc.ibm.risc b/src/cmd/INIT/cc.ibm.risc
new file mode 100755
index 0000000..17a8f70
--- /dev/null
+++ b/src/cmd/INIT/cc.ibm.risc
@@ -0,0 +1,63 @@
+: cc wrapper for aix risc xlc : 2009-09-28 :
+
+hosttype=ibm.risc
+
+case $HOSTTYPE in
+$hosttype-64)
+ case " $* " in
+ *" -q64 "*) ;;
+ *) set -- -q64 "$@" ;;
+ esac
+ ;;
+*) case " $* " in
+ *" -q64 "*) HOSTTYPE=$hosttype-64 ;;
+ *) HOSTTYPE=$hosttype ;;
+ esac
+ ;;
+esac
+
+case " $* " in
+*" -dumpmachine "*)
+ echo $HOSTTYPE
+ exit
+ ;;
+esac
+
+bin=/usr/vac/bin
+cc=$bin/xlc
+
+ccflags="-brtl -qhalt=e -qsuppress=1506-224:1506-507"
+case " $@ " in
+*" -G "*)
+ ccflags="$ccflags -berok"
+ ;;
+esac
+if test -x $bin/c99
+then # the xlc optimizer vintage that supports c99 is flawed and causes the ast build to fail #
+ case " $* " in
+ *" -O "*)
+ set '' "$@" ''
+ shift
+ while :
+ do a=$1
+ shift
+ case $a in
+ '') break ;;
+ -O) ;;
+ *) set '' "$@" $a ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ $cc $ccflags "$@"
+ code=$?
+else export PATH=/bin:$PATH LIBPATH=/usr/lib:/lib
+ ccflags="$ccflags -blibpath:$LIBPATH"
+fi
+$cc $ccflags "$@"
+code=$?
+case $code in
+127|255) code=1 ;;
+esac
+exit $code
diff --git a/src/cmd/INIT/cc.ibm.risc.gcc b/src/cmd/INIT/cc.ibm.risc.gcc
new file mode 100755
index 0000000..5d4d16b
--- /dev/null
+++ b/src/cmd/INIT/cc.ibm.risc.gcc
@@ -0,0 +1,36 @@
+: cc wrapper for aix risc gcc : 2012-02-14 :
+
+hosttype=ibm.risc
+
+case $HOSTTYPE in
+$hosttype-64)
+ case " $* " in
+ *" -maix64 "*) ;;
+ *) set -- -maix64 "$@" ;;
+ esac
+ ;;
+*) case " $* " in
+ *" -maix64 "*) HOSTTYPE=$hosttype-64 ;;
+ *) HOSTTYPE=$hosttype ;;
+ esac
+ ;;
+esac
+
+case " $* " in
+*" -dumpmachine "*)
+ echo $HOSTTYPE
+ exit
+ ;;
+esac
+
+cc=gcc
+ccflags=
+
+case " $@ " in
+*" -shared "*)
+ ccflags="$ccflags -shared -Wl,-G -Wl,-berok"
+ ;;
+*) ccflags="-Wl,-brtl"
+ ;;
+esac
+$cc $ccflags "$@"
diff --git a/src/cmd/INIT/cc.linux.i386-64-icc b/src/cmd/INIT/cc.linux.i386-64-icc
new file mode 100755
index 0000000..4d945bf
--- /dev/null
+++ b/src/cmd/INIT/cc.linux.i386-64-icc
@@ -0,0 +1,22 @@
+: linux.i386-64 icc wrapper : 2011-10-18 :
+
+HOSTTYPE=linux.i386-64-icc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+icc=$(which icc 2>/dev/null)
+case $icc in
+"") if test -f /etc/profile.d/icc.sh
+ then . /etc/profile.d/icc.sh
+ fi
+ icc=$(which icc 2>/dev/null)
+ case $icc in
+ "") echo icc: not found >&2
+ exit 127
+ ;;
+ esac
+ ;;
+esac
+$icc "$@"
diff --git a/src/cmd/INIT/cc.linux.i386-icc b/src/cmd/INIT/cc.linux.i386-icc
new file mode 100755
index 0000000..09dc25c
--- /dev/null
+++ b/src/cmd/INIT/cc.linux.i386-icc
@@ -0,0 +1,22 @@
+: linux.ia64 icc wrapper : 2011-10-18 :
+
+HOSTTYPE=linux.ia64-icc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+icc=$(which icc 2>/dev/null)
+case $icc in
+"") if test -f /etc/profile.d/icc.sh
+ then . /etc/profile.d/icc.sh
+ fi
+ icc=$(which icc 2>/dev/null)
+ case $icc in
+ "") echo icc: not found >&2
+ exit 127
+ ;;
+ esac
+ ;;
+esac
+$icc "$@"
diff --git a/src/cmd/INIT/cc.linux.ia64-icc b/src/cmd/INIT/cc.linux.ia64-icc
new file mode 100755
index 0000000..09dc25c
--- /dev/null
+++ b/src/cmd/INIT/cc.linux.ia64-icc
@@ -0,0 +1,22 @@
+: linux.ia64 icc wrapper : 2011-10-18 :
+
+HOSTTYPE=linux.ia64-icc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+icc=$(which icc 2>/dev/null)
+case $icc in
+"") if test -f /etc/profile.d/icc.sh
+ then . /etc/profile.d/icc.sh
+ fi
+ icc=$(which icc 2>/dev/null)
+ case $icc in
+ "") echo icc: not found >&2
+ exit 127
+ ;;
+ esac
+ ;;
+esac
+$icc "$@"
diff --git a/src/cmd/INIT/cc.lynxos.i386 b/src/cmd/INIT/cc.lynxos.i386
new file mode 100755
index 0000000..acd0d02
--- /dev/null
+++ b/src/cmd/INIT/cc.lynxos.i386
@@ -0,0 +1,81 @@
+: lynxos.i386 cc wrapper with -dynamic default : 2005-02-14 :
+
+HOSTTYPE=lynxos.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=gcc
+
+link=1
+static=0
+set . "$@" /../
+while :
+do shift
+ case $1 in
+ /../) break ;;
+ esac
+ case $1 in
+ *.[cChHiI]|*.[cChHiI][pPxX][pPxX])
+ set . -D__NO_INCLUDE_WARN__ -I/sys/include/kernel -I/sys/include/family/x86 "$@"
+ shift
+ break
+ ;;
+ -o) case $2 in
+ /../) ;;
+ *) x=$1
+ shift
+ set . "$@" "$x"
+ shift
+ ;;
+ esac
+ ;;
+ -static)static=1
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+done
+while :
+do case $1 in
+ /../) shift
+ break
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+ shift
+done
+case $link:$static in
+1:0) static=n ;;
+esac
+case $static in
+n) specs=/tmp/cc$$.specs
+ trap 'status=$?; rm -f $specs; exit $status' 0 1 2
+ echo '*link: %{shared:-shared} %{static:-static} %{mshared|shared: %{static: %eerror: -shared and -static may not be combined. }}' > $specs
+ $cc -specs=$specs "$@"
+ ;;
+*) $cc "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.lynxos.ppc b/src/cmd/INIT/cc.lynxos.ppc
new file mode 100755
index 0000000..32738f2
--- /dev/null
+++ b/src/cmd/INIT/cc.lynxos.ppc
@@ -0,0 +1,85 @@
+: lynxos.ppc cc wrapper with -mshared default : 2005-06-01 :
+
+HOSTTYPE=lynxos.ppc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=gcc
+
+link=1
+static=0
+set . "$@" /../
+while :
+do shift
+ case $1 in
+ /../) break ;;
+ esac
+ case $1 in
+ *.[cChHiI]|*.[cChHiI][pPxX][pPxX])
+ set . -D__NO_INCLUDE_WARN__ -I/sys/include/kernel -I/sys/include/family/ppc "$@"
+ shift
+ break
+ ;;
+ -o) case $2 in
+ /../) ;;
+ *) x=$1
+ shift
+ set . "$@" "$x"
+ shift
+ ;;
+ esac
+ ;;
+ -static)static=1
+ ;;
+ -mshared)
+ static=n
+ continue
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+done
+while :
+do case $1 in
+ /../) shift
+ break
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+ shift
+done
+case $link:$static in
+1:0) static=n ;;
+esac
+case $static in
+n) specs=/tmp/cc$$.specs
+ trap 'status=$?; rm -f $specs; exit $status' 0 1 2
+ echo '*link: %{shared:-shared} %{static:-static} %{mshared|shared: %{static: %eerror: -shared and -static may not be combined. }}' > $specs
+ $cc -specs=$specs -mshared "$@"
+ ;;
+*) $cc "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.mvs.390 b/src/cmd/INIT/cc.mvs.390
new file mode 100755
index 0000000..50bc7d5
--- /dev/null
+++ b/src/cmd/INIT/cc.mvs.390
@@ -0,0 +1,279 @@
+: mvs.390 cc wrapper for unix message and exit code semantics : 2012-01-20 :
+
+HOSTTYPE=mvs.390
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+ar=ar
+cc=/bin/c89
+CC=/bin/c++
+ccflags="-D_ALL_SOURCE -Wc,dll"
+objmax=60
+tmpfiles=
+unbotch=
+
+# -n as *first* arg shows but does not do
+# -Wc,exportall => -Wl,dll
+# -Bdynamic => .c,.o dynamic
+# -Bstatic => .c,.o static
+# *.C => cc=$CC
+# *.cpp => cc=$CC
+# *.cxx => cc=$CC
+# no optimization until the optimizer is fixed:
+# -O dropped (no optimization)
+# -0 dropped (no optimization)
+# -1 -O (default level 1 optimization)
+# -2 -2 (maximal level 2 optimization)
+
+let argc=0 cmp=0 dll=0 libc=0 dynamic=1 dynamic_objc=0 static_objc=0 relc=0 botched=0
+case $1 in
+-n) exec=print
+ shift
+ ;;
+*) exec=
+ ;;
+esac
+export _CC_ACCEPTABLE_RC=1
+export _C89_ACCEPTABLE_RC=$_CC_ACCEPTABLE_RC
+export _CXX_ACCEPTABLE_RC=$_CC_ACCEPTABLE_RC
+case " $* " in
+*.C" "*)let dll=2
+ cc=$CC
+ export _CXXSUFFIX=C
+ ;;
+*.cpp" "*)let dll=2
+ cc=$CC
+ export _CXXSUFFIX=cpp
+ ;;
+*.cxx" "*)let dll=2
+ cc=$CC
+ export _CXXSUFFIX=cxx
+ ;;
+esac
+exe=
+xxx=
+while :
+do case $# in
+ 0) break ;;
+ esac
+ arg=$1
+ case $arg in
+ -1) arg=-O
+ ;;
+ -Bdynamic)
+ let dynamic=1
+ ;;
+ -Bstatic)
+ let dynamic=0
+ ;;
+ -c) let cmp=1
+ ;;
+ -D_ALL_SOURCE|-D_ALL_SOURCE=*)
+ arg=
+ ;;
+ -D*[\ \(\)]*)
+ arg=${arg#-D}
+ botch_macro[botched]=${arg%%=*}
+ botch_value[botched]=${arg#*=}
+ let botched=botched+1
+ arg=
+ ;;
+ -o) argv[argc]=$arg
+ let argc=argc+1
+ shift
+ arg=$1
+ exe=$arg
+ rm -f "$exe"
+ ;;
+ -[O0]) arg=
+ ;;
+ -Wc,dll)arg=
+ ;;
+ -Wc,exportall)
+ let dll=1
+ ;;
+ -Wl,dll)arg=
+ let dll=1
+ ;;
+ *.c) if [[ $botched != 0 ]]
+ then src=$arg
+ arg=${arg##*/}
+ unbotch="$unbotch ${arg%.c}.o"
+ arg=__$arg
+ tmpfiles="$tmpfiles $arg"
+ {
+ while [[ $botched != 0 ]]
+ do let botched=botched-1
+ print -r -- "#define ${botch_macro[botched]} ${botch_value[botched]}"
+ done
+ cat $src
+ } > $arg
+ fi
+ ;;
+ *.o) if test 0 != $dynamic
+ then let dynamic_objc=dynamic_objc+1
+ else let static_objc=static_objc+1
+ fi
+ ;;
+ *.x) a=${arg%.x}.a
+ if test -f $a
+ then argv[argc]=$a
+ let argc=argc+1
+ xxx=-Wl,dll
+ case $a in
+ ast.a|*/ast.a)
+ cc="$CC -u_ast_init"
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ case $arg in
+ ?*) argv[argc]=$arg
+ let argc=argc+1
+ ;;
+ esac
+ shift
+done
+
+tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+tmpfiles="$tmp $tmpfiles"
+
+# if any dll .o's are in .a then a .x gets generated
+# but the native cc doesn't jcl for the .x
+# -Wl,dll does that, so we nuke the .x and keep the exe
+
+test 0 != $dll && xxx=
+case $xxx in
+?*) case $exe in
+ ?*) a=${exe##*/}
+ a=${a%.*}
+ case $exe in
+ */*) tmpfiles="$tmpfiles ${exe%/*}/${a}.x" ;;
+ *) tmpfiles="$tmpfiles ${a}.x" ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+if test 0 != $dll
+then if test 0 != $cmp
+ then xxx="-D_SHARE_EXT_VARS $xxx"
+ else xxx="-Wl,dll $xxx"
+ fi
+fi
+set -- $xxx "${argv[@]}"
+
+# can't handle more than objmax .o's
+# -r into intermediates doesn't work, but the cat trick does
+# also, the runtime dll file must be executable but cc -Wl,dll forgets
+
+if test 0 != $dll -a \( $dynamic_objc -ge $objmax -o 0 != $static_objc \)
+then unset argv
+ argc=0 libc=0 dynamic=1 dynamic_objc=0 static_objc=0 endc=0
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -Bdynamic)
+ let dynamic=1
+ ;;
+ -Bstatic)
+ let dynamic=0
+ ;;
+ *.o) if test 0 != $dynamic
+ then dynamic_objv[dynamic_objc]=$1
+ let dynamic_objc=dynamic_objc+1
+ else static_objv[static_objc]=$1
+ let static_objc=static_objc+1
+ fi
+ ;;
+ -l*) libv[libc]=$1
+ let libc=libc+1
+ ;;
+ -o) argv[argc]=$1
+ let argc=argc+1
+ shift
+ argv[argc]=$1
+ let argc=argc+1
+ exe=$1
+ ;;
+ *) argv[argc]=$1
+ let argc=argc+1
+ ;;
+ esac
+ shift
+ done
+ if test 0 != $static_objc
+ then case $exe in
+ ?*) $exec $ar cr ${exe%.*}.a "${static_objv[@]}" ;;
+ esac
+ fi
+ if test 0 != $dynamic_objc
+ then cat=0.0.o
+ tmpfiles="$tmpfiles $cat"
+ cat "${dynamic_objv[@]}" > $cat || exit
+ else cat=
+ fi
+ set -- "${argv[@]}" $cat "${libv[@]}"
+fi
+
+# grep through the warning/error messages to get the true exit code
+# some annoying messages are dropped while we're at it
+
+trap 'rm -f $tmpfiles' 0 1 2 15
+$exec $cc $ccflags "$@" 2> $tmp
+code=$?
+for i in $unbotch
+do test -f __$i && mv __$i $i
+done
+typeset -l lc
+while :
+do if read line
+ then lc=$line
+ case $lc in
+ *'#include file'*'not found'*)
+ code=1
+ ;;
+ *'#pragma ignored'*)
+ continue
+ ;;
+ *'definition side file is not defined'*)
+ continue
+ ;;
+ *'step ended with return code 4'*)
+ code=0
+ continue
+ ;;
+ *'step ended with return code'*)
+ code=1
+ continue
+ ;;
+ *'try again'*)
+ code=1
+ continue
+ ;;
+ *'unknown preprocessing directive'*)
+ code=1
+ case $lc in
+ 'warning '*)
+ set -- $line
+ shift
+ line=$*
+ ;;
+ esac
+ ;;
+ *'unresolved writable static references are detected'*)
+ test 0 != $dll && continue
+ ;;
+ esac
+ else case $code:$exe in
+ 0:?*) $exec chmod +x $exe ;;
+ esac
+ exit $code
+ fi
+ echo "$line" >&2
+done < $tmp
diff --git a/src/cmd/INIT/cc.next.i386 b/src/cmd/INIT/cc.next.i386
new file mode 100755
index 0000000..16df709
--- /dev/null
+++ b/src/cmd/INIT/cc.next.i386
@@ -0,0 +1,158 @@
+: next.i386 cc wrapper for unix message and exit code semantics : 1995-05-09 :
+
+HOSTTYPE=next.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+# 1995-05-09 -lposix termios.o waitpid.o setpgid.o *do* work
+# 1994-11-04 -posix has old redirection hole bug
+# -D_POSIX_SOURCE requires <sys/dirent.h> manual fixes
+# libexpr/exeval.c bombs -O, no -O ok
+
+command=cc
+cc="/bin/cc -D_POSIX_SOURCE"
+nooptimize="exeval"
+
+# first check $INSTALLROOT/botch
+
+case $INSTALLROOT in
+"") echo "$command: INSTALLROOT: must be defined and exported" >&2; exit 1 ;;
+esac
+if test ! -d $INSTALLROOT/botch -a -dryrun != "$1"
+then if mkdir $INSTALLROOT/botch
+ then : ok to initialize
+ else echo "$command: $INSTALLROOT/botch must be initialized by the owner of $INSTALLROOT" 2>&1
+ exit 1
+ fi
+ (
+ cd $INSTALLROOT/botch
+ dir=.
+ for i in lib . include sys
+ do case $i in
+ .) dir=.
+ ;;
+ *) case $i in
+ /*) dir=$i ;;
+ *) dir=$dir/$i ;;
+ esac
+ test -d $dir || mkdir $dir
+ ;;
+ esac
+ done
+ if test ! -f include/sys/dirent.h
+ then echo "#include <dirent.h>" > tmp.c
+ header=`$cc -E tmp.c | sed -e '/^#[ ]*1[ ].*\/sys\/dirent\.h"/!d' -e 's/.*"\(.*\)".*/\1/'`
+ sed -e 's/[ ]off_t[ ][ ]*d_off[ ]*;//' $header > include/sys/dirent.h
+ fi
+ if test ! -f lib/libbotch.a
+ then lipo /usr/lib/libposix.a -thin i386 -output tmp.a
+ ar x tmp.a termios.o waitpid.o setpgid.o
+ ar cr lib/libbotch.a *.o
+ ranlib lib/libbotch.a
+ fi
+ rm -f *.[aco]
+ )
+fi
+
+# now slip in our args
+
+case $nooptimize in
+"") nooptimize=.
+ ;;
+*) optimize=
+ for arg in $nooptimize
+ do case $optimize in
+ ?*) optimize="$optimize|" ;;
+ esac
+ optimize="$optimize$arg.[ci]|*/$arg.[ci]"
+ done
+ nooptimize=$optimize
+ ;;
+esac
+set . "$@" .
+noexec=
+library=
+local=
+optimize=
+verbose=
+while :
+do shift
+ arg=$1
+ shift
+ case $arg in
+ .) break
+ ;;
+ -[cES]) library=1
+ ;;
+ -O) optimize=1
+ ;;
+ -v) verbose=1
+ ;;
+ -dryrun)noexec=1
+ verbose=1
+ ;;
+ -I-) case $local in
+ "") local=1
+ set . "$@" -I$INSTALLROOT/botch/include -I- -I$INSTALLROOT/botch/include
+ ;;
+ *) set . "$@" -I- -I$INSTALLROOT/botch/include
+ ;;
+ esac
+ continue
+ ;;
+ -I*|*.[cChHiI]|*.[cChHiI][pPxX][pPxX])
+ case $optimize in
+ 1) eval "
+ case \$arg in
+ $nooptimize)
+ optimize=0
+ ;;
+ esac
+ "
+ ;;
+ esac
+ case $local in
+ "") local=1
+ set . "$@" -I$INSTALLROOT/botch/include "$arg"
+ continue
+ ;;
+ esac
+ ;;
+ -last|*/libast.a)
+ case $library in
+ "") library=1
+ set . "$@" $INSTALLROOT/botch/lib/libbotch.a "$arg" $INSTALLROOT/botch/lib/libbotch.a
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ set . "$@" "$arg"
+done
+case $library in
+"") set . "$@" $INSTALLROOT/botch/lib/libbotch.a
+ shift
+ ;;
+esac
+case $optimize in
+0) set . "$@" .
+ while :
+ do shift
+ arg=$1
+ shift
+ case $arg in
+ .) break ;;
+ -O) set . "$@" ;;
+ *) set . "$@" "$arg" ;;
+ esac
+ done
+ ;;
+esac
+case $verbose in
+?*) echo $cc "$@" ;;
+esac
+case $noexec in
+"") $cc "$@" ;;
+esac
diff --git a/src/cmd/INIT/cc.next.m68k b/src/cmd/INIT/cc.next.m68k
new file mode 100755
index 0000000..1c2f8b5
--- /dev/null
+++ b/src/cmd/INIT/cc.next.m68k
@@ -0,0 +1,9 @@
+: next.m68k cc wrapper that enables posix : 2000-12-15 :
+
+HOSTTYPE=next.m68k
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/bin/cc -posix -Xlinker -m "$@"
diff --git a/src/cmd/INIT/cc.osf.alpha b/src/cmd/INIT/cc.osf.alpha
new file mode 100755
index 0000000..fe19bb4
--- /dev/null
+++ b/src/cmd/INIT/cc.osf.alpha
@@ -0,0 +1,9 @@
+: osf.alpha cc wrapper with reasonable namespace defaults : 1998-02-04 :
+
+HOSTTYPE=osf.alpha
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/usr/bin/cc -std -Dnoshare=_noshare_ -Dreadonly=_readonly_ "$@"
diff --git a/src/cmd/INIT/cc.pentium4 b/src/cmd/INIT/cc.pentium4
new file mode 100755
index 0000000..8794cda
--- /dev/null
+++ b/src/cmd/INIT/cc.pentium4
@@ -0,0 +1,26 @@
+: linux.pentium4 gcc wrapper : 2005-10-24 :
+
+HOSTTYPE=linux.pentium4
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+case " $* " in
+*" -O "*)
+ set -A argv -- "$@"
+ set -A nargv
+ integer i j
+ for ((i = j = 0; i < ${#argv[@]}; i++))
+ do if [[ ${argv[i]} == -O ]]
+ then nargv[j++]=-O3
+ nargv[j++]=-march=pentium4
+ else nargv[j++]=${argv[i]}
+ fi
+ done
+ gcc "${nargv[@]}"
+ exit
+ ;;
+esac
+
+gcc "$@"
diff --git a/src/cmd/INIT/cc.sco.i386 b/src/cmd/INIT/cc.sco.i386
new file mode 100755
index 0000000..d0cba57
--- /dev/null
+++ b/src/cmd/INIT/cc.sco.i386
@@ -0,0 +1,9 @@
+: sco.i386 cc wrapper with reasonable binary and namespace : 1998-02-04 :
+
+HOSTTYPE=sco.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/bin/cc -b elf -D_SVID3 "$@"
diff --git a/src/cmd/INIT/cc.sgi.mips2 b/src/cmd/INIT/cc.sgi.mips2
new file mode 100755
index 0000000..a0e5d33
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips2
@@ -0,0 +1,68 @@
+: sgi.mips2 cc wrapper that generates mips2 binaries : 2006-02-14 :
+
+HOSTTYPE=sgi.mips2
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=-OPT:Olimit=0
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+if test -d /usr/lib32
+then LD_LIBRARYN32_PATH=/lib32 $cc -32 -mips2 $flags $dynamic $ldignore $ignore "$@"
+else $cc -mips2 $flags $ignore "$@"
+fi
diff --git a/src/cmd/INIT/cc.sgi.mips3 b/src/cmd/INIT/cc.sgi.mips3
new file mode 100755
index 0000000..426317a
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips3
@@ -0,0 +1,110 @@
+: sgi.mips3 cc wrapper that generates mips3 binaries : 2007-04-27 :
+
+HOSTTYPE=sgi.mips3
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+# ld:
+# 15
+# 84
+# 85
+# 134
+# cc:
+# 1685 (first!!) Invalid error number: X.
+# 1035 cpp #error -- 0 exit status by default - botch botch botch
+# 1048
+# 1155
+# 1171 The indicated expression has no effect.
+# 1184 "=" is used where where "==" may have been intended.
+# 1209 The controlling expression is constant.
+# 1343
+# 3169 X not marked as intrinsic because it is not yet declared
+# 3170 X not marked as intrinsic because it is not yet declared
+# 3421 expecting function name #pragma intrinsic (X)
+# 3433 X not marked as intrinsic because it is not yet declared
+# 3434 X not marked as intrinsic because it is not yet declared
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=-OPT:Olimit=0
+fatal=1035
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3421,3433,3434
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $fatal in
+?*) fatal="-diag_error $fatal" ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+case $1 in
+-mips2) if test -d /usr/lib32
+ then LD_LIBRARYN32_PATH=/lib32 $cc -32 -mips2 $flags $dynamic $ldignore $ignore "$@"
+ else $cc -mips2 $flags $ignore "$@"
+ fi
+ ;;
+-mips4) case " $* " in
+ *" -ldl "*)
+ integer n=0
+ for i
+ do case $i in
+ -ldl) ;;
+ *) a[n++]=$i ;;
+ esac
+ done
+ set -- ${a[@]}
+ esac
+ $cc -64 -mips4 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+*) $cc -n32 -mips3 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.sgi.mips3-o32 b/src/cmd/INIT/cc.sgi.mips3-o32
new file mode 100755
index 0000000..a9c6c9c
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips3-o32
@@ -0,0 +1,65 @@
+: sgi.mips3-o32 cc wrapper that generates mips3 o32 binaries : 2006-02-14 :
+
+HOSTTYPE=sgi.mips3-o32
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+$cc -o32 -mips3 $flags $dynamic $ldignore $ignore "$@"
diff --git a/src/cmd/INIT/cc.sgi.mips4 b/src/cmd/INIT/cc.sgi.mips4
new file mode 100755
index 0000000..1300cd2
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips4
@@ -0,0 +1,90 @@
+: sgi.mips4 cc wrapper that generates mips4 binaries : 2007-04-27 :
+
+HOSTTYPE=sgi.mips4
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=-OPT:Olimit=0
+fatal=1035
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $fatal in
+?*) fatal="-diag_error $fatal" ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+case $1 in
+-mips2) if test -d /usr/lib32
+ then LD_LIBRARYN32_PATH=/lib32 $cc -32 -mips2 $flags $dynamic $ldignore $ignore "$@"
+ else $cc -mips2 $flags $ignore "$@"
+ fi
+ ;;
+-mips3) $cc -n32 -mips3 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+*) case " $* " in
+ *" -ldl "*)
+ integer n=0
+ for i
+ do case $i in
+ -ldl) ;;
+ *) a[n++]=$i ;;
+ esac
+ done
+ set -- ${a[@]}
+ esac
+ $cc -64 -mips4 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.sgi.mips4-n32 b/src/cmd/INIT/cc.sgi.mips4-n32
new file mode 100755
index 0000000..0e1b562
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips4-n32
@@ -0,0 +1,65 @@
+: sgi.mips4-n32 cc wrapper that generates mips4 n32 binaries : 2006-02-14 :
+
+HOSTTYPE=sgi.mips4-n32
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+$cc -n32 -mips4 $flags $dynamic $ldignore $ignore "$@"
diff --git a/src/cmd/INIT/cc.specialize b/src/cmd/INIT/cc.specialize
new file mode 100755
index 0000000..87077b5
--- /dev/null
+++ b/src/cmd/INIT/cc.specialize
@@ -0,0 +1,35 @@
+: -O* specialization cc wrapper : 2011-11-11 :
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=cc
+
+CCREPLACE='' # these (possibly empty) options replace -O*
+CCALWAYS='' # these (possibly empty) options always set
+
+case $CCREPLACE in
+'') ;;
+*) case " $* " in
+ *" -O"*)
+ set '' "$@" ''
+ shift
+ while :
+ do a=$1
+ shift
+ case $a in
+ '') break
+ ;;
+ -O*) set '' "$@" $CCREPLACE
+ ;;
+ *) set '' "$@" "$a"
+ ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ ;;
+esac
+$cc $CCALWAYS "$@"
diff --git a/src/cmd/INIT/cc.unix.mc68k b/src/cmd/INIT/cc.unix.mc68k
new file mode 100755
index 0000000..ebdfa0d
--- /dev/null
+++ b/src/cmd/INIT/cc.unix.mc68k
@@ -0,0 +1,76 @@
+: 3B1/PC7300 unix.mc68k cc wrapper for ANSI C : 2002-09-01 :
+
+HOSTTYPE=unix.mc68k
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+# /bin/cc predates ANSI C; use gcc
+# some headers depend on SYSTEM5 or mc68k being defined
+# headers for Ethernet software are under /usr/ethernet/include
+# both /usr/lib/libnet.a and /usr/lib/libcurses.a define select()
+# -lcurses uses a version of select for napms(), but that
+# implementation always returns an error if given file
+# descriptors to watch
+# the one in -lnet must be used if fds (instead of or in addition to
+# a timeout) are of interest therefore, -lnet should be
+# specified before -lcurses
+# rename(old, new) in /usr/lib/libnet.a fails if new exists
+# (permitted by ANSI/ISO C-1990 7.9.4.2)
+# gcc -fpic doesn't work as there's no _GLOBAL_OFFSET_TABLE symbol
+
+cc="gcc"
+
+exec=
+show=:
+inc=0
+lib=0
+set '' -DSYSTEM5 -Dmc68k "$@" ''
+shift
+while :
+do a=$1
+ shift
+ case $a in
+ '') break
+ ;;
+ -lcurses|libcurses.a|*/libcurses.a)
+ lib=1
+ set '' "$@" -lnet
+ shift
+ ;;
+ -lnet|libnet.a|*/libnet.a)
+ lib=1
+ ;;
+ -o) a=$1
+ shift
+ set '' "$@" -o
+ shift
+ ;;
+ -fpic) continue
+ ;;
+ -n) exec=:
+ continue
+ ;;
+ -v) show=echo
+ continue
+ ;;
+ -*) ;;
+ *) case $inc in
+ 0) inc=1
+ set '' "$@" -I/usr/ethernet/include
+ shift
+ ;;
+ esac
+ ;;
+ esac
+ set '' "$@" "$a"
+ shift
+done
+case $lib in
+0) set '' "$@" -lnet
+ shift
+ ;;
+esac
+$show $cc "$@"
+$exec $cc "$@"
diff --git a/src/cmd/INIT/crossexec.sh b/src/cmd/INIT/crossexec.sh
new file mode 100644
index 0000000..9d73ee2
--- /dev/null
+++ b/src/cmd/INIT/crossexec.sh
@@ -0,0 +1,139 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: cross compiler a.out execution
+
+command=crossexec
+
+tmp=/tmp/cross$$
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: crossexec (AT&T Labs Research) 2004-01-04 $
+]
+'$USAGE_LICENSE$'
+[+NAME?crossexec - cross compiler a.out execution]
+[+DESCRIPTION?\bcrossexec\b runs a cross-compiled \acommand\a in an environment
+ that supports a cross-compilation architecture different from the
+ current host. The cross environment is determined by \acrosstype\a,
+ usually a host type name produced by \bpackage\b(1). \acrosstype\a
+ is used to find an entry in \b$HOME/.crossexec\b that specifies
+ the cross compiler host and access details.]
+[+?The exit status of \bcrossexec\b is the exit status of \acommand\a.]
+[+CROSS ENVIRONMENT FILE?\b$HOME/.crossexec\b contains one line for each
+ supported \acrosstype\a. Each line contains 5 tab separated fields.
+ Field default values are specified as \b-\b. The fields are:]{
+ [+crosstype?The host type produced by \bpackage\b(1).]
+ [+host?The host name.]
+ [+user?The user name on \ahost\a. The default is the current user.]
+ [+dir?The directory to copy \acommand\a and execute it. The default
+ is the \auser\a \b$HOME\b on \ahost\a.]
+ [+shell?The command used to get shell access to \ahost\a. Currently
+ only \brsh\b and \bssh\b are supported.]
+ [+copy?The command used to copy \acommand\a to \ahost\a. Currently
+ only \brcp\b and \bscp\b are supported.]
+}
+[n:show?Show the underlying commands but do not execute.]
+
+crosstype command [ option ... ] [ file ... ]
+
+[+SEE ALSO?\brcp\b(1), \brsh\b(1), \bscp\b(1), \bssh\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="crosstype command [ option ... ] [ file ... ]"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+exec=
+
+# get the options and operands
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ n) exec=echo ;;
+ *) usage ;;
+ esac
+done
+shift $OPTIND-1
+case $# in
+[01]) usage ;;
+esac
+
+type=$1
+shift
+cmd=$1
+shift
+
+# get the host info
+
+info=$HOME/.$command
+if test ! -r $info
+then echo "$command: $info: not found" >&2
+ exit 1
+fi
+ifs=${IFS-'
+ '}
+while :
+do IFS=' '
+ read hosttype hostname usr dir sh cp
+ code=$?
+ IFS=$ifs
+ case $code in
+ 0) ;;
+ *) echo "$command: $type: unknown cross compiler host type" >&2
+ exit 1
+ ;;
+ esac
+ case $hosttype in
+ $type) break ;;
+ esac
+done < $info
+
+# fill in the defaults
+
+case $usr in
+-) cpu= shu= ;;
+*) cpu=${usr}@ shu="-l $usr" ;;
+esac
+case $dir in
+-) dir= ;;
+esac
+case $sh in
+''|-) sh=ssh ;;
+esac
+case $cp in
+''|-) cp=scp ;;
+scp) cp="$cp -q" ;;
+esac
+
+trap "rm -f $tmp" 0 1 2 3 15
+$exec $cp $cmd $cpu$hostname:$dir </dev/null || exit 1
+cmd=./${cmd##*/}
+$exec $sh $shu $hostname "cd $dir; LD_LIBRARY_PATH=: $cmd $@ </dev/null 2>/dev/null; code=\$?; rm -f $cmd; echo $command: exit \$code >&2" </dev/null 2>$tmp
+exit `sed -e '/^'$command': exit [0-9][0-9]*$/!d' -e 's/.* //' $tmp`
diff --git a/src/cmd/INIT/db.c b/src/cmd/INIT/db.c
new file mode 100644
index 0000000..5a3a7c1
--- /dev/null
+++ b/src/cmd/INIT/db.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for sleepycat dbm compatibility
+ */
+
+#define DB_DBM_HSEARCH 1
+
+#if DB_DBM_HSEARCH
+#include <db.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/ditto.sh b/src/cmd/INIT/ditto.sh
new file mode 100644
index 0000000..1141a0d
--- /dev/null
+++ b/src/cmd/INIT/ditto.sh
@@ -0,0 +1,460 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: replicate directory hierarchies
+
+COMMAND=ditto
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $COMMAND"
+ USAGE=$'
+[-?
+@(#)$Id: ditto (AT&T Labs Research) 2010-11-22 $
+]
+'$USAGE_LICENSE$'
+[+NAME?ditto - replicate directory hierarchies]
+[+DESCRIPTION?\bditto\b replicates the \asource\a directory hierarchy
+ to the \adestination\a directory hierarchy. Both \asource\a and
+ \adestination\a may be of the form
+ [\auser\a@]][\ahost\a:]][\adirectory\a]]. At least one of
+ \ahost\a: or \adirectory\a must be specified. The current user is used
+ if \auser@\a is omitted, the local host is used if \ahost\a: is
+ omitted, and the user home directory is used if \adirectory\a is
+ omitted.]
+[+?Remote hosts and files are accessed via \bssh\b(1) or \brsh\b(1). \bksh\b(1),
+ \bpax\b(1), and \btw\b(1) must be installed on the local and remote hosts.]
+[+?For each source file \bditto\b does one of these actions:]{
+ [+chmod|chown?change the mode and/or ownership of the destination
+ file to match the source]
+ [+copy?copy the source file to the destination]
+ [+delete?delete the destination file]
+ [+skip?the destination file is not changed]
+}
+[+?The source and destination hierarchies are generated by \btw\b(1) with
+ the \b--logical\b option. An \b--expr\b option may
+ be specified to prune the search. The \btw\b searches are relative to
+ the \asource\a and \adestination\a directories.]
+[c:checksum?Copy if the \btw\b(1) 32x4 checksum mismatches.]
+[d:delete?Delete \adestination\a files that are not in the \asource\a.]
+[e:expr?\btw\b(1) select expression.]:[tw-expression]
+[m!:mode?Preserve file mode.]
+[n:show?Show the operations but do not exectute.]
+[o:owner?Preserve file user and group ownership.]
+[p:physical?Generate source and destination hierarchies by \btw\b(1) with
+ the \b--physical\b option.]
+[r:remote?The remote access protocol; either \bssh\b or
+ \brsh\b.]:[protocol:=ssh]
+[u:update?Copy only if the \asource\a file is newer than the
+ \adestination\a file.]
+[v:verbose?Trace the operations as they are executed.]
+[D:debug?Enable the debug trace.]
+
+source destination
+
+[+SEE ALSO?\brdist\b(1), \brsync\b(1), \brsh\b(1), \bssh\b(1), \btw\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="de:[tw-expression]mnouvD source destination"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+parse() # id user@host:dir
+{
+ typeset id dir user host
+ id=$1
+ dir=$2
+ (( debug || ! exec )) && print -r $id $dir
+ if [[ $dir == *@* ]]
+ then
+ user=${dir%%@*}
+ dir=${dir#${user}@}
+ else
+ user=
+ fi
+ if [[ $dir == *:* ]]
+ then
+ host=${dir%%:*}
+ dir=${dir#${host}:}
+ else
+ host=
+ fi
+ if [[ $user ]]
+ then
+ user="-l $user"
+ if [[ ! $host ]]
+ then
+ host=$(hostname)
+ fi
+ fi
+ eval ${id}_user='$user'
+ eval ${id}_host='$host'
+ eval ${id}_dir='$dir'
+}
+
+# initialize
+
+typeset -A chown chmod
+typeset tw cp rm link
+integer ntw=0 ncp=0 nrm=0 nlink=0 n
+
+typeset src_user src_host src_path src_type src_uid src_gid src_perm src_sum
+typeset dst_user dst_host dst_path dst_type dst_uid dst_gid dst_perm dst_sum
+integer src_size src_mtime src_eof
+integer dst_size dst_mtime dst_eof
+
+integer debug=0 delete=0 exec=1 mode=1 owner=0 update=0 verbose=0 logical
+
+typeset remote=ssh trace
+typeset checksum='"-"' pax="pax"
+typeset paxreadflags="" paxwriteflags="--write --format=tgz --nosummary"
+
+tw[ntw++]=tw
+(( logical=ntw ))
+tw[ntw++]=--logical
+tw[ntw++]=--chop
+tw[ntw++]=--ignore-errors
+tw[ntw++]=--expr=sort:name
+
+# grab the options
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ c) checksum=checksum ;;
+ d) delete=1 ;;
+ e) tw[ntw++]=--expr=\"$OPTARG\" ;;
+ m) mode=0 ;;
+ n) exec=0 verbose=1 ;;
+ o) owner=1 ;;
+ p) tw[logical]=--physical ;;
+ r) remote=$OPTARG ;;
+ u) update=1 ;;
+ v) verbose=1 ;;
+ D) debug=1 ;;
+ *) usage ;;
+ esac
+done
+shift $OPTIND-1
+if (( $# != 2 ))
+then usage
+fi
+tw[ntw++]=--expr=\''action:printf("%d\t%d\t%s\t%s\t%s\t%-.1s\t%o\t%s\t%s\n", size, mtime, '$checksum', uid, gid, mode, perm, path, symlink);'\'
+if (( exec ))
+then
+ paxreadflags="$paxreadflags --read"
+fi
+if (( verbose ))
+then
+ paxreadflags="$paxreadflags --verbose"
+fi
+
+# start the source and destination path list generators
+
+parse src "$1"
+parse dst "$2"
+
+# the |& command may exit before the exec &p
+# the print sync + read delays the |& until the exec &p finishes
+
+if [[ $src_host ]]
+then ($remote $src_user $src_host "{ test ! -f .profile || . ./.profile ;} && cd $src_dir && read && ${tw[*]}") 2>&1 |&
+else (cd $src_dir && read && eval "${tw[@]}") 2>&1 |&
+fi
+exec 5<&p 7>&p
+print -u7 sync
+exec 7>&-
+
+if [[ $dst_host ]]
+then ($remote $dst_user $dst_host "{ test ! -f .profile || . ./.profile ;} && cd $dst_dir && read && ${tw[*]}") 2>&1 |&
+else (cd $dst_dir && read && eval "${tw[@]}") 2>&1 |&
+fi
+exec 6<&p 7>&p
+print -u7 sync
+exec 7>&-
+
+# scan through the sorted path lists
+
+if (( exec ))
+then
+ src_skip=*
+ dst_skip=*
+else
+ src_skip=
+ dst_skip=
+fi
+src_path='' src_eof=0
+dst_path='' dst_eof=0
+ifs=${IFS-$' \t\n'}
+IFS=$'\t'
+while :
+do
+ # get the next source path
+
+ if [[ ! $src_path ]] && (( ! src_eof ))
+ then
+ if read -r -u5 text src_mtime src_sum src_uid src_gid src_type src_perm src_path src_link
+ then
+ if [[ $text != +([[:digit:]]) ]]
+ then
+ print -u2 $COMMAND: source: "'$text'"
+ src_path=
+ continue
+ fi
+ src_size=$text
+ elif (( dst_eof ))
+ then
+ break
+ elif (( src_size==0 ))
+ then
+ exit 1
+ else
+ src_path=
+ src_eof=1
+ fi
+ fi
+
+ # get the next destination path
+
+ if [[ ! $dst_path ]] && (( ! dst_eof ))
+ then
+ if read -r -u6 text dst_mtime dst_sum dst_uid dst_gid dst_type dst_perm dst_path dst_link
+ then
+ if [[ $text != +([[:digit:]]) ]]
+ then
+ print -u2 $COMMAND: destination: $text
+ dst_path=
+ continue
+ fi
+ dst_size=$text
+ elif (( src_eof ))
+ then
+ break
+ elif (( dst_size==0 ))
+ then
+ exit 1
+ else
+ dst_path=
+ dst_eof=1
+ fi
+ fi
+
+ # determine the { cp rm chmod chown } ops
+
+ if (( debug ))
+ then
+ [[ $src_path ]] && print -r -u2 -f $': src %8s %10s %s %s %s %s %3s %s\n' $src_size $src_mtime $src_sum $src_uid $src_gid $src_type $src_perm "$src_path"
+ [[ $dst_path ]] && print -r -u2 -f $': dst %8s %10s %s %s %s %s %3s %s\n' $dst_size $dst_mtime $dst_sum $dst_uid $dst_gid $dst_type $dst_perm "$dst_path"
+ fi
+ if [[ $src_path == $dst_path ]]
+ then
+ if [[ $src_type != $dst_type ]]
+ then
+ rm[nrm++]=$dst_path
+ if [[ $dst_path != $dst_skip ]]
+ then
+ if [[ $dst_type == d ]]
+ then
+ dst_skip="$dst_path/*"
+ print -r rm -r "'$dst_path'"
+ else
+ dst_skip=
+ print -r rm "'$dst_path'"
+ fi
+ fi
+ fi
+ if [[ $src_type == l ]]
+ then if [[ $src_link != $dst_link ]]
+ then
+ cp[ncp++]=$src_path
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r cp "'$src_path'"
+ fi
+ fi
+ elif [[ $src_type != d ]] && { (( update && src_mtime > dst_mtime )) || (( ! update )) && { (( src_size != dst_size )) || [[ $src_sum != $dst_sum ]] ;} ;}
+ then
+ if [[ $src_path != . ]]
+ then
+ cp[ncp++]=$src_path
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r cp "'$src_path'"
+ fi
+ fi
+ else
+ if (( owner )) && [[ $src_uid != $dst_uid || $src_gid != $dst_gid ]]
+ then
+ chown[$src_uid.$src_gid]="${chown[$src_uid.$src_gid]} '$src_path'"
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r chown $src_uid.$src_gid "'$src_path'"
+ fi
+ if (( (src_perm & 07000) || mode && src_perm != dst_perm ))
+ then
+ chmod[$src_perm]="${chmod[$src_perm]} '$src_path'"
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r chmod $src_perm "'$src_path'"
+ fi
+ fi
+ elif (( mode && src_perm != dst_perm ))
+ then
+ chmod[$src_perm]="${chmod[$src_perm]} '$src_path'"
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r chmod $src_perm "'$src_path'"
+ fi
+ fi
+ fi
+ src_path=
+ dst_path=
+ elif [[ ! $dst_path || $src_path && $src_path < $dst_path ]]
+ then
+ if [[ $src_path != . ]]
+ then
+ cp[ncp++]=$src_path
+ if [[ $src_path != $src_skip ]]
+ then
+ if [[ $src_type == d ]]
+ then
+ src_skip="$src_path/*"
+ print -r cp -r "'$src_path'"
+ else
+ src_skip=
+ print -r cp "'$src_path'"
+ fi
+ fi
+ fi
+ src_path=
+ elif [[ $dst_path ]]
+ then
+ if (( delete ))
+ then
+ rm[nrm++]=$dst_path
+ if [[ $dst_path != $dst_skip ]]
+ then
+ if [[ $dst_type == d ]]
+ then
+ dst_skip="$dst_path/*"
+ print -r rm -r "'$dst_path'"
+ else
+ dst_skip=
+ print -r rm "'$dst_path'"
+ fi
+ fi
+ fi
+ dst_path=
+ fi
+done
+IFS=$ifs
+
+(( exec )) || exit 0
+
+# generate, transfer and execute the { rm chown chmod } script
+
+if (( ${#rm[@]} || ${#chmod[@]} || ${#chown[@]} ))
+then
+ {
+ if (( verbose ))
+ then
+ print -r -- set -x
+ fi
+ print -nr -- cd "'$dst_dir'"
+ n=0
+ for i in ${rm[@]}
+ do
+ if (( --n <= 0 ))
+ then
+ n=32
+ print
+ print -nr -- rm -rf
+ fi
+ print -nr -- " '$i'"
+ done
+ for i in ${!chown[@]}
+ do
+ n=0
+ for j in ${chown[$i]}
+ do
+ if (( --n <= 0 ))
+ then
+ n=32
+ print
+ print -nr -- chown $i
+ fi
+ print -nr -- " $j"
+ done
+ done
+ for i in ${!chmod[@]}
+ do
+ n=0
+ for j in ${chmod[$i]}
+ do
+ if (( --n <= 0 ))
+ then
+ n=32
+ print
+ print -nr -- chmod $i
+ fi
+ print -nr -- " $j"
+ done
+ done
+ print
+ } | {
+ if (( ! exec ))
+ then
+ cat
+ elif [[ $dst_host ]]
+ then
+ $remote $dst_user $dst_host sh
+ else
+ $SHELL
+ fi
+ }
+fi
+
+# generate, transfer and read back the { cp } tarball
+
+if (( ${#cp[@]} ))
+then
+ {
+ cd $src_dir &&
+ print -r -f $'%s\n' "${cp[@]}" |
+ $pax $paxwriteflags
+ } | {
+ if [[ $dst_host ]]
+ then
+ $remote $dst_user $dst_host "{ test ! -f .profile || . ./.profile ;} && { test -d \"$dst_dir\" || mkdir -p \"$dst_dir\" ;} && cd \"$dst_dir\" && gunzip | $pax $paxreadflags"
+ else
+ ( { test -d "$dst_dir" || mkdir -p "$dst_dir" ;} && cd "$dst_dir" && gunzip | $pax $paxreadflags )
+ fi
+ }
+ wait
+fi
diff --git a/src/cmd/INIT/dl.c b/src/cmd/INIT/dl.c
new file mode 100644
index 0000000..c710ad6
--- /dev/null
+++ b/src/cmd/INIT/dl.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -ldl
+ */
+
+#ifndef dlopen
+#include <dlfcn.h>
+#endif
+
+int
+main()
+{
+ dlopen("libdl.so",0);
+ return 0;
+}
diff --git a/src/cmd/INIT/execrate.sh b/src/cmd/INIT/execrate.sh
new file mode 100644
index 0000000..71ba78d
--- /dev/null
+++ b/src/cmd/INIT/execrate.sh
@@ -0,0 +1,179 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: wrapper for .exe challenged win32 systems/commands
+
+command=execrate
+
+bins='/bin /usr/bin /usr/sbin'
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: execrate (AT&T Labs Research) 2002-02-02 $
+]
+'$USAGE_LICENSE$'
+[+NAME?execrate - wrapper for .exe challenged commands]
+[+DESCRIPTION?\bexecrate\b runs \acommand\a after checking the \afile\a
+ operands for standard semantics with respect to \bwin32\b \b.exe\b
+ suffix conventions. This command is only needed on \bwin32\b
+ systems that inconsistently handle \b.exe\b across library and
+ command interfaces. \acommand\a may be one of \bcat\b(1), \bchmod\b(1),
+ \bcmp\b(1), \bcp\b(1), \bln\b(1), \bmv\b(1), or \brm\b(1).
+ Only the 2 argument forms of \bcp\b, \bln\b and \bmv\b are handled.
+ Unsupported commands and commands requiring no change are
+ silently executed.]
+[+?With no arguments \bexecrate\b exits with status 0 if the current system
+ is \b.exe\b challenged, 1 if the current system is normal.]
+[n:show?Show the underlying commands but do not execute.]
+
+command [ option ... ] file ...
+
+[+SEE ALSO?\bwebster\b(1)]
+'
+ usage()
+ {
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+ }
+ exec=1
+ while getopts $ARGV0 "$USAGE" OPT
+ do case $OPT in
+ n) exec=0 ;;
+ *) usage ;;
+ esac
+ done
+ shift `expr $OPTIND - 1`
+ ;;
+*) usage()
+ {
+ echo "Usage: execrate [ -n ] [ command [ option ... ] file ... ]" >&2
+ exit 2
+ }
+ exec=1
+ while :
+ do case $1 in
+ -n) exec=0 ;;
+ -*) usage ;;
+ *) break ;;
+ esac
+ shift
+ done
+ ;;
+esac
+case $# in
+0) if test ! -x /bin/cat.exe
+ then exit 1 # normal
+ fi
+ if /bin/cat /bin/cat >/dev/null 2>&1
+ then exit 1 # normal
+ fi
+ exit 0 # challenged
+ ;;
+1) usage
+ ;;
+esac
+case $1 in
+*cat|*rm)
+ NUM=0
+ ;;
+*chgrp|*chmod)
+ NUM=1
+ ;;
+*cmp|*cp|*ln|*mv)
+ NUM=2
+ ;;
+*) case $exec in
+ 0) echo "$@" ;;
+ *) "$@" ;;
+ esac
+ exit
+ ;;
+esac
+CMD=$1
+shift
+case $CMD in
+*/*) ;;
+*) for d in $bins
+ do if test -x $d/$1 -o -x $d/$1.exe
+ then CMD=$d/$1
+ break
+ fi
+ done
+ ;;
+esac
+while :
+do case $1 in
+ -*) CMD="$CMD $1" ;;
+ *) break ;;
+ esac
+ shift
+done
+case $exec in
+0) CMD="echo $CMD" ;;
+esac
+case $NUM:$# in
+*:0) ;;
+1:*) CMD="$CMD $1"
+ NUM=0
+ shift
+ ;;
+esac
+case $NUM:$# in
+0:*) status=0
+ for f
+ do if test "$f" -ef "$f".exe
+ then f=$f.exe
+ fi
+ $CMD "$f"
+ case $? in
+ 0) ;;
+ *) status=$? ;;
+ esac
+ done
+ exit $status
+ ;;
+2:2) f=$1
+ case $f in
+ *.exe) ;;
+ *) if test "$f" -ef "$f".exe
+ then f=$f.exe
+ fi
+ ;;
+ esac
+ case $f in
+ *.exe) if test -d "$2"
+ then t=$2/$f
+ else t=$2
+ fi
+ case $t in
+ */*) b=`basename "$t"` ;;
+ *) b=$t ;;
+ esac
+ case $b in
+ *.*) $CMD "$f" "$t"; exit ;;
+ *) $CMD "$f" "$t".exe; exit ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+$CMD "$@"
diff --git a/src/cmd/INIT/filter.sh b/src/cmd/INIT/filter.sh
new file mode 100644
index 0000000..2637a58
--- /dev/null
+++ b/src/cmd/INIT/filter.sh
@@ -0,0 +1,98 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: convert command that operates on file args to pipeline filter
+
+command=filter
+
+tmp=/tmp/$command$$
+suf=
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: filter (AT&T Labs Research) 2001-05-31 $
+]
+'$USAGE_LICENSE$'
+[+NAME?filter - run a command in stdin/stdout mode]
+[+DESCRIPTION?\bfilter\b runs \acommand\a in a mode that takes input from
+ the \afile\a operands, or from the standard input if no \afile\a
+ operands are specified, and writes the results to the standard output.
+ It can be used to run commands like \bsplit\b(1), that normally modify
+ \afile\a operands in-place, in pipelines. The \afile\a operands are
+ not modified; \acommand\a is run on copies in \b/tmp\b.]
+
+command [ option ... ] [ file ... ]
+
+[+SEE ALSO?\bstrip\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="command [ option ... ] [ file ... ]"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ *) usage ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+case $# in
+0) usage ;;
+esac
+
+cmd=$1
+while :
+do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -*) cmd="$cmd $1" ;;
+ *) break ;;
+ esac
+done
+trap 'rm -f $tmp$suf' 0 1 2 3 15
+case $# in
+0) cat > $tmp
+ $cmd $tmp
+ ;;
+*) for file
+ do suf=${file##*/}
+ case $suf in
+ *.*) suf=.${suf#*.} ;;
+ *) suf= ;;
+ esac
+ cp $file $tmp$suf || exit 1
+ chmod u+rwx $tmp$suf || exit 1
+ $cmd $tmp$suf || exit 1
+ cat $tmp$suf
+ rm -f $tmp$suf
+ done
+ ;;
+esac
diff --git a/src/cmd/INIT/gdbm.c b/src/cmd/INIT/gdbm.c
new file mode 100644
index 0000000..cc0a9f6
--- /dev/null
+++ b/src/cmd/INIT/gdbm.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lgdbm
+ */
+
+#define _hdr_gdbm_ndbm 1
+
+#if _hdr_gdbm_ndbm
+#include <gdbm/ndbm.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/gdbm1.c b/src/cmd/INIT/gdbm1.c
new file mode 100644
index 0000000..6ad2071
--- /dev/null
+++ b/src/cmd/INIT/gdbm1.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lgdbm
+ */
+
+#define _hdr_gdbm_ndbm 1
+
+#if _hdr_gdbm_ndbm
+#include <gdbm-ndbm.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/gdbm2.c b/src/cmd/INIT/gdbm2.c
new file mode 100644
index 0000000..1b9a48f
--- /dev/null
+++ b/src/cmd/INIT/gdbm2.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lgdbm
+ */
+
+#define _hdr_ndbm 1
+
+#if _hdr_ndbm
+#include <ndbm.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/hello.c b/src/cmd/INIT/hello.c
new file mode 100755
index 0000000..2a8e2d1
--- /dev/null
+++ b/src/cmd/INIT/hello.c
@@ -0,0 +1,23 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef printf
+#include <stdio.h>
+#endif
+int main() { int new = 0; printf("hello world\n"); return new;}
diff --git a/src/cmd/INIT/hosttype.tst b/src/cmd/INIT/hosttype.tst
new file mode 100644
index 0000000..7a64588
--- /dev/null
+++ b/src/cmd/INIT/hosttype.tst
@@ -0,0 +1,6 @@
+hp.pa hostname 9000/730 hp9000s700 HP-UX hostname A.09.01 A
+linux-aout.i386 hostname i586 i386 linux hostname 1.1.59 #1
+sgi.mips2 hostname.domain IP22 mips IRIX hostname 5.2 02282016
+osf.alpha hostname.domain alpha alpha OSF1 hostname.domain V3.2 62
+sun4 hostname.domain sun4 sparc SunOS hostname.domain 4.1.1 1 sun4c
+sol.sun4 hostname.domain sun4 sparc SunOS hostname.domain 5.4 Generic_101945-13
diff --git a/src/cmd/INIT/hurl.sh b/src/cmd/INIT/hurl.sh
new file mode 100644
index 0000000..60e8a6b
--- /dev/null
+++ b/src/cmd/INIT/hurl.sh
@@ -0,0 +1,207 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: copy http url data
+
+command=hurl
+agent="$command/2009-01-20 (AT&T Research)"
+authorize=
+verbose=0
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: hurl (AT&T Research) 2009-01-20 $
+]
+'$USAGE_LICENSE$'
+[+NAME?hurl - copy http url data]
+[+DESCRIPTION?\bhurl\b copies the data for the \bhttp\b \aurl\a operand
+ to the standard output. The \aurl\a must be of the form
+ \b[http://]]\b\ahost\a[\b:\b\aport\a]]\b/\b\apath\a. The default
+ \aport\a is \b80\b.]
+[+?\bhurl\b is a shell script that attempts to access the \aurl\a by
+ these methods:]{
+ [+/dev/tcp/\ahost\a\b/80\b?Supported by \bksh\b(1) and recent
+ \bbash\b(1).]
+ [+wget -nv -O - \aurl\a?]
+ [+lynx -source \aurl\a?]
+ [+curl -s -L -o - \aurl\a?]
+}
+[a:authorize?The url authorization user name and password, separated
+ by \b:\b (one colon character.)]:[user::password]
+[s:size?Terminate the data transmission after \abytes\a have been
+ transferred.]:[bytes]
+[v:verbose?Verbose trace.]
+
+url
+
+[+SEE ALSO?\bcurl\b(1), \blynx\b(1), \bwget\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="a:v"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+integer limit=0 total=0 block=8*1024
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ a) authorize=$OPTARG ;;
+ s) limit=$OPTARG ;;
+ v) verbose=1 ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+url=$1
+AUTHORIZE=
+
+exec 9<&0
+
+while :
+do test 0 != $verbose && echo "$command: url=$url" >&2
+ case $url in
+ *://*/*)prot=${url%%:*}
+ url=${url#*://}
+ ;;
+ *) prot=http
+ ;;
+ esac
+ host=$url
+ path=/${host#*/}
+ host=${host%%/*}
+ case $host in
+ *:+([0-9]))
+ port=${host##*:}
+ host=${host%:*}
+ ;;
+ *) port=80
+ ;;
+ esac
+ test 0 != $verbose && echo "$command: prot=$prot host=$host port=$port path=$path" >&2
+ case $prot in
+ http) if (eval "exec >" || exit 0) 2>/dev/null &&
+ eval "exec 8<> /dev/tcp/\$host/$port" 2>/dev/null
+ then test 0 != $verbose && echo "$command: using /dev/tcp/$host/$port" >&2
+ if ! echo "GET $path HTTP/1.0
+Host: $host
+User-Agent: $agent ${AUTHORIZE}
+ " >&8
+ then echo "$command: $host: write error"
+ exit 1
+ fi
+ {
+ if ! read prot code text
+ then echo "$command: $host: read error" >&2
+ exit 1
+ fi
+ code=${code%:*}
+ type=Basic
+ realm=access
+ test 0 != $verbose && echo "$command: prot=$prot code=$code $text" >&2
+ while :
+ do if ! read head data
+ then echo "$command: $host: read error" >&2
+ exit 1
+ fi
+ test 0 != $verbose && echo "$command: head=$head $data" >&2
+ case $head in
+ Location:)
+ case $code in
+ 30[123])url=$data
+ continue 2
+ ;;
+ esac
+ ;;
+ WWW-Authenticate:)
+ set -- $data
+ type=$1
+ shift
+ eval "$@"
+ realm=${realm%$'\r'}
+ ;;
+ ''|?) break
+ ;;
+ esac
+ done
+ case $code in
+ 200) if (( limit ))
+ then (( limit = (limit + block - 1) / block))
+ dd bs=$block count=$limit silent=1
+ else cat
+ fi
+ exit
+ ;;
+ 401) {
+ if [[ $AUTHORIZE || $type != Basic ]]
+ then print authorization failed
+ exit 1
+ fi
+ if [[ ! $authorize ]]
+ then if [[ ! -t 0 ]]
+ then print authorization failed
+ exit 1
+ fi
+ print -n "Enter user name for $realm: "
+ read -u9 user
+ print -n "Password: "
+ trap 'stty echo <&9' 0 1 2 3 15
+ stty -echo
+ read password
+ stty echo
+ print
+ trap - 0 1 2 3 15
+ authorize=$user:$password
+ fi
+ AUTHORIZE=$'\nAuthorization: '$type' '$(print -n -r -- "$authorize" | uuencode -h -x base64)$'\r'
+ } <&9 >&2
+ continue 2
+ ;;
+ *) echo "$0: $url: $code: $text" >&2
+ exit 1
+ ;;
+ esac
+ } <&8
+ elif wget ${authorize:+--http-user="${authorize%:*}"} ${password:+--http-passwd="${password##*:}"} -nv -O - $url 2>/dev/null
+ then test 0 != $verbose && echo "$command: using wget" >&2
+ exit
+ elif lynx ${authorize:+-auth "$authorize"} -source $url 2>/dev/null
+ then test 0 != $verbose && echo "$command: using wget" >&2
+ exit
+ elif curl ${authorize:+-u "$authorize"} -s -L -o - $url 2>/dev/null
+ then test 0 != $verbose && echo "$command: using curl" >&2
+ exit
+ else echo "$command: $url: { /dev/tcp/$host/$port wget curl } failed" >&2
+ exit 1
+ fi
+ ;;
+ *) echo "$command: $prot: protocol not supported" >&2
+ exit 1
+ ;;
+ esac
+done
diff --git a/src/cmd/INIT/iconv.c b/src/cmd/INIT/iconv.c
new file mode 100644
index 0000000..64f2797
--- /dev/null
+++ b/src/cmd/INIT/iconv.c
@@ -0,0 +1,29 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef iconv
+#include <iconv.h>
+#endif
+
+int
+main()
+{
+ iconv(0, 0, 0, 0, 0);
+ return 0;
+}
diff --git a/src/cmd/INIT/iffe.sh b/src/cmd/INIT/iffe.sh
new file mode 100644
index 0000000..cfd216c
--- /dev/null
+++ b/src/cmd/INIT/iffe.sh
@@ -0,0 +1,4639 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+# Glenn Fowler & Phong Vo
+# AT&T Research
+#
+# test if feature exists
+# this script is written to make it through all sh variants
+#
+# NOTE: .exe a.out suffix and [\\/] in path patterns for dos/nt
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+command=iffe
+version=2012-02-23 # update in USAGE too #
+
+compile() # $cc ...
+{
+ "$@" 2>$tmp.err
+ _compile_status=$?
+ if test -s $tmp.err
+ then cat $tmp.err >&2
+ case $_compile_status in
+ [1-9]|[1-9][0-9]|1[01][0-9]|12[0-7])
+ if egrep -i -c 'terminated with signal|core dump|segmentation fault' $tmp.err >&$nullout
+ then _compile_status=139
+ fi
+ ;;
+ esac
+ fi
+ case $_compile_status in
+ ?|??|1[01]?|12[0-8]|25?)
+ ;;
+ *) echo "$command: $@" >&$stderr
+ cat $tmp.err >&$stderr
+ echo "$command: $1: core dump or fatal interruption -- results inconclusive" >&$stderr
+ exit $_compile_status
+ ;;
+ esac
+ return $_compile_status
+}
+
+is_hdr() # [ - ] [ file.c ] hdr
+{
+ case $1 in
+ -) _is_hdr_flag=-; shift ;;
+ *) _is_hdr_flag= ;;
+ esac
+ case $1 in
+ *.c) _is_hdr_file=$1; shift ;;
+ *) _is_hdr_file=$tmp.c ;;
+ esac
+ is hdr $1
+ compile $cc -c $_is_hdr_file <&$nullin >&$nullout 2>$tmp.e
+ _is_hdr_status=$?
+ case $_is_hdr_status in
+ 0) if test -s $tmp.e
+ then case `grep '#.*error' $tmp.e` in
+ ?*) _is_hdr_status=1 ;;
+ esac
+ fi
+ ;;
+ esac
+ case $_is_hdr_status in
+ 0) success $_is_hdr_flag
+ ;;
+ *) case $debug in
+ 3) cat $tmp.e >&$stderr ;;
+ esac
+ failure $_is_hdr_flag
+ ;;
+ esac
+ return $_is_hdr_status
+}
+
+pkg() # package
+{
+ case $1 in
+ '') pth=`getconf PATH 2>/dev/null`
+ case $pth in
+ '') pth="/bin /usr/bin" ;;
+ *:*) pth=`echo "$pth" | sed 's/:/ /g'` ;;
+ esac
+ return
+ ;;
+ '<') shift
+ ;;
+ *) return
+ ;;
+ esac
+ case $1 in
+ X|X11*) i="openwin"
+ case $1 in
+ X) set X11 ;;
+ esac
+ case $1 in
+ X11) case $# in
+ 1) set $1 6 5 4 ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) i=
+ ;;
+ esac
+ pth="{ usr . - . contrib local $i - . share - . lib - $1"
+ i=$1
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ '>') shift; break ;;
+ esac
+ pth="$pth ${i}R$1 ${i}.$1"
+ done
+ pth="$pth . } $*"
+}
+
+is() # op name
+{
+ case $verbose in
+ 1) case $complete in
+ 1) failure ;;
+ esac
+ oo=$1
+ shift
+ case $1 in
+ ?*) yy=is
+ ii=$1
+ complete=1
+ case $oo in
+ cmd) mm="a command" ;;
+ dat) mm="a library data symbol" ;;
+ dfn) mm="a macro with extractable value" ;;
+ exp) mm="true" ;;
+ hdr) mm="a header" ;;
+ id) mm="an identifier" ;;
+ lcl) mm="a native header" ;;
+ key) mm="a reserved keyword" ;;
+ lib) mm="a library function" ;;
+ LIB) case $2 in
+ "") mm="a library" ;;
+ *) ii=$*; mm="a library group" ;;
+ esac
+ ;;
+ mac) mm="a macro" ;;
+ mem) mm="a member of $2" ;;
+ mth) mm="a math library symbol" ;;
+ nos) mm="a non-opaque struct" ;;
+ npt) mm="a symbol that needs a prototype" ;;
+ num) mm="a numeric constant or enum" ;;
+ nxt) mm="an include path for the native header" ;;
+ opt) mm="set in \$PACKAGE_OPTIONS" ;;
+ pth) mm="a file" ;;
+ run) yy="capture output of" mm= ;;
+ siz) mm="a type with known size" ;;
+ sym) mm="a typed variable" ;;
+ sys) mm="a system header" ;;
+ typ) mm="a type or typedef" ;;
+ val) yy="determine" mm="value" ;;
+ *) yy= mm= ;;
+ esac
+ case $ii in
+ [abcdefghijklmnopqrstuvwxyz]*[abcdefghijklmnopqrstuvwxyz]'{') ii="$ii ... }end" ;;
+ esac
+ $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr
+ complete=1
+ ;;
+ esac
+ ;;
+ esac
+}
+
+success()
+{
+ case $1 in
+ -) shift
+ ;;
+ *) case $result in
+ UNKNOWN) result=SUCCESS ;;
+ esac
+ case $1 in
+ +) return ;;
+ esac
+ ;;
+ esac
+ case $complete:$verbose in
+ 1:1) case $suspended in
+ 1) suspended=0
+ $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr
+ ;;
+ esac
+ complete=0
+ case $# in
+ 0) mm="yes" ;;
+ *) mm="'$*'" ;;
+ esac
+ case $debug in
+ 0) echo " $mm" >&$stderr ;;
+ *) echo "$command: ... $mm" >&$stderr ;;
+ esac
+ ;;
+ esac
+}
+
+failure()
+{
+ case $1 in
+ -) shift ;;
+ *) result=FAILURE
+ case $1 in
+ +) return ;;
+ esac
+ ;;
+ esac
+ case $complete:$verbose in
+ 1:1) case $suspended in
+ 1) suspended=0
+ $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr
+ ;;
+ esac
+ complete=0
+ case $group in
+ '') case $# in
+ 0) mm="no" ;;
+ *) mm=$* ;;
+ esac
+ ;;
+ *) mm=
+ ;;
+ esac
+ case $debug in
+ 0) echo " $mm" >&$stderr ;;
+ *) echo "$command: ... $mm" >&$stderr ;;
+ esac
+ ;;
+ esac
+}
+
+# report
+#
+# - ignore global status
+# -0 normal sense
+# -1 inverted sense if ! def
+# status test status 0:success *:failure
+# success success comment
+# failure failure comment
+# default default setting comment
+#
+# globals
+#
+# $not invert test sense
+# $M test variable
+# $m test macro
+# $v default macro
+
+report() # [-] [-0] [-1] status value success failure default
+{
+ case $1 in
+ -) _report_ignore=$1
+ shift
+ ;;
+ *) _report_ignore=
+ ;;
+ esac
+ _report_not=$not
+ case $1 in
+ -0) shift
+ ;;
+ -1) shift
+ case $def in
+ ''|-) case $_report_not in
+ 1) _report_not= ;;
+ *) _report_not=1 ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ _report_status=$1
+ case $_report_ignore:$_report_status in
+ -:*) ;;
+ *:0) success $_report_ignore
+ ;;
+ *) failure $_report_ignore
+ case $group in
+ ?*) return ;;
+ esac
+ ;;
+ esac
+ _report_value=$2
+ case $_report_not in
+ 1) case $_report_status in
+ 0) _report_status=1 ;;
+ *) _report_status=0 ;;
+ esac
+ _report_success=$4
+ _report_failure=$3
+ ;;
+ *) _report_success=$3
+ _report_failure=$4
+ ;;
+ esac
+ _report_default=$5
+ case $_report_status in
+ 0) case $M in
+ *-*) ;;
+ *) usr="$usr$nl#define $m $_report_value"
+ case $_report_success in
+ ''|-) ;;
+ *) case $define in
+ 1) echo "#define $m $_report_value /* $_report_success */" ;;
+ n) echo "$m=$_report_value"
+ esac
+ ;;
+ esac
+ eval $m=\'$_report_value\'
+ ;;
+ esac
+ ;;
+ *) case $M in
+ *-*) ;;
+ *) case $_report_failure in
+ ''|-) ;;
+ *) case $define$all$config$undef in
+ 1?1?|1??1)echo "#undef $m /* $_report_failure */" ;;
+ 11??) echo "#define $m 0 /* $_report_failure */" ;;
+ n1?1) echo "$m=" ;;
+ n1??) echo "$m=0" ;;
+ esac
+ ;;
+ esac
+ case $_report_default in
+ ''|-) ;;
+ *) case $define$set in
+ 1?*) echo "#define $v $set /* $_report_default */" ;;
+ n?*) echo "$v=$set" ;;
+ esac
+ ;;
+ esac
+ eval $m=0
+ ;;
+ esac
+ ;;
+ esac
+}
+
+noisy()
+{
+ case $complete:$verbose in
+ 1:1) suspended=1
+ echo >&$stderr
+ ;;
+ esac
+}
+
+here_broken=0
+
+literal() # line that echo might process
+{
+ if cat <<!
+$*
+!
+ then : old here doc botch not present
+ else case $here_broken in
+ 0) here_broken=1
+ echo "$command: your shell botches here documents; this was fixed back in the 80's" >&$stderr
+ ;;
+ esac
+ sh -c "cat <<!
+$*
+!
+"
+ fi
+}
+
+copy() # "output-file" "data-that-must-not-be-processed-by-echo"
+{
+ case $1 in
+ -) case $shell in
+ ksh) print -r - "$2"
+ ;;
+ *) if cat <<!
+$2
+!
+ then : ancient here doc botch not present
+ else case $here_broken in
+ 0) here_broken=1
+ echo "$command: your shell botches here documents; this was fixed back in the 80's" >&$stderr
+ ;;
+ esac
+ sh -c "cat <<!
+$2
+!
+"
+ fi
+ ;;
+ esac
+ ;;
+ *) case $shell in
+ ksh) print -r - "$2" > "$1"
+ ;;
+ *) if cat > "$1" <<!
+$2
+!
+ then : ancient here doc botch not present
+ else case $here_broken in
+ 0) here_broken=1
+ echo "$command: your shell botches here documents; this was fixed back in the 80's" >&$stderr
+ ;;
+ esac
+ sh -c "cat > \"$1\" <<!
+$2
+!
+"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# verify that cc is a C compiler
+
+checkcc()
+{
+ # check for local package root directories
+
+ case $PACKAGE_PATH in
+ ?*) for i in `echo $PACKAGE_PATH | sed 's,:, ,g'`
+ do if test -d $i/include
+ then cc="$cc -I$i/include"
+ occ="$occ -I$i/include"
+ fi
+ if test -d $i/lib
+ then cc="$cc -L$i/lib"
+ occ="$occ -L$i/lib"
+ for y in $libpaths
+ do eval $y=\"\$$y:\$i/lib\$${y}_default\"
+ eval export $y
+ done
+ fi
+ done
+ ;;
+ esac
+ echo "int i = 1;" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then echo "(;" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then cctest="should not compile '(;'"
+ fi
+ else cctest="should compile 'int i = 1;'"
+ fi
+ case $cctest in
+ "") cctest=0
+ ;;
+ *) echo "$command: $cc: not a C compiler: $cctest" >&$stderr
+ exit 1
+ ;;
+ esac
+}
+
+checkread()
+{
+ case $cctest in
+ "") checkcc ;;
+ esac
+ case $posix_read in
+ -no) ;;
+ *) posix_read=`(read -r _checkread_line; echo $_checkread_line) 2>/dev/null <<!
+a z
+!
+`
+ ;;
+ esac
+ case $posix_read in
+ "a z") posix_read=1
+ ;;
+ *) copy ${tmp}r.c "
+ extern int read();
+ extern int write();
+ int main()
+ {
+ char c;
+ char r;
+ int k;
+ char s[32];
+ k = 0;
+ while (read(0, &c, 1) == 1)
+ {
+ if (k >= 0)
+ {
+ if (c == ' ' || c == '\\t')
+ {
+ if (k < sizeof(s))
+ s[k++] = c;
+ continue;
+ }
+ if (k > 1 && c != '#' && c != '\\n' && c != '\\r')
+ write(1, s + 1, k - 1);
+ k = -1;
+ }
+ if (c == '\\r')
+ {
+ r = c;
+ if (read(0, &c, 1) == 1 && c != '\\n')
+ write(1, &r, 1);
+ }
+ write(1, &c, 1);
+ if (c == '\\n')
+ return 0;
+ }
+ return 1;
+ }"
+ if compile $cc -o ${tmp}r.exe ${tmp}r.c >&$nullout
+ then posix_read=${tmp}r.exe
+ else echo "$command: cannot compile read -r workaround" >&$stderr
+ exit 1
+ fi
+ ;;
+ esac
+}
+
+execute()
+{
+ if test "" != "$cross"
+ then crossexec $cross "$@"
+ _execute_=$?
+ elif test -d /NextDeveloper
+ then "$@" <&$nullin >&$nullout
+ _execute_=$?
+ "$@" <&$nullin | cat
+ else "$@"
+ _execute_=$?
+ fi
+ return $_execute_
+}
+
+exclude()
+{
+ case $excludes in
+ '') return 0 ;;
+ esac
+ for _exclude_var
+ do eval _exclude_old=\$$_exclude_var
+ case $_exclude_old in
+ *" -I"*);;
+ *) continue ;;
+ esac
+ _exclude_new=
+ _exclude_sep=
+ for _exclude_arg in $_exclude_old
+ do _exclude_skip=
+ for _exclude_dir in $excludes
+ do case $_exclude_arg in
+ -I$_exclude_dir|-I*/$_exclude_dir)
+ _exclude_skip=1
+ break;
+ ;;
+ esac
+ done
+ case $_exclude_skip in
+ '') _exclude_new="$_exclude_new$_exclude_sep$_exclude_arg"
+ _exclude_sep=" "
+ ;;
+ esac
+ done
+ eval $_exclude_var=\$_exclude_new
+ case $debug in
+ 0) ;;
+ *) echo $command: exclude $_exclude_var: "$_exclude_old => $_exclude_new" >&$stderr
+ ;;
+ esac
+ done
+}
+
+all=0
+apis=
+binding="-dy -dn -Bdynamic -Bstatic -Wl,-ashared -Wl,-aarchive -call_shared -non_shared '' -static"
+complete=0
+config=0
+defhdr=
+define=1
+explicit=0
+iff=
+usr=
+cross=
+debug=0
+deflib=
+dir=FEATURE
+excludes=
+executable="test -x"
+exists="test -e"
+gothdr=
+gotlib=
+idno=
+idyes=
+ifs=${IFS-'
+ '}
+in=
+includes=
+intrinsic=
+libpaths="LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARY64_PATH LIBPATH SHLIB_PATH"
+ LD_LIBRARY_PATH_default=:/lib:/usr/lib
+ LD_LIBRARYN32_PATH_default=:/lib32:/usr/lib32
+ LD_LIBRARY64_PATH_default=:/lib64:/usr/lib64
+ LIBPATH_default=:/lib:/usr/lib
+ SHLIB_PATH_default=:/shlib:/usr/shlib:/lib:/usr/lib
+nl="
+"
+optimize=1
+occ=cc
+one=
+out=
+posix_read=-check
+case `(set -f && set x * && echo $# && set +f) 2>/dev/null` in
+2) posix_noglob="set -f" posix_glob="set +f" ;;
+*) case `(set -F && set x * && echo $# && set +F) 2>/dev/null` in
+ 2) posix_noglob="set -F" posix_glob="set +F" ;;
+ *) posix_noglob=":" posix_glob=":" ;;
+ esac
+ ;;
+esac
+protoflags=
+puthdr=
+putlib=
+pragma=
+case $RANDOM in
+$RANDOM)shell=bsh
+ ($executable .) 2>/dev/null || executable='test -r'
+ ($exists .) 2>/dev/null || exists='test -r'
+ ;;
+*) case $BASH_VERSION in
+ ?*) shell=bash ;;
+ *) shell=ksh ;;
+ esac
+ ;;
+esac
+reallystatic=
+reallystatictest=
+regress=
+static=.
+statictest=
+case $COTEMP in
+"") case $HOSTNAME in
+ ""|?|??|???|????|????)
+ tmp=${HOSTNAME}
+ ;;
+ *) case $shell in
+ bsh) eval `echo $HOSTNAME | sed 's/\\(....\\).*/tmp=\\1/'` ;;
+ *) eval 'tmp=${HOSTNAME%${HOSTNAME#????}}' ;;
+ esac
+ ;;
+ esac
+ tmp=${tmp}$$
+ ;;
+*) tmp=x${COTEMP}
+ ;;
+esac
+COTEMP=${tmp}
+export COTEMP
+case $tmp in
+./*) ;;
+??????????*)
+ case $shell in
+ bsh) eval `echo $tmp | sed 's/\\(.........\\).*/tmp=\\1/'` ;;
+ *) eval 'tmp=${tmp%${tmp#?????????}}' ;;
+ esac
+ ;;
+?????????)
+ ;;
+????????)
+ tmp=F$tmp
+ ;;
+esac
+case $tmp in
+./*) ;;
+*) tmp=./$tmp ;;
+esac
+undef=0
+verbose=0
+vers=
+
+# options -- `-' for output to stdout otherwise usage
+
+case $1 in
+-) out=-; shift ;;
+esac
+set=
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: iffe (AT&T Research) 2012-02-23 $
+]
+'$USAGE_LICENSE$'
+[+NAME?iffe - C compilation environment feature probe]
+[+DESCRIPTION?\biffe\b is a command interpreter that probes the C
+ compilation environment for features. A feature is any file, option
+ or symbol that controls or is controlled by the C compiler. \biffe\b
+ tests features by generating and compiling C programs and observing
+ the behavior of the C compiler and generated programs.]
+[+?\biffe\b statements are line oriented. Statements may appear in the
+ operand list with the \b:\b operand or \bnewline\b as the line
+ delimiter. The standard input is read if there are no command
+ line statements or if \afile\a\b.iffe\b is omitted.]
+[+?Though similar in concept to \bautoconf\b(1) and \bconfig\b(1), there
+ are fundamental differences. The latter tend to generate global
+ headers accessed by all components in a package, whereas \biffe\b is
+ aimed at localized, self contained feature testing.]
+[+?Output is generated in \bFEATURE/\b\atest\a by default, where \atest\a is
+ the base name of \afile\a\b.iffe\b or the \biffe\b \brun\b
+ file operand. Output is first generated in a temporary file; the
+ output file is updated if it does not exist or if the temporary file
+ is different. If the first operand is \b-\b then the output is written
+ to the standard output and no update checks are done.]
+[+?Files with suffixes \b.iffe\b and \b.iff\b are assumed to contain
+ \biffe\b statements.]
+[a:all?Define failed test macros \b0\b. By default only successful test macros
+ are defined \b1\b.]
+[c:cc?Sets the C compiler name and flags to be used in the feature
+ tests.]:[C-compiler-name [C-compiler-flags ...]]]
+[C:config?Generate \bconfig\b(1) style \aHAVE_\a* macro names. This implies
+ \b--undef\b. Since \bconfig\b(1) has inconsistent naming conventions,
+ the \bexp\b op may be needed to translate from the (consistent)
+ \biffe\b names. Unless otherwise noted a \bconfig\b macro name
+ is the \biffe\b macro name prefixed with \bHAVE\b and converted to
+ upper case. \b--config\b is set by default if the command arguments
+ contain a \brun\b op on an input file with the base name \bconfig\b.]
+[d:debug?Sets the debug level. Level 0 inhibits most
+ error messages, level 1 shows compiler messages, and
+ level 2 traces internal \biffe\b \bsh\b(1) actions and does
+ not remove core dumps on exit.]#[level]
+[D:define?Successful test macro definitions are emitted. This is the default.]
+[E:explicit?Disable implicit test output.]
+[F:features?Sets the feature test header to \ahdr\a. This header typically
+ defines *_SOURCE feature test macros.]:[hdr:=NONE]
+[i:input?Sets the input file name to \afile\a, which
+ must contain \biffe\b statements.]:[file]
+[I:include?Adds \b-I\b\adir\a to the C compiler flags.]:[dir]
+[L:library?Adds \b-L\b\adir\a to the C compiler flags.]:[dir]
+[n:name-value?Output \aname\a=\avalue\a assignments only.]
+[N!:optimize?\b--nooptimize\b disables compiler optimization options.]
+[o:output?Sets the output file name to \afile\a.]:[file]
+[O:stdio?Sets the standard io header to \ahdr\a.]:[hdr:=stdio.h]
+[e:package?Sets the \bproto\b(1) package name to \aname\a.]:[name]
+[p:prototyped?Emits \b#pragma prototyped\b at the top of the
+ output file. See \bproto\b(1).]
+[P:pragma?Emits \b#pragma\b \atext\a at the top of the output file.]:[text]
+[r:regress?Massage output for regression testing.]
+[s:shell?Sets the internal shell name to \aname\a. Used for debugging
+ Bourne shell compatibility (otherwise \biffe\b uses \aksh\a constructs
+ if available). The supported names are \bksh\b, \bbsh\b, \bbash\b, and
+ \bosh\b. \bosh\b forces the \bread -r\b compatibility read command to
+ be compiled and used instead of \bread -r\b. The default is determined
+ by probing the shell at startup.]:[name]
+[S:static?Sets the C compiler flags that force static linking. If not set
+ then \biffe\b probes the compiler to determine the flags. \biffe\b
+ must use static linking (no dlls) because on some systems missing
+ library symbols are only detected when referenced at runtime from
+ dynamically linked executables.]:[flags]
+[u:undef?\b#undef\b failed test macros. By default only successful test macros
+ are defined \b1\b.]
+[v:verbose?Produce a message line on the standard error for each test as
+ it is performed.]
+[x:cross?Some tests compile an executable (\ba.out\b) and then run it.
+ If the C compiler is a cross compiler and the executable format is
+ incompatible with the execution environment then the generated
+ executables must be run in a different environment, possibly on
+ another host. \acrosstype\a is the HOSTTYPE for generated executables
+ (the \bpackage\b(1) command generates a consistent HOSTTYPE namespace).
+ Generated executables are run via \bcrossexec\b(1) with \acrosstype\a
+ as the first argument. \bcrossexec\b supports remote execution for
+ cross-compiled executables. See \bcrossexec\b(1) for
+ details.]:[crosstype]
+[X:exclude?Removes \b-I\b\adir\a and \b-I\b*/\adir\a C compiler flags.]:[dir]
+
+[ - ] [ file.iffe | statement [ : statement ... ] ]
+
+[+SYNTAX?\biffe\b input consists of a sequence of statement lines. Statements
+ that span more than one line contain \abegin\a\b{\b as the last
+ operand (where \abegin\a is command specific) and zero
+ or more data lines terminated by a line containing
+ \b}end\b as the first operand. The statement syntax is:
+ [\aname\a \b=\b]] [\b!\b]] \atest\a[,\atest\a...]] [\b-\b]]
+ [\aarg\a[,\aarg\a...]]]] [\aprereq\a ...]]
+ [\abegin\a{ ... |\bend\b ...]] [= [\adefault\a]]]].
+ \atest\as and \aarg\as may be combined, separated by commas, to perform
+ a set of tests on a set of arguments. \aname\a \b=\b before \atest\a
+ overrides the default test variable and macro name, and \b-\b after
+ \atest\a performs the test but does not define the test variable and
+ macro values. \b!\b before \atest\a inverts the test sense for \bif\b,
+ \belif\b, and \byes{\b and \bno{\b blocks.]
+[+?\aprereq\as are used when applying the features tests and may be
+ combinations of:]{
+ [+compiler options?\b-D\b*, \b-L\b*, etc.]
+ [+library references?\b-l\b*, *\b.a\b, etc. \b_LIB_\b\aname\a
+ is defined to be 1 if \b-l\b\aname\a is a library.]
+ [+header references?*\b.h\b. \a_dir_name\a is defined to be 1
+ if \adir/name\a\b.h\b is a header, or if \adir\a is
+ omitted, \b_hdr_\b\aname\a is defined to be 1 if
+ \aname\a\b.h\b is a header.]
+ [+-?Prereq grouping mark; prereqs before the first \b-\b are
+ passed to all feature tests. Subsequent groups
+ are attempted in left-to-right order until the first
+ successful group is found.]
+ }
+[+?\abegin\a\b{\b ... \b}end\b delimit multiline code blocks that override
+ or augment the default code provided by \biffe\b. User supplied code
+ blocks should be compatible with the K&R, ANSI, and C++ C language
+ dialects for maximal portability. In addition to all macro definitions
+ generated by previous tests, all generated code contains the
+ following at the top to hide dialect differences:]{
+ [+ ?#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)]
+ [+ ?#define _STD_ 1]
+ [+ ?#define _ARG_(x) x]
+ [+ ?#define _VOID_ void]
+ [+ ?#else]
+ [+ ?#define _STD_ 0]
+ [+ ?#define _ARG_(x) ()]
+ [+ ?#define _VOID_ char]
+ [+ ?#endif]
+ [+ ?#if defined(__cplusplus)]
+ [+ ?#define _BEGIN_EXTERNS_ extern "C" {]
+ [+ ?#define _END_EXTERNS_ }]
+ [+ ?#else]
+ [+ ?#define _BEGIN_EXTERNS_]
+ [+ ?#define _END_EXTERNS_]
+ [+ ?#endif]
+ [+ ?#define _NIL_(x) ((x)0)]
+ [+ ?#include <stdio.h>]
+ }
+[+?= \adefault\a may be specified for the \bkey\b, \blib\b, \bmac\b, \bmth\b
+ and \btyp\b tests. If the test fails for \aarg\a then
+ \b#define\b \aarg\a \adefault\a is emitted. \bkey\b accepts multiple
+ \b= \b\adefault\a values; the first valid one is used.]
+[+?Each test statement generates a portion of a C language header that contains
+ macro defintions, comments, and other text corresponding to the feature
+ tests. \b#ifndef _def_\b\aname\a\b_\b\adirectory\a ...
+ \b#endif\b guards the generated header from multiple \b#include\bs,
+ where \aname\a is determined by either the \brun\b statement input file
+ name if any, or the first \atest\a in the first statement, and \adirectory\a
+ is the basename component of either the \brun\b statement file, if any,
+ or the current working directory. The output file name is determined
+ in this order:]{
+ [+-?If the first command line operand is \b-\b then the output
+ is written to the standard output.]
+ [+--output=\afile\a?Output is \afile\a.]
+ [+set out \afile\a?Output is \afile\a.]
+ [+[run]] [\adirectory\a/]]\abase\a[\a.suffix\a]]?Output is
+ \bFEATURE/\b\abase\a.]
+ }
+[+?Generated \biffe\b headers are often referenced in C source as:
+ \b#include "FEATURE/\b\afile\a". The \bnmake\b(1) base rules contain
+ metarules for generating \bFEATURE/\b\afile\a from
+ \bfeatures/\b\afile\a[\asuffix\a]], where \asuffix\a may be omitted,
+ \b.c\b, or \b.sh\b (see the \brun\b test below). Because
+ \b#include\b prerequisites are automatically detected, \bnmake\b(1)
+ ensures that all prerequisite \biffe\b headers are generated before
+ compilation. Note that the directories are deliberately named
+ \bFEATURE\b and \bfeatures\b to keep case-ignorant file systems
+ happy.]
+[+?The feature tests are:]{
+ [+# \acomment\a?Comment line - ignored.]
+ [+api \aname\a \aYYYYMMDD\a \asymbol ...\a?Emit api compatibility tests
+ for \aname\a and \b#define\b \asymbol\a \asymbol\a_\aYYYYMMDD\a
+ when \aNAME\a_API is >= \aYYYYMMDD\a (\aNAME\a is \aname\a
+ converted to upper case). If \aNAME\a_API is not defined
+ then \asymbol\a maps to the newest \aYYYYMMDD\a for \aname\a.]
+ [+define \aname\a [ (\aarg,...\a) ]] [ \avalue\a ]]?Emit a macro
+ \b#define\b for \aname\a if it is not already defined. The
+ definition is passed to subsequent tests.]
+ [+extern \aname\a \atype\a [ (\aarg,...\a) | [\adimension\a]] ]]?Emit
+ an \bextern\b prototype for \aname\a if one is not already
+ defined. The prototype is passed to subsequent tests.]
+ [+header \aheader\a?Emit \b#include <\b\aheader\a\b>\b if \aheader\a
+ exists. The \b#include\b is passed to subsequent tests.]
+ [+print \atext\a?Copy \atext\a to the output file. \atext\a is passed
+ to subsequent tests.]
+ [+reference \aheader\a?If \aheader\a exists then add \b#include\b
+ \aheader\a to subsequent tests.]
+ [+ver \aname\a \aYYYYMMDD\a?\b#define\b \aNAME\a_VERSION \aYYYYMMDD\a
+ (\aNAME\a is \aname\a converted to upper case).]
+ [+cmd \aname\a?Defines \b_cmd_\b\aname\a if \aname\a is an executable
+ in one of the standard system directories (\b/bin, /etc,
+ /usr/bin, /usr/etc, /usr/ucb\b).
+ \b_\b\adirectory\a\b_\b\aname\a is defined for \adirectory\a
+ in which \aname\a is found (with \b/\b translated to \b_\b).]
+ [+dat \aname\a?Defines \b_dat_\b\aname\a if \aname\a is a data symbol
+ in the default libraries.]
+ [+def \aname\a?Equivalent to \bcmd,dat,hdr,key,lib,mth,sys,typ\b
+ \aname\a.]
+ [+dfn \aname\a?If \aname\a is a macro in the candidate headers then
+ a \b#define\b \aname\a \avalue\a statment is output for the
+ \avalue\a defined in the headers. The definition is \b#ifndef\b
+ guarded.]
+ [+exp \aname\a \aexpression\a?If \aexpression\a is a \"...\" string
+ then \aname\a is defined to be the string, else if the
+ \bexpr\b(1) evaluation of \aexpression\a is not 0 then \aname\a
+ is defined to be 1, otherwise \aname\a is defined to be 0.
+ Identifiers in \aexpression\a may be previously defined names
+ from other \biffe\b tests; undefined names evaluate to 0.
+ If \aname\a was defined in a previous successful test then
+ the current and subsequent \bexp\b test on \aname\a are
+ skipped. If \aname\a is \b-\b then the \aexpression\a is
+ simply evaluated.]
+ [+hdr \aname\a?Defines \b_hdr_\b\aname\a if the header
+ \b<\b\aname\a\b.h>\b exists. The \b--config\b macro name is
+ \bHAVE_\b\aNAME\a\b_H\b.]
+ [+if \astatement\a ... | \belif\b \astatement\a ... | \belse\b | \bendif\b?
+ Nested if-else test control.]
+ [+iff \aname\a?The generated header \b#ifndef-#endif\b macro guard is
+ \b_\b\aname\a\b_H\b.]
+ [+inc \afile\a [ re ]]?Read #define macro names from \afile\a
+ and arrange for those names to evaluate to 1 in \bexp\b
+ expressions. If \are\a is specified then macros not matching
+ \are\a are ignored.]
+ [+key \aname\a?Defines \b_key_\b\aname\a if \aname\a is a reserved
+ word (keyword).]
+ [+lcl \aname\a?Generates a \b#include\b statement for the native version
+ of the header \b<\b\aname\a\b.h>\b if it exists. Defines
+ \b_lcl_\b\aname\a on success. The \b--config\b macro name is
+ \bHAVE_\b\aNAME\a\b_H\b. The default \are\a is \b^HAVE_\b
+ for \b--config\b and \b^_\b otherwise.]
+ [+lib \aname\a?Defines \b_lib_\b\aname\a if \aname\a is an external
+ symbol in the default libraries.]
+ [+mac \aname\a?Defines \b_mac_\b\aname\a if \aname\a is a macro.]
+ [+mem \astruct.member\a?Defines \b_mem_\b\amember\a\b_\b\astruct\a
+ if \amember\a is a member of the structure \astruct\a.]
+ [+mth \aname\a?Defines \b_mth_\b\aname\a if \aname\a is an external
+ symbol in the math library.]
+ [+nop \aname\a?If this is the first test then \aname\a may be used
+ to name the output file and/or the output header guard macro.
+ Otherwise this test is ignored.]
+ [+npt \aname\a?Defines \b_npt_\b\aname\a if the \aname\a symbol
+ requires a prototype. The \b--config\b macro name is
+ \bHAVE_\aNAME\a\b_DECL\b with the opposite sense.]
+ [+num \aname\a?Defines \b_num_\b\aname\a if \aname\a is a numeric
+ constant \aenum\a or \amacro\a.]
+ [+nxt \aname\a?Defines a string macro \b_nxt_\b\aname\a suitable for
+ a \b#include\b statement to include the next (on the include
+ path) or native version of the header \b<\b\aname\a\b.h>\b
+ if it exists. Also defines the \"...\" form
+ \b_nxt_\b\aname\a\b_str\b. The \b--config\b macro name is
+ \bHAVE_\b\aNAME\a\b_NEXT\b.]
+ [+one \aheader\a ...?Generates a \b#include\b statement for the first
+ header found in the \aheader\a list.]
+ [+opt \aname\a?Defines \b_opt_\b\aname\a if \aname\a is a space-separated
+ token in the global environment variable \bPACKAGE_OPTIONS\b.]
+ [+pth \afile\a [ \adir\a ... | { \ag1\a - ... - \agn\a } | < \apkg\a [\aver\a ...]] > ]]?Defines
+ \b_pth_\b\afile\a, with embedded \b/\b chars translated to
+ \b_\b, to the path of the first instance of \afile\a in the
+ \adir\a directories. \b{\b ... \b}\b forms a directory list
+ from the cross-product of \b-\b separated directory groups
+ \ag1\a ... \agn\a. < ... > forms a directory list for the
+ package \apkg\a with optional versions. If no operands are
+ specified then the default PATH directories are used. The
+ \b--config\b macro name is \aNAME\a\b_PATH\b.]
+ [+run \afile\a?Runs the tests in \afile\a based on the \afile\a
+ suffix:]{
+ [+.c?\afile\a is compiled and executed and the output is copied
+ to the \biffe\b output file. Macros and headers supplied
+ to \bbegin{\b ... \b}end\b are also supplied to
+ \afile\a.]
+ [+.sh?\afile\a is executed as a shell script and the output is
+ copied to the \biffe\b output file.]
+ [+.iffe \bor no suffix?\afile\a contains \biffe\b
+ statements.]
+ }
+ [+set \aoption value\a?Sets option values. The options are described
+ above.]
+ [+siz \aname\a?Defines \b_siz_\b\aname\a to be \bsizeof\b(\aname\a) if
+ \aname\a is a type in any of \b<sys/types.h>, <times.h>,
+ <stddef.h>, <stdlib.h>\b. Any \b.\b characters in \aname\a are
+ translated to space before testing and are translated to \b_\b
+ in the output macro name.]
+ [+sym \aname\a?Defines \b_ary_\b\aname\a if \aname\a is an array,
+ \b_fun_\b\aname\a if \aname\a is a function pointer,
+ \b_ptr_\b\aname\a if \aname\a is a pointer, or
+ \b_reg_\b\aname\a if \aname\a is a scalar. In most cases
+ \aname\a is part of a macro expansion.]
+ [+sys \aname\a?Defines \b_sys_\b\aname\a if the header
+ \b<sys/\b\aname\a\b.h>\b exists. The \b--config\b macro name is
+ \bHAVE_SYS_\b\aNAME\a\b_H\b.]
+ [+tst \aname\a?A user defined test on name. A source block must be
+ supplied. Defines \b_\b\aname\a on success. \btst - ...\b is
+ treated as \btst - - ...\b.]
+ [+typ \aname\a?Defines \b_typ_\b\aname\a if \aname\a is a type in any
+ of \b<sys/types.h>, <times.h>, <stddef.h>, <stdlib.h>\b. Any
+ \b.\b characters in \aname\a are translated to space before
+ testing and are translated to \b_\b in the output macro name.]
+ [+val \aname\a?The output of \becho\b \aname\a is written to the
+ output file.]
+ [+var \aname\a?A user defined test on name. A source block must be
+ supplied. Sets the \bexp\b variable \b_\b\aname\a on success
+ but does not define a macro.]
+ [+(\aexpression\a)?Equivalent to \bexp -\b \aexpression\a.]
+}
+[+?Code block names may be prefixed by \bno\b to invert the test sense. The
+ block names are:]{
+ [+cat?The block is copied to the output file.]
+ [+compile?The block is compiled (\bcc -c\b).]
+ [+cross?The block is executed as a shell script using \bcrossexec\b(1)
+ if \b--cross\b is on, or on the local host otherwise, and the
+ output is copied to the output file. Test macros are not
+ exported to the script.]
+ [+execute?The block is compiled, linked, and executed. \b0\b exit
+ status means success.]
+ [+fail?If the test fails then the block text is evaluated by
+ \bsh\b(1).]
+ [+link?The block is compiled and linked (\bcc -o\b).]
+ [+macro?The block is preprocessed (\bcc -E\b) and lines containing
+ text bracketed by \b<<"\b ... \b">>\b (\aless-than less-than
+ double-quote ... double-quote greater-than greater-than\a)
+ are copied to the output file with the brackets omitted.]
+ [+no?If the test fails then the block text is copied to the
+ output file. Deprecated: use { \bif\b \belif\b \belse\b
+ \bendif\b } with unnamed \b{\b ... \b}\b blocks.]
+ [+note?If the test succeeds then the block is copied to the output
+ as a \b/*\b ... \b*/\b comment.]
+ [+output?The block is compiled, linked, and executed, and the output
+ is copied to the output file.]
+ [+pass?If the test succeeds then the block text is evaluated by
+ \bsh\b(1).]
+ [+preprocess?The block is preprocessed (\bcc -E\b).]
+ [+run?The block is executed as a shell script and the output is
+ copied to the output file. Succesful test macros are also
+ defined as shell variables with value \b1\b and are available
+ within the block. Likewise, failed test macros are defined
+ as shell variables with value \b0\b.]
+ [+status?The block is compiled, linked, and executed, and the exit
+ status is the test outcome, 0 for \afailure\a, the value
+ otherwise.]
+ [+yes?If the test succeeds then the block text is copied to the output
+ file. \byes{\b ... \b}end\b is equivalent to the unnamed block
+ \b{\b ... \b}\b. Deprecated: use { \bif\b \belif\b \belse\b
+ \bendif\b } with unnamed \b{\b ... \b}\b blocks.]
+}
+[+SEE ALSO?\bautoconf\b(1), \bconfig\b(1), \bgetconf\b(1), \bcrossexec\b(1),
+ \bnmake\b(1), \bpackage\b(1), \bproto\b(1), \bsh\b(1)]
+'
+ while getopts -a "$command" "$USAGE" OPT
+ do case $OPT in
+ a) set="$set set all :" ;;
+ c) set="$set set cc $OPTARG :" ;;
+ C) set="$set set config :" ;;
+ d) set="$set set debug $OPTARG :" ;;
+ D) set="$set set define :" ;;
+ E) set="$set set explicit :" ;;
+ F) set="$set set features $OPTARG :" ;;
+ i) set="$set set input $OPTARG :" ;;
+ I) set="$set set include $OPTARG :" ;;
+ L) set="$set set library $OPTARG :" ;;
+ n) set="$set set namval $OPTARG :" ;;
+ N) set="$set set nooptimize $OPTARG :" ;;
+ o) set="$set set output $OPTARG :" ;;
+ e) set="$set set package $OPTARG :" ;;
+ p) set="$set set prototyped :" ;;
+ P) set="$set set pragma $OPTARG :" ;;
+ r) set="$set set regress :" ;;
+ s) set="$set set shell $OPTARG :" ;;
+ S) set="$set set static $OPTARG :" ;;
+ O) set="$set set stdio $OPTARG :" ;;
+ u) set="$set set undef :" ;;
+ v) set="$set set verbose :" ;;
+ x) set="$set set cross $OPTARG :" ;;
+ X) set="$set set exclude $OPTARG :" ;;
+ esac
+ done
+ shift `expr $OPTIND - 1`
+ ;;
+*) while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -) break
+ ;;
+ --) shift
+ break
+ ;;
+ --a|--al|--all)
+ REM=a
+ ;;
+ --cc=*) REM=c`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --co|--con|--conf|--confi|--config)
+ REM=C
+ ;;
+ --cr=*|--cro=*|--cros=*|--cross=*)
+ REM=x`echo X$1 | sed -e 's,[^=]*=,,'`
+ ;;
+ --d=*|--de=*|--deb=*|--debu=*|--debug=*)
+ REM=d`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --def|--defi|--defin|--define)
+ REM=D
+ ;;
+ --e=*|--ex=*|--exc=*|--excl=*|--exclu=*|--exclud=*|--exclude=*)
+ REM=X`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --e|--ex|--exp|--expl|--expli|--explic|--explici|--explicit)
+ REM=E
+ ;;
+ --f=*|--fe=*|--fea=*|--feat=*|--featu=*|--featur=*|--feature=*|--features=*)
+ REM=F`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --inp=*|--inpu=*|--input=*)
+ REM=i`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --inc=*|--incl=*|--inclu=*|--includ=*|--include=*)
+ REM=I`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --l=*|--li=*|--lib=*|--libr=*|--libra=*|--librar=*|--library=*)
+ REM=L`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --n|--na|--nam|--name|--name-v|--name-va|--name-val|--name-valu|--name-value)
+ REM=n
+ ;;
+ --o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*)
+ REM=o`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --pa=*|--pac=*|--pack=*|--packa=*|--packag=*|--package=*)
+ REM=e`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --pro|--prot|--proto|--protot|--prototy|--prototyp|--prototype|--prototyped)
+ REM=p
+ ;;
+ --pra=*|--prag=*|--pragma=*)
+ REM=P`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --r|--re|--reg|--regre|--regres|--regress)
+ REM=r
+ ;;
+ --sh=*|--she=*|--shel=*|--shell=*)
+ REM=s`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --sta=*|--stat=*|--stati=*|--static=*)
+ REM=S`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --std=*|--stdi=*|--stdio=*)
+ REM=O`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --u|--un|--und|--unde|--undef)
+ REM=u
+ ;;
+ --v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
+ REM=v
+ ;;
+ --*) echo $command: $1: unknown option >&2
+ exit 2
+ ;;
+ -*) REM=`echo X$1 | sed 's,X-,,'`
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ while :
+ do case $REM in
+ '') break ;;
+ esac
+ eval `echo $REM | sed "s,\(.\)\(.*\),OPT='\1' REM='\2',"`
+ case $OPT in
+ [cdFiILoOePsSxX])
+ case $REM in
+ '') case $# in
+ 0) echo $command: -$OPT: option argument expected >&2
+ exit 1
+ ;;
+ esac
+ OPTARG=$1
+ shift
+ ;;
+ *) OPTARG=$REM
+ REM=''
+ ;;
+ esac
+ esac
+ case $OPT in
+ a) set="$set set all :" ;;
+ c) set="$set set cc $OPTARG :" ;;
+ C) set="$set set config :" ;;
+ d) set="$set set debug $OPTARG :" ;;
+ D) set="$set set define :" ;;
+ E) set="$set set explicit :" ;;
+ F) set="$set set features $OPTARG :" ;;
+ i) set="$set set input $OPTARG :" ;;
+ I) set="$set set include $OPTARG :" ;;
+ L) set="$set set library $OPTARG :" ;;
+ n) set="$set set namval $OPTARG :" ;;
+ N) set="$set set nooptimize $OPTARG :" ;;
+ o) set="$set set output $OPTARG :" ;;
+ e) set="$set set package $OPTARG :" ;;
+ p) set="$set set prototyped :" ;;
+ P) set="$set set pragma $OPTARG :" ;;
+ r) set="$set set regress :" ;;
+ s) set="$set set shell $OPTARG :" ;;
+ S) set="$set set static $OPTARG :" ;;
+ O) set="$set set stdio $OPTARG :" ;;
+ u) set="$set set undef :" ;;
+ v) set="$set set verbose :" ;;
+ x) set="$set set cross $OPTARG :" ;;
+ X) set="$set set exclude $OPTARG :" ;;
+ *) echo "Usage: $command [-aCDEnpruv] [-c C-compiler-name [C-compiler-flags ...]] [-d level]
+ [-F features-header] [-i file] [-o file] [-O stdio-header] [-e name] [-P text]
+ [-s shell-path] [-S[flags]] [-x cross-exec-prefix] [-I dir] [-L dir] [-X dir] [ - ]
+ [ file.iffe | statement [ : statement ... ] ]" >&2
+ exit 2
+ ;;
+ esac
+ done
+ done
+ ;;
+esac
+case $1 in
+-) out=-; shift ;;
+esac
+case $# in
+0) in=- ;;
+esac
+set -- $set "$@"
+case " $* " in
+*' set config '*|*' run config.'*|*' run '*' config.'*|*' run '*'/config.'*)
+ config=1
+ ;;
+esac
+
+# standard error to /dev/null unless debugging
+# standard output to the current output file
+#
+# stdout original standard output
+# stderr original standard error
+# nullin /dev/null input
+# nullout /dev/null output
+
+stdout=5 stderr=6 nullin=7 nullout=8
+eval "exec $nullin</dev/null $nullout>/dev/null $stdout>&1 $stderr>&2"
+case " $* " in
+*" set debug "[3456789]*)
+ ;;
+*) eval "exec 2>&$nullout"
+ ;;
+esac
+
+# prompt complications
+
+case `print -n aha </dev/null 2>/dev/null` in
+aha) show='print -n' SHOW='' ;;
+*) case `echo -n aha 2>/dev/null` in
+ -n*) show=echo SHOW='\c' ;;
+ *) show='echo -n' SHOW='' ;;
+ esac
+ ;;
+esac
+
+# tmp files cleaned up on exit
+# status: 0:success 1:failure 2:interrupt
+
+status=1
+case $debug in
+2) core=
+ ;;
+*) if (ulimit -c 0) >/dev/null 2>&1
+ then ulimit -c 0
+ core=
+ else core="core core.??*"
+ fi
+ ;;
+esac
+trap "rm -f $core $tmp*" 0
+if (:>$tmp.c) 2>/dev/null
+then rm -f $tmp.c
+else echo "$command: cannot create tmp files in current dir" >&2
+ exit 1
+fi
+status=2
+
+# standard header for c source
+
+std='#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
+#define _STD_ 1
+#define _ARG_(x) x
+#define _VOID_ void
+#else
+#define _STD_ 0
+#define _ARG_(x) ()
+#define _VOID_ char
+#endif
+#if defined(__cplusplus)
+#define _BEGIN_EXTERNS_ extern "C" {
+#define _END_EXTERNS_ }
+#else
+#define _BEGIN_EXTERNS_
+#define _END_EXTERNS_
+#endif
+#define _NIL_(x) ((x)0)'
+tst=
+ext="#include <stdio.h>"
+noext='*[<"][Ss][Tt][Dd][Ii][Oo].[Hh][">]*|*<ast.h>*|*<sfio.h>*|*/[*]<NOSTDIO>[*]/*'
+
+# loop on op [ arg [ ... ] ] [ : op [ arg [ ... ] ] ]
+
+argx=0
+cur=.
+can=
+cansep=
+cctest=
+file=
+hdrtest=
+ifelse=NONE
+ifstack=
+ini=
+init=1
+line=0
+nan=
+prototyped=
+while :
+do case $in in
+ "") case $argx:$* in
+ 1:$argv);;
+ 1:*) argx=0
+ set x $argv
+ shift
+ ;;
+ esac
+ ;;
+ *) case $ini in
+ '') if read lin
+ then case $shell in
+ ksh) let line=line+1 ;;
+ *) line=`expr $line + 1` ;;
+ esac
+ $posix_noglob
+ set x $lin
+ $posix_glob
+ case $# in
+ 1) continue ;;
+ esac
+ else set x
+ fi
+ ;;
+ *) $posix_noglob
+ set x $ini
+ $posix_glob
+ ini=
+ ;;
+ esac
+ shift
+ case $init in
+ 1) case $1 in
+ iff) init=0
+ ;;
+ print|ref|set)
+ ;;
+ *) init=0
+ ini=$*
+ set ini
+ ;;
+ esac
+ esac
+ ;;
+ esac
+ case $# in
+ 0) case $ifstack in
+ ?*) echo "$command: $file$line: missing endif" >&$stderr
+ exit 1
+ ;;
+ esac
+ set set out +
+ ;;
+ esac
+
+ # if nesting
+
+ while :
+ do case $1 in
+ "if") ifstack="$ifelse:$ifstack"
+ case $ifelse in
+ KEEP|NONE)
+ ifelse=TEST
+ ;;
+ TEST) ;;
+ *) ifelse=DONE
+ ;;
+ esac
+ shift
+ case $explicit in
+ 1) set '' - "$@"; shift ;;
+ esac
+ ;;
+ "elif") case $ifelse in
+ SKIP) ifelse=TEST
+ ;;
+ TEST) ;;
+ *) ifelse=DONE
+ ;;
+ NONE) echo "$command: $file$line: $1: no matching if" >&$stderr
+ exit 1
+ ;;
+ esac
+ shift
+ case $explicit in
+ 1) set '' - "$@"; shift ;;
+ esac
+ ;;
+ "else") case $ifelse in
+ KEEP) ifelse=DONE
+ ;;
+ SKIP|TEST)
+ ifelse=KEEP
+ ;;
+ NONE) echo "$command: $file$line: $1: no matching if" >&$stderr
+ exit 1
+ ;;
+ esac
+ shift
+ ;;
+ "endif")case $ifelse in
+ NONE) echo "$command: $file$line: $1: no matching if" >&$stderr
+ exit 1
+ ;;
+ esac
+ case $shell in
+ ksh) ifelse=${ifstack%%:*}
+ ifstack=${ifstack#*:}
+ ;;
+ *) eval `echo $ifstack | sed 's,\([^:]*\):\(.*\),ifelse=\1 ifstack=\2,'`
+ ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+
+ # check if "run xxx" is equivalent to "set in xxx"
+
+ case $1 in
+ "("*) set exp - "$@" ;;
+ *.iffe|*.iff) set run "$@" ;;
+ esac
+ case $1 in
+ :) shift
+ continue
+ ;;
+ run) case $shell in
+ bsh) case $2 in
+ */*) x=`echo $2 | sed 's,.*[\\\\/],,'` ;;
+ *) x=$2 ;;
+ esac
+ ;;
+ *) eval 'x=${2##*[\\/]}'
+ ;;
+ esac
+ case $x in
+ *.iffe|*.iff)
+ set set in $2 ;;
+ *.*) ;;
+ *) set set in $2 ;;
+ esac
+ ;;
+ esac
+
+ # { inc set } drop out early
+
+ case $1 in
+ ""|"#"*)continue
+ ;;
+ inc) case $ifelse in
+ DONE|SKIP) set ''; shift; continue ;;
+ esac
+ shift
+ case $# in
+ 0) echo "$command: $file$line: path expected" >&$stderr
+ exit 1
+ ;;
+ esac
+ p=$1
+ shift
+ if test ! -f $p
+ then echo "$command: $file$line: $p: file not found" >&$stderr
+ exit 1
+ fi
+ case $# in
+ 0) case $config in
+ 1) e="^HAVE_" ;;
+ *) e="^_" ;;
+ esac
+ ;;
+ 1) e=$1
+ ;;
+ *) shift
+ echo "$command: $file$line: warning: $*: operands ignored" >&$stderr
+ ;;
+ esac
+ eval `sed -e '/^#define[ ]/!d' -e 's/#define[ ]//' -e 's/[ (].*//' ${e:+"-e/$e/!d"} -e 's/.*/&=1/' $p | LC_ALL=C sort -u`
+ continue
+ ;;
+ set) case $ifelse in
+ DONE|SKIP) set ''; shift; continue ;;
+ esac
+ shift
+ case $1 in
+ ""|"#"*)op=
+ ;;
+ *) arg=
+ op=$1
+ case $op in
+ --*) case $shell in
+ bsh) op=`echo X$op | sed 's/X--//'` ;;
+ *) op=${op#--} ;;
+ esac
+ ;;
+ -*) case $op in
+ -??*) case $shell in
+ bsh) arg=`echo X$op | sed 's/X-.//'`
+ op=`echo X$op | sed 's/X\\(-.\\).*/\\1/'`
+ ;;
+ *) arg=${op#-?}
+ op=${op%$arg}
+ ;;
+ esac
+ ;;
+ esac
+ case $op in
+ a) op=all ;;
+ c) op=cc ;;
+ C) op=config ;;
+ d) op=debug ;;
+ D) op=define ;;
+ E) op=explicit ;;
+ F) op=features ;;
+ i) op=input ;;
+ I) op=include ;;
+ L) op=library ;;
+ n) op=namval ;;
+ N) op=nooptimize ;;
+ o) op=output ;;
+ e) op=package ;;
+ p) op=prototyped ;;
+ P) op=pragma ;;
+ r) op=regress ;;
+ s) op=shell ;;
+ S) op=static ;;
+ O) op=stdio ;;
+ u) op=undef ;;
+ v) op=verbose ;;
+ x) op=cross ;;
+ X) op=exclude ;;
+ esac
+ ;;
+ esac
+ shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *" "*) shift
+ continue
+ ;;
+ ""|"#"*)break
+ ;;
+ :) shift
+ break
+ ;;
+ esac
+ case $arg in
+ "") arg=$1 ;;
+ *) arg="$arg $1" ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ case $op in
+ all) all=1
+ continue
+ ;;
+ cc) occ=
+ for x in $arg
+ do case $occ in
+ "") case $x in
+ *=*) case $shell in
+ bsh) eval $x
+ export `echo $x | sed 's/=.*//'`
+ ;;
+ *) export $x
+ ;;
+ esac
+ ;;
+ -O*) case $optimize in
+ 1) occ=$x ;;
+ esac
+ ;;
+ *) occ=$x
+ ;;
+ esac
+ ;;
+ *) occ="$occ $x"
+ ;;
+ esac
+ done
+ exclude occ
+ continue
+ ;;
+ config) config=1
+ continue
+ ;;
+ cross) case $arg in
+ ""|-) cross= ;;
+ *) cross="$arg" libpaths= ;;
+ esac
+ continue
+ ;;
+ debug) debug=$arg
+ case $arg in
+ 0) exec 2>&$nullout
+ set -
+ show=echo
+ SHOW=
+ ;;
+ ""|1) exec 2>&$stderr
+ set -
+ show=echo
+ SHOW=
+ ;;
+ 2|3) exec 2>&$stderr
+ case $shell in
+ ksh) eval 'PS4="${PS4%+*([ ])}+\$LINENO+ "'
+ esac
+ show=echo
+ SHOW=
+ set -x
+ ;;
+ *) echo "$command: $arg: debug levels are 0, 1, 2, 3" >&$stderr
+ ;;
+ esac
+ continue
+ ;;
+ define) define=1
+ continue
+ ;;
+ exclude)case $arg in
+ ""|-) excludes= ;;
+ *) excludes="$excludes $arg" ;;
+ esac
+ exclude includes occ
+ continue
+ ;;
+ explicit)
+ explicit=1
+ continue
+ ;;
+ features)case $arg in
+ '') tst= ;;
+ *) tst="#include \"$arg\"" ;;
+ esac
+ continue
+ ;;
+ "in"|input)
+ case $arg in
+ "") in=-
+ ;;
+ *) in=$arg
+ if test ! -r $in
+ then echo "$command: $in: not found" >&$stderr
+ exit 1
+ fi
+ exec < $in
+ file=$in:
+ case $out in
+ "") case $in in
+ *[.\\/]*)
+ case $shell in
+ bsh) eval `echo $in | sed -e 's,.*[\\\\/],,' -e 's/\\.[^.]*//' -e 's/^/out=/'`
+ ;;
+ *) eval 'out=${in##*[\\/]}'
+ eval 'out=${out%.*}'
+ ;;
+ esac
+ ;;
+ *) out=$in
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+ include)case $arg in
+ ""|-) includes= ;;
+ *) includes="$includes -I$arg" ;;
+ esac
+ exclude includes
+ continue
+ ;;
+ library)for y in $libpaths
+ do eval $y=\"\$$y:\$arg\$${y}_default\"
+ eval export $y
+ done
+ continue
+ ;;
+ namval) define=n
+ continue
+ ;;
+ nodebug)exec 2>&$nullout
+ set -
+ continue
+ ;;
+ nodefine)
+ define=0
+ continue
+ ;;
+ nooptimize)
+ optimize=0
+ case $occ in
+ *" -O"*)occ=`echo $occ | sed 's/ -O[^ ]*//g'`
+ cc=$occ
+ ;;
+ esac
+ ;;
+ optimize)
+ optimize=1
+ ;;
+ out|output)
+ out=$arg
+ defhdr=
+ usr=
+ deflib=
+ one=
+ puthdr=
+ putlib=
+ case $op in
+ output) continue ;;
+ esac
+ def=
+ test=
+ ;;
+ package)protoflags="$protoflags -e $arg"
+ continue
+ ;;
+ prototyped|noprototyped)
+ pragma="$pragma $op"
+ case $op in
+ prototyped) prototyped=1 ;;
+ *) prototyped= ;;
+ esac
+ continue
+ ;;
+ pragma) pragma="$pragma $arg"
+ continue
+ ;;
+ regress)regress=1
+ version=1995-03-19
+ continue
+ ;;
+ shell) case $arg in
+ osh) posix_read=-no
+ shell=bsh
+ ;;
+ esac
+ shell=$arg
+ continue
+ ;;
+ static) static=$arg
+ continue
+ ;;
+ stdio) case $arg in
+ '') ext=
+ ;;
+ *) ext=
+ sep=
+ for i in $arg
+ do case $i in
+ -) case $ext in
+ '') continue ;;
+ *) break ;;
+ esac
+ ;;
+ esac
+ echo "#include \"$i\"" > t.c
+ if $cc -E t.c > /dev/null 2>&1
+ then ext="$ext$sep#include \"$arg\""
+ sep=$nl
+ fi
+ done
+ ;;
+ esac
+ continue
+ ;;
+ undef) undef=1
+ continue
+ ;;
+ verbose)verbose=1
+ continue
+ ;;
+ *) echo "$command: $op: unknown option" >&$stderr
+ exit 1
+ ;;
+ esac
+ ;;
+ api|define|extern|header|include|print|reference|ver)
+ op=$1
+ shift
+ arg=
+ ;;
+ *) case $2 in
+ '=') def=$1
+ shift
+ shift
+ ;;
+ *) case $1 in
+ '-'|'?')def=-
+ shift
+ ;;
+ *) def=
+ ;;
+ esac
+ ;;
+ esac
+ case $1 in
+ '!') not=1
+ shift
+ ;;
+ *) not=
+ ;;
+ esac
+ case $1 in
+ *'{') op=-
+ ;;
+ '('*|'"'*'"'|'<'*'>')
+ op=exp
+ case $def in
+ '') def=- ;;
+ esac
+ ;;
+ *) op=$1
+ shift
+ ;;
+ esac
+ arg=
+ cc="$occ $includes"
+ group=
+ groups=
+ fail=
+ hdr=
+ lib=
+ mac=
+ no=
+ note=
+ opt=
+ pass=
+ pth=
+ run=
+ set=
+ src=
+ test=
+ yes=
+ case $# in
+ 0) ;;
+ *) case $1 in
+ "#"*) set x
+ shift
+ ;;
+ *) case $op in
+ ref) ;;
+ *) case $1 in
+ '-') case $op:$2 in
+ tst:*) arg=$1
+ case $2 in
+ -) shift ;;
+ esac
+ ;;
+ *:-*) arg=$1
+ shift
+ ;;
+ *) def=-
+ shift
+ case $1 in
+ '('*|*'{'|'"'*'"'|'<'*'>')
+ arg=-
+ ;;
+ *) arg=$1
+ case $# in
+ 0) ;;
+ *) shift ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ -*|+*|'('*|*'{'|'"'*'"'|'<'*'>')
+ arg=-
+ ;;
+ *) arg=$1
+ shift
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $1 in
+ '('*|'"'*'"'|'<'*'>')
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *[.{}]*)break ;;
+ esac
+ case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ shift
+ done
+ case $arg in
+ '') arg=- ;;
+ esac
+ case $op in
+ exp) case $def in
+ ''|'-') ;;
+ *) arg=$def ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ sline=$line
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ "") ;;
+ "#"*) set x
+ ;;
+ "=") shift
+ set=$*
+ case $set in
+ "") set=" " ;;
+ esac
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ shift
+ done
+ break
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*'{'|'{')
+ v=$1
+ shift
+ x=
+ case $v in
+ "note{")
+ sep=" " ;;
+ *) sep=$nl ;;
+ esac
+ case $v in
+ '{') e='}' ;;
+ *) e='}end' ;;
+ esac
+ n=1
+ SEP=
+ while :
+ do case $# in
+ 0) case $posix_read in
+ -*) checkread ;;
+ esac
+ case $in in
+ "") echo "$command: $file$line: missing }end" >&$stderr
+ exit 1
+ ;;
+ esac
+ while :
+ do case $posix_read in
+ 1) case $shell in
+ ksh) IFS= read -r lin
+ eof=$?
+ while :
+ do lin="${lin#[' ']}"
+ case $lin in
+ [' ']*'#'*);;
+ *) break ;;
+ esac
+ done
+ ;;
+ *) IFS=
+ read -r lin
+ eof=$?
+ IFS=$ifs
+ case $lin in
+ [' ']*) lin=`sed -e 's,^[ ],,' -e 's,^[ ]*#,#,' <<!
+$lin
+!
+`
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) lin=`$posix_read`
+ eof=$?
+ ;;
+ esac
+ case $eof in
+ 0) case $shell in
+ ksh) let line=line+1 ;;
+ *) line=`expr $line + 1` ;;
+ esac
+ $posix_noglob
+ set x $lin
+ $posix_glob
+ case $2 in
+ $v) case $shell in
+ ksh) let n=n+1 ;;
+ *) n=`expr $n + 1` ;;
+ esac
+ ;;
+ $e|$e';')
+ case $n in
+ 1) shift
+ break 2
+ ;;
+ esac
+ case $shell in
+ ksh) let n=n-1 ;;
+ *) n=`expr $n - 1` ;;
+ esac
+ ;;
+ esac
+ x="$x$SEP$lin"
+ SEP=$sep
+ ;;
+ *) echo "$command: $file$line: missing $e" >&$stderr
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $1 in
+ $v) case $shell in
+ ksh) let n=n+1 ;;
+ *) n=`expr $n + 1` ;;
+ esac
+ ;;
+ $e|$e';')
+ case $n in
+ 1) break ;;
+ esac
+ case $shell in
+ ksh) let n=n-1 ;;
+ *) n=`expr $n - 1` ;;
+ esac
+ ;;
+ esac
+ x="$x$SEP$1"
+ SEP=$sep
+ shift
+ done
+ case $v in
+ 'note{');;
+ *) x="$x$nl" # \r\n bash needs this barf # ;;
+ esac
+ case $v in
+ 'fail{') fail=$x ;;
+ 'nofail{') pass=$x v='pass{' ;;
+ 'nopass{') fail=$x v='fail{' ;;
+ 'no{') no=$x ;;
+ 'note{') note=$x ;;
+ 'pass{') pass=$x ;;
+ 'test{') test=$x ;;
+ 'yes{'|'{') yes=$x ;;
+ *) src=$x run=$v ;;
+ esac
+ ;;
+ :) shift
+ break
+ ;;
+ *[\"\'\(\)\{\}\ \ ]*)
+ case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ -) group=$group$1
+ case $group in
+ -) com_hdr=$hdr
+ com_lib=$lib
+ com_mac=$mac
+ com_opt=$opt
+ com_pth=$pth
+ com_test=$test
+ ;;
+ *) groups="$groups $1"
+ ;;
+ esac
+ ;;
+ -l*) case $group in
+ --*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ +l*) case $shell in
+ bsh) x=`echo X$1 | sed 's/X+/-/'` ;;
+ *) eval 'x=-${1#+}' ;;
+ esac
+ case $group in
+ --*) groups="$groups $x" ;;
+ *) lib="$lib $x" ;;
+ esac
+ ;;
+ -*|+*) case $op in
+ ref) cc="$cc $1"
+ occ="$occ $1"
+ case $1 in
+ -L*) case $shell in
+ ksh) x=${1#-L} ;;
+ *) x=`echo x$1 | sed 's,^x-L,,'` ;;
+ esac
+ for y in $libpaths
+ do eval $y=\"\$$y:\$x\$${y}_default\"
+ eval export $y
+ done
+ ;;
+ esac
+ ;;
+ *) case $group in
+ --*) groups="$groups $1"
+ ;;
+ *) case $op in
+ run) opt="$opt $1"
+ ;;
+ *) case $1 in
+ -D*) mac="$mac $1" ;;
+ *) cc="$cc $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *.[aAxX]|*.[dD][lL][lL]|*.[lL][iI][bB])
+ case $group in
+ --*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ *[.\\/]*)
+ case $group in
+ --*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1" ;;
+ *) hdr="$hdr $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $group in
+ --*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ shift
+ done
+ case $group in
+ -) group= ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $ifelse in
+ DONE|SKIP) continue ;;
+ esac
+
+ # make sure $cc compiles C
+
+ case $cc in
+ "") cc="$occ $includes" ;;
+ esac
+ case $cctest in
+ "") checkcc ;;
+ esac
+
+ # some ops allow no args
+
+ case $arg in
+ '') case $op in
+ api) arg=-
+ case $1:$2 in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*:[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
+ a=$1
+ shift
+ case " $apis " in
+ *" $a "*)
+ ;;
+ *) apis="$apis $a"
+ eval api_sym_${a}= api_ver_${a}=
+ ;;
+ esac
+ rel=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
+ rel="$rel $1"
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :) break ;;
+ esac
+ eval syms='$'api_sym_${a}
+ case $syms in
+ '') sep='' ;;
+ *) sep=$nl ;;
+ esac
+ for r in $rel
+ do syms=$syms$sep${1}:${r}
+ sep=$nl
+ done
+ eval api_sym_${a}='$'syms
+ shift
+ done
+ ;;
+ *) echo "$command: $op: expected: name YYYYMMDD symbol ..." >&$stderr
+ ;;
+ esac
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :) break ;;
+ esac
+ shift
+ done
+ ;;
+ iff|ini)arg=-
+ ;;
+ comment)copy - "/* $* */"
+ continue
+ ;;
+ define) x=$1
+ shift
+ case $1 in
+ '('*')')
+ arg=$1
+ shift
+ ;;
+ esac
+ case $in in
+ "") v=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ t=$1
+ shift
+ case $t in
+ ":") break ;;
+ esac
+ v="$v $t"
+ done
+ ;;
+ *) v=$*
+ ;;
+ esac
+ is mac $x
+ copy $tmp.c "$std
+$usr
+#ifndef $x
+(
+#endif
+int x;
+"
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then success -
+ else failure -
+ copy - "#define $x$arg $v"
+ usr="$usr${nl}#define $x$arg $v"
+ fi
+ continue
+ ;;
+ extern) x=$1
+ shift
+ t=$1
+ shift
+ is npt $x
+ copy $tmp.c "
+$std
+#include <sys/types.h>
+$usr
+_BEGIN_EXTERNS_
+struct _iffe_struct { int _iffe_member; };
+extern struct _iffe_struct* $x _ARG_((struct _iffe_struct*));
+_END_EXTERNS_
+"
+ # some compilers with -O only warn for invalid intrinsic prototypes
+ case " $cc " in
+ *" -O "*) xx=`echo $cc | sed 's/ -O / /g'` ;;
+ *) xx=$cc ;;
+ esac
+ if compile $xx -c $tmp.c <&$nullin >&$nullout
+ then success -
+ while :
+ do case $1 in
+ ''|'('*|'['*)
+ break
+ ;;
+ esac
+ t="$t $1"
+ shift
+ done
+ case $in in
+ "") v=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ t=$1
+ shift
+ case $t in
+ ":") break ;;
+ esac
+ v="$v $t"
+ done
+ ;;
+ *) v=$*
+ ;;
+ esac
+ copy - "extern $t $x$v;"
+ # NOTE: technically if prototyped is on all tests should
+ # be run through proto(1), but we'd like iffe to
+ # work sans proto -- so we drop the extern's in
+ # the test headers
+ case $prototyped in
+ '') usr="$usr${nl}extern $t $x$v;" ;;
+ esac
+ else failure -
+ case $in in
+ "") while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ ":") break ;;
+ esac
+ done
+ ;;
+ esac
+ fi
+ continue
+ ;;
+ header|include|reference)
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ x=$1
+ shift
+ case $x in
+ ":") break ;;
+ esac
+ case " $gothdr " in
+ *" - $x "*)
+ ;;
+ *" + $x "*)
+ case $usr in
+ *"# include <"$x">"*)
+ ;;
+ *) case $op in
+ reference)
+ ;;
+ *) copy - "#include <$x>"
+ ;;
+ esac
+ usr="$usr${nl}#include <$x>"
+ ;;
+ esac
+ ;;
+ *) copy $tmp.c "$std
+$usr
+#include <$x>
+int x;
+"
+ if is_hdr - $x
+ then gothdr="$gothdr + $x"
+ case $op in
+ reference)
+ ;;
+ *) copy - "#include <$x>"
+ ;;
+ esac
+ usr="$usr${nl}#include <$x>"
+ else gothdr="$gothdr - $x"
+ fi
+ ;;
+ esac
+ done
+ continue
+ ;;
+ print) case $in in
+ "") v=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ t=$1
+ shift
+ case $t in
+ ":") break ;;
+ esac
+ v="$v $t"
+ done
+ ;;
+ *) v=$*
+ ;;
+ esac
+ copy - "$*"
+ usr="$usr${nl}$v"
+ continue
+ ;;
+ ver) arg=-
+ case $1:$2 in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*:[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
+ vers="$vers$nl$1"
+ eval ver_$1=$2
+ ;;
+ *) echo "$command: $op: expected: name YYYYMMDD" >&$stderr
+ ;;
+ esac
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :) break ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ ;;
+ esac
+
+ # save $* for ancient shells
+
+ argx=1
+ argv=$*
+
+ # loop on all candidate groups
+
+ while :
+ do
+ # check the candidate macros
+
+ cc="$cc $mac"
+
+ # check for global default headers (some cc -E insist on compiling)
+
+ case $hdrtest in
+ '') hdrtest=1
+ allinc=
+ for x in types
+ do case $config in
+ 0) c=_sys_${x}
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$x ;;
+ *) u=`echo $x | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_SYS_${u}_H
+ ;;
+ esac
+ x=sys/$x.h
+ echo "${allinc}#include <$x>" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ case $explicit in
+ 0) can="$can$cansep#define $c 1 /* #include <$x> ok */"
+ nan="$nan$cansep$c=1"
+ cansep=$nl
+ ;;
+ esac
+ eval $c=1
+ allinc="${allinc}#include <$x>$nl"
+ else gothdr="$gothdr - $x"
+ case $explicit$all$config$undef in
+ 0?1?|0??1)
+ can="$can$cansep#undef $c /* #include <$x> not ok */"
+ nan="$nan$cansep$c="
+ cansep=$nl
+ ;;
+ 01??) can="$can$cansep#define $c 0 /* #include <$x> not ok */"
+ nan="$nan$cansep$c=0"
+ cansep=$nl
+ ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+
+ # add implicit headers/libraries before the checks
+
+ case $op in
+ npt) hdr="sys/types.h stdlib.h unistd.h $hdr"
+ ;;
+ siz|typ)hdr="sys/types.h time.h sys/time.h sys/times.h stddef.h stdlib.h $hdr"
+ ;;
+ esac
+
+ # check the candidate headers
+
+ case $hdr in
+ ?*) z=$hdr
+ hdr=
+ dis=0
+ for x in $z
+ do case $x in
+ *.h) case " $gothdr " in
+ *" - $x "*)
+ continue
+ ;;
+ *" + $x "*)
+ ;;
+ *) case $shell in
+ bsh) eval `echo $x | sed -e 's,^\\([^\\\\/]*\\).*[\\\\/]\\([^\\\\/]*\\)\$,\\1_\\2,' -e 's/\\..*//' -e 's/^/c=/'`
+ ;;
+ *) eval 'c=${x##*[\\/]}'
+ eval 'c=${c%%.*}'
+ case $x in
+ */*) eval 'c=${x%%[\\/]*}_${c}' ;;
+ esac
+ ;;
+ esac
+ case $explicit in
+ 0) dis=0
+ ;;
+ *) case $x in
+ */*) dis=$c ;;
+ *) dis=hdr ;;
+ esac
+ case ${dis}_ in
+ ${op}_*)dis=0 ;;
+ *) dis=1 ;;
+ esac
+ ;;
+ esac
+ case $config in
+ 0) case $x in
+ */*) c=_${c} ;;
+ *) c=_hdr_${c} ;;
+ esac
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_${u}_H
+ ;;
+ esac
+ echo "${allinc}#include <$x>" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ case $dis in
+ 0) can="$can$cansep#define $c 1 /* #include <$x> ok */"
+ nan="$nan$cansep$c=1"
+ cansep=$nl
+ ;;
+ esac
+ eval $c=1
+ else gothdr="$gothdr - $x"
+ case $dis$all$config$undef in
+ 0?1?|0??1)
+ can="$can$cansep#undef $c /* #include <$x> not ok */"
+ nan="$nan$cansep$c="
+ cansep=$nl
+ ;;
+ 01??) can="$can$cansep#define $c 0 /* #include <$x> not ok */"
+ nan="$nan$cansep$c=0"
+ cansep=$nl
+ ;;
+ esac
+ continue
+ fi
+ ;;
+ esac
+ ;;
+ *) test -r $x || continue
+ ;;
+ esac
+ hdr="$hdr $x"
+ done
+ ;;
+ esac
+
+ # check the candidate libraries
+
+ case $lib in
+ ?*) z=$lib
+ lib=
+ p=
+ hit=0
+ echo "int main(){return(0);}" > $tmp.c
+ for x in $z
+ do p=$x
+ case " $gotlib " in
+ *"- $p "*)
+ failure +
+ p=
+ ;;
+ *"+ $p "*)
+ success +
+ lib="$lib $p"
+ ;;
+ *) rm -f $tmp.exe
+ is LIB $p
+ if compile $cc -o $tmp.exe $tmp.c $p <&$nullin >&$nullout
+ then success
+ gotlib="$gotlib + $p"
+ lib="$lib $p"
+ e=0
+ else a=
+ e=1
+ for l in $z
+ do case $l in
+ -) a=
+ continue
+ ;;
+ $p) a=$p
+ continue
+ ;;
+ *) case $gotlib in
+ *" $l "*) continue ;;
+ esac
+ ;;
+ esac
+ case $a in
+ $p) a="$a $l"
+ if compile $cc -o $tmp.exe $tmp.c $a <&$nullin >&$nullout
+ then success
+ gotlib="$gotlib + $p"
+ lib="$lib $p"
+ e=0
+ break
+ fi
+ ;;
+ esac
+ done
+ case $e in
+ 1) failure
+ gotlib="$gotlib - $p"
+ ;;
+ esac
+ fi
+ y=
+ for x in $p
+ do case $shell in
+ bsh) c=`echo X$x | sed 's,X-l,,'` ;;
+ *) eval 'c=${x#-l}' ;;
+ esac
+ case $c in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ c=`echo '' $c | sed -e 's,.*[\\\\/],,' -e 's,\.[^.]*$,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g' -e '/^lib./s,^lib,,'`
+ ;;
+ esac
+ case $config in
+ 0) case $e$p in
+ 0*' '*) case " $gotlib " in
+ *[-+]" $x "*)
+ ;;
+ *) can="$can$cansep#define _LIB_$c 1 /* $x is a library */"
+ nan="$nan${cansep}_LIB_$c=1"
+ cansep=$nl
+ eval _LIB_$c=1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=$u
+ case $e in
+ 0*' '*) case " $gotlib " in
+ *[-+]" $x "*)
+ ;;
+ *) can="$can$cansep#define HAVE_${c}_LIB 1 /* $x is a library */"
+ nan="$nan${cansep}HAVE_${c}_LIB=1"
+ cansep=$nl
+ eval HAVE_${c}_LIB=1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ y=${y}_$c
+ done
+ case $config in
+ 0) c=_LIB${y} ;;
+ 1) c=HAVE${y}_LIB ;;
+ esac
+ case $p in
+ *' '*) q="a library group" ;;
+ *) q="a library" ;;
+ esac
+ case $e in
+ 0) can="$can$cansep#define $c 1 /* $p is $q */"
+ nan="$nan$cansep$c=1"
+ cansep=$nl
+ eval $c=1
+ case $hit in
+ 1) break ;;
+ esac
+ ;;
+ 1) case $all$config$undef in
+ ?1?|??1)can="$can$cansep#undef $c /* $p is not $q */"
+ nan="$nan$cansep$c="
+ cansep=$nl
+ ;;
+ 1??) can="$can$cansep#define $c 0 /* $p is not $q */"
+ nan="$nan$cansep$c=0"
+ cansep=$nl
+ ;;
+ esac
+ eval $c=0
+ ;;
+ esac
+ p=
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # last op precheck
+
+ case $op in
+ ref) deflib="$deflib $lib"
+ defhdr="$defhdr $hdr"
+ break
+ ;;
+ esac
+ IFS=" ,"
+ case $shell in
+ bash) op=`echo $op`
+ arg=`echo $arg`
+ ;;
+ *) eval op=\"$op\"
+ eval arg=\"$arg\"
+ ;;
+ esac
+ IFS=$ifs
+
+ # check for op aliases
+
+ x=
+ for o in $op
+ do case $o in
+ def|default) x="$x cmd dat hdr key lib mth sys typ" ;;
+ *) x="$x $o" ;;
+ esac
+ done
+
+ # loop on the ops o and args a
+
+ result=UNKNOWN
+ for o in $x
+ do for a in $arg
+ do c=
+ case $a in
+ *[.\\/]*)
+ case $o in
+ hdr|lcl|nxt|pth|sys)
+ x=$a
+ case $x in
+ *.lcl|*.nxt)
+ case $o in
+ sys) x=sys/$x ;;
+ esac
+ case $shell in
+ bsh) eval `echo $x | sed 's,\\(.*\\)\.\\([^.]*\\),x=\\1 o=\\2,'`
+ ;;
+ *) o=${x##*.}
+ x=${x%.${o}}
+ ;;
+ esac
+ v=$x
+ ;;
+ esac
+ case $x in
+ *[\\/]*)case $shell in
+ bsh) eval `echo $x | sed 's,\\(.*\\)[\\\\//]\\(.*\\),p=\\1 v=\\2,'`
+ ;;
+ *) eval 'p=${x%/*}'
+ eval 'v=${x##*/}'
+ ;;
+ esac
+ ;;
+ *.*) case $shell in
+ bsh) eval `echo $x | sed 's,\\(.*\\)\\.\\(.*\\),p=\\1 v=\\2,'`
+ ;;
+ *) eval 'p=${x%.*}'
+ eval 'v=${x##*.}'
+ ;;
+ esac
+ ;;
+ *) p=
+ ;;
+ esac
+ case $o in
+ lcl|nxt) c=$v.$o ;;
+ *) c=$v ;;
+ esac
+ ;;
+ *) case $shell in
+ bsh) eval `echo $a | sed -e 's,.*[\\\\/],,' -e 's/\\(.*\\)\\.\\(.*\\)/p=\\1 v=\\2/'`
+ ;;
+ *) eval 'p=${a%.*}'
+ eval 'p=${p##*[\\/]}'
+ eval 'v=${a##*.}'
+ eval 'v=${v##*[\\/]}'
+ ;;
+ esac
+ ;;
+ esac
+ case $p in
+ '') f=${v} ;;
+ *) f=${p}/${v} ;;
+ esac
+ case $o in
+ run) v=$p
+ p=
+ m=_${v}
+ ;;
+ mem) case $p in
+ *.*) case $shell in
+ bsh) eval `echo $p | sed 's/\\([^.]*\\)\\.\\(.*\\)/p=\\1 m=\\2/'`
+ ;;
+ *) eval 'm=${p#*.}'
+ eval 'p=${p%%.*}'
+ ;;
+ esac
+ v=${m}.${v}
+ esac
+ case $config in
+ 0) m=_${v}_${p} ;;
+ 1) m=_${v}_in_${p} ;;
+ esac
+ ;;
+ *) case $p in
+ '') m=_${v} ;;
+ *) m=_${p}_${v} ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) p=
+ v=$a
+ f=$a
+ m=_${v}
+ ;;
+ esac
+ case $c in
+ '') c=$v ;;
+ esac
+ M=$m
+ case $o in
+ out) case $a in
+ -) a=-
+ ;;
+ ?*) test="$a $test"
+ a=
+ ;;
+ esac
+ ;;
+ *) case " $idyes " in
+ *" $m "*)
+ i=1
+ ;;
+ *) case " $idno " in
+ *" $m "*)
+ i=0
+ ;;
+ *) case $m in
+ *'*') m=`echo "$m" | sed 's,\*,_ptr,g'` ;;
+ esac
+ case $m in
+ *[-+/\\]*)
+ i=0
+ ;;
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ is id $m
+ copy $tmp.c "int $m = 0;"
+ if compile $cc -c $tmp.c
+ then success -
+ idyes="$idyes $m"
+ i=1
+ else failure -
+ idno="$idno $m"
+ i=0
+ fi
+ ;;
+ *) i=1
+ ;;
+ esac
+ ;;
+ esac
+ case $i in
+ 0) case $o in
+ dat|dfn|key|lib|mac|mth|nos|npt|siz|sym|typ|val)
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $m in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ m=`echo "X$m" | sed -e 's,^.,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'`
+ ;;
+ esac
+
+ # check output redirection
+
+ case $out in
+ $cur) ;;
+ *) case $cur in
+ $a|$c) ;;
+ *) case $cur in
+ .) ;;
+ *) case $vers in
+ ?*) echo
+ for api in $vers
+ do API=`echo $api | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+ eval ver='${'ver_${api}'}'
+ echo "#define ${API}_VERSION ${ver}"
+ done
+ esac
+ case $apis in
+ ?*) for api in $apis
+ do map=
+ sep=
+ eval syms='"${'api_sym_${api}'}"'
+ # old solaris requires -k<space><junk> #
+ set x x `echo "$syms" | sort -t: -u -k 1,1 -k 2,2nr 2>/dev/null | sed 's/:/ /'`
+ case $# in
+ 2) # ancient sort doesn't have -k #
+ set x x `echo "$syms" | sort -t: -u +0 -1 +1 -2nr 2>/dev/null | sed 's/:/ /'`
+ ;;
+ esac
+ sym=
+ while :
+ do shift 2
+ case $# in
+ [01]) break ;;
+ esac
+ prv=$sym
+ sym=$1
+ rel=$2
+ case $prv in
+ $sym) echo "#elif _API_${api} >= $rel"
+ ;;
+ *) case $prv in
+ '') echo
+ echo "#if !defined(_API_${api}) && defined(_API_DEFAULT)"
+ echo "#define _API_${api} _API_DEFAULT"
+ echo "#endif"
+ ;;
+ *) echo "#endif"
+ ;;
+ esac
+ echo
+ echo "#if ( _BLD_${api} || !_API_${api} || _API_${api} >= $rel )"
+ ;;
+ esac
+ echo "#undef ${sym}"
+ echo "#define ${sym} ${sym}_${rel}"
+ map=$map$sep${sym}_${rel}
+ sep=' '
+ done
+ echo "#endif"
+ echo
+ echo "#define _API_${api}_MAP \"$map\""
+ done
+ echo
+ ;;
+ esac
+ case $iff in
+ ?*) echo "#endif" ;;
+ esac
+ case $cur in
+ -) ;;
+ *) exec >/dev/null
+ case $cur in
+ *[\\/]*|*.h) x=$cur ;;
+ *) x=$dir/$cur ;;
+ esac
+ case $define in
+ n) sed '/^#/d' $tmp.h > $tmp.c
+ sed '/^#/d' $x > $tmp.t
+ ;;
+ *) (proto -r $protoflags $tmp.h) >/dev/null 2>&1
+ sed 's,/\*[^/]*\*/, ,g' $tmp.h > $tmp.c
+ sed 's,/\*[^/]*\*/, ,g' $x > $tmp.t
+ ;;
+ esac
+ if cmp -s $tmp.c $tmp.t
+ then rm -f $tmp.h
+ case $verbose in
+ 1) echo "$command: $x: unchanged" >&$stderr ;;
+ esac
+ else case $x in
+ ${dir}[\\/]$cur) test -d $dir || mkdir $dir || exit 1 ;;
+ esac
+ mv $tmp.h $x
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ case $out in
+ +) case $status in
+ 1) ;;
+ *) status=0 ;;
+ esac
+ exit $status
+ ;;
+ -) eval "exec >&$stdout"
+ ;;
+ *) exec >$tmp.h
+ ;;
+ esac
+ case $out in
+ "") case $a in
+ *[\\/]*|???????????????*) cur=$c ;;
+ *) cur=$a ;;
+ esac
+ ;;
+ *) cur=$out
+ ;;
+ esac
+ case $in in
+ ""|-|+) case $o in
+ run) x=" from $a" ;;
+ *) x= ;;
+ esac
+ ;;
+ *) x=" from $in"
+ ;;
+ esac
+
+ # output header comments
+
+ case $define in
+ n) ;;
+ ?) echo "/* : : generated$x by $command version $version : : */"
+ for x in $pragma
+ do echo "#pragma $x"
+ done
+ case $out in
+ ""|-|+) x=$m
+ ;;
+ *.*) case $shell in
+ bsh) eval `echo $in | sed -e 's,\\.,_,g' -e 's/^/x=/'`
+ ;;
+ *) i=$out
+ x=_
+ while :
+ do case $i in
+ *.*) eval 'x=$x${i%%.*}_'
+ eval 'i=${i#*.}'
+ ;;
+ *) x=$x$i
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ *) x=_$out
+ ;;
+ esac
+ case $o in
+ iff) case $M in
+ ""|*-*) ;;
+ *) iff=${m}_H ;;
+ esac
+ ;;
+ *) case $regress in
+ '') case $x in
+ *-*) ;;
+ *) x=`pwd | sed -e 's,.*[\\\\/],,' -e 's,\\..*,,' -e 's,^lib,,' -e 's,^,'${x}_',' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'`
+ # ksh n+ bug workaround
+ case $x in
+ *[!_]*) ;;
+ *) x=_$$ ;;
+ esac
+ iff=_def${x}
+ ;;
+ esac
+ ;;
+ *) case $x in
+ *-*) ;;
+ *) iff=_REGRESS
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $iff in
+ ?*) echo "#ifndef $iff"
+ echo "#define $iff 1"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $can in
+ ?*) case $define in
+ 1) echo "$can" ;;
+ n) echo "$nan" ;;
+ esac
+ can=
+ nan=
+ cansep=
+ ;;
+ esac
+
+ # set up the candidate include list
+
+ pre=
+ inc=
+ for x in $defhdr - $hdr
+ do case $x in
+ -) case $pre in
+ ?*) continue ;;
+ esac
+ case $v in
+ *.*) for x in `echo $v | sed 's,\\., ,g'`
+ do pre="$pre
+#undef $x"
+ done
+ ;;
+ *) case $o in
+ siz|typ)case $v in
+ char|short|int|long)
+ ;;
+ *) pre="#undef $v"
+ ;;
+ esac
+ ;;
+ *) pre="#undef $v"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *.h) case $shell in
+ bsh) eval `echo $x | sed -e 's,^\\([^\\\\/]*\\).*[\\\\/]\\([^\\\\/]*\\)\$,\\1_\\2,' -e 's/\\..*//' -e 's/^/c=/'`
+ ;;
+ *) eval 'c=${x##*[\\/]}'
+ eval 'c=${c%%.*}'
+ case $x in
+ */*) eval 'c=${x%%[\\/]*}_${c}' ;;
+ esac
+ ;;
+ esac
+ case $config in
+ 0) case $x in
+ */*) c=_${c} ;;
+ *) c=_hdr_${c} ;;
+ esac
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_${u}_H
+ ;;
+ esac
+ case " $puthdr " in
+ *" $c "*)
+ ;;
+ *) puthdr="$puthdr $c"
+ usr="$usr$nl#define $c 1"
+ ;;
+ esac
+ inc="$inc
+#include <$x>"
+ ;;
+ esac
+ done
+
+ # set up the candidate lib list
+
+ for x in $lib $deflib
+ do case $shell in
+ ksh) eval 'c=${x#-l}' ;;
+ *) c=`echo X$x | sed 's,X-l,,'` ;;
+ esac
+ case $c in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ c=`echo '' $c | sed -e 's,.*[\\\\/],,' -e 's,\.[^.]*$,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g' -e '/^lib./s,^lib,,'`
+ ;;
+ esac
+ case $config in
+ 0) c=_LIB_${c}
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_${u}_LIB
+ ;;
+ esac
+ case " $putlib " in
+ *" $c "*)
+ ;;
+ *) putlib="$putlib $c"
+ usr="$usr$nl#define $c 1"
+ ;;
+ esac
+ done
+
+ # src overrides builtin test
+
+ case $config:$def in
+ 0:) case $o in
+ tst|var);;
+ *) m=_${o}${m} ;;
+ esac
+ ;;
+ 1:) case $o in
+ tst|var)m=${v} ;;
+ esac
+ case $shell in
+ ksh) typeset -u u=$m ;;
+ *) u=`echo $m | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ case $o in
+ tst|var)case $m in
+ $u) ;;
+ *) case $m in
+ hdr_*|lib_*|sys_*)
+ case $shell in
+ ksh) u=${u#????} ;;
+ *) u=`echo $u | sed 's/....//'` ;;
+ esac
+ ;;
+ esac
+ m=HAVE_${u}
+ ;;
+ esac
+ ;;
+ dat) m=HAVE${u}_DATA ;;
+ hdr|lcl)m=HAVE${u}_H ;;
+ key) m=HAVE${u}_RESERVED ;;
+ mth) m=HAVE${u}_MATH ;;
+ npt) m=HAVE${u}_DECL ;;
+ pth) m=${u}_PATH
+ case $shell in
+ ksh) m=${m#_} ;;
+ *) m=`echo $m | sed 's,^_,,'` ;;
+ esac
+ ;;
+ nxt) m=HAVE${u}_NEXT ;;
+ siz) m=SIZEOF${u} ;;
+ sys) m=HAVE_SYS${u}_H ;;
+ *) m=HAVE${u} ;;
+ esac
+ ;;
+ *) m=$def
+ M=$m
+ ;;
+ esac
+ case $src in
+ ?*) case $src in
+ $noext) EXT= ;;
+ *) EXT="$tst
+$ext"
+ ;;
+ esac
+ copy $tmp.c "$std
+$EXT
+$usr
+$inc
+$src
+"
+ V=1
+ e=0
+ is tst "${note:-$run}"
+ case $run in
+ cat*|nocat*)
+ copy - "$src"
+ ;;
+ cross*|nocross*)
+ copy $tmp.sh "$src"
+ chmod +x $tmp.sh
+ execute $tmp.sh <&$nullin || e=1
+ ;;
+ run*|norun*)
+ (eval "$src") <&$nullin || e=1
+ ;;
+ mac*|nomac*)
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then sed -e '/<<[ ]*".*"[ ]*>>/!d' -e 's/<<[ ]*"//g' -e 's/"[ ]*>>//g' $tmp.i
+ else e=1
+ fi
+ ;;
+ p*|nop*)compile $cc -DTEST=$p -DID=$v -E $tmp.c <&$nullin >&$nullout || e=1
+ ;;
+ c*|noc*)compile $cc -DTEST=$p -DID=$v -c $tmp.c <&$nullin >&$nullout || e=1
+ ;;
+ *) case $run in
+ status*)ccflags=
+ ;;
+ s*|nos*)case $reallystatictest in
+ '') #UNDENT...
+
+ reallystatictest=.
+ echo "$tst
+$ext
+int main(){printf("hello");return(0);}" > ${tmp}s.c
+ rm -f ${tmp}s.exe
+ if compile $cc -c ${tmp}s.c <&$nullin >&$nullout &&
+ compile $cc -o ${tmp}s.exe ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e &&
+ $executable ${tmp}s.exe
+ then e=`wc -l ${tmp}s.e`
+ eval set x x $binding
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f ${tmp}s.exe
+ compile $cc -o ${tmp}s.exe $1 ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e && $executable ${tmp}s.exe || continue
+ case `wc -l ${tmp}s.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ d=`ls -s ${tmp}s.exe`
+ rm -f ${tmp}s.exe
+ compile $cc -o ${tmp}s.exe $2 ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e && $executable ${tmp}s.exe || continue
+ case `wc -l ${tmp}s.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case `ls -s ${tmp}s.exe` in
+ $d) ;;
+ *) reallystatic=$2
+ set x
+ shift
+ break
+ ;;
+ esac
+ done
+ fi
+ rm -f ${tmp}s.*
+ #...INDENT
+ ;;
+ esac
+ ccflags=$reallystatic
+ ;;
+ *) ccflags=
+ ;;
+ esac
+ set x $mac
+ e=1
+ while :
+ do o=
+ shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -) break ;;
+ esac
+ o="$o $1"
+ shift
+ done
+ rm -f $tmp.exe
+ if compile $cc $ccflags $o -DTEST=$p -DID=$v -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout && $executable $tmp.exe
+ then case $run in
+
+ status*)execute $tmp.exe <&$nullin >&$nullout
+ V=$?
+ case $V in
+ 0) e=1 ;;
+ *) e=0 ;;
+ esac
+ break
+ ;;
+ no[ls]*);;
+ [ls]*) e=0 && break ;;
+ noo*) execute $tmp.exe <&$nullin >$tmp.out || break ;;
+ o*) execute $tmp.exe <&$nullin >$tmp.out && e=0 && break ;;
+ no*) execute $tmp.exe <&$nullin >&$nullout || break ;;
+ *) execute $tmp.exe <&$nullin >&$nullout && e=0 && break ;;
+
+ esac
+ else case $run in
+ no[els]*)e=1 && break ;;
+ esac
+ fi
+ case $# in
+ 0) case $run in
+ no*) e=0 ;;
+ esac
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ o=1
+ case $run in
+ no*) case $e in
+ 0) e=1 ;;
+ *) e=0 ;;
+ esac
+ ;;
+ esac
+ case $run in
+ o*|noo*)case $e in
+ 0) cat $tmp.out ;;
+ esac
+ rm -f $tmp.out
+ ;;
+ esac
+ report $e $V "${note:-$run\ passed}" "${note:-$run} failed"
+ continue
+ ;;
+ esac
+
+ # initialize common builtin state
+
+ case $o in
+ dat|lib|mth|run)
+ case $statictest in
+ "") statictest=FoobaR
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+_BEGIN_EXTERNS_
+extern int $statictest;
+_END_EXTERNS_
+int main(){char* i = (char*)&$statictest; return ((unsigned int)i)^0xaaaa;}
+"
+ rm -f $tmp.exe
+ if compile $cc -o $tmp.exe $tmp.c <&$nullin >&$nullout && $executable $tmp.exe
+ then case $static in
+ .) static=
+ copy $tmp.c "
+$tst
+$ext
+int main(){printf("hello");return(0);}
+"
+ rm -f $tmp.exe
+ if compile $cc -c $tmp.c <&$nullin >&$nullout &&
+ compile $cc -o $tmp.exe $tmp.o <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ then e=`wc -l $tmp.e`
+ eval set x x $binding
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f $tmp.exe
+ compile $cc -o $tmp.exe $1 $tmp.o <&$nullin >&$nullout && $executable $tmp.exe || continue
+ case `wc -l $tmp.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ d=`ls -s $tmp.exe`
+ rm -f $tmp.exe
+ compile $cc -o $tmp.exe $2 $tmp.o <&$nullin >&$nullout && $executable $tmp.exe || continue
+ case `wc -l $tmp.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case `ls -s $tmp.exe` in
+ $d) ;;
+ *) static=$2
+ set x
+ shift
+ break
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ else static=
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ # builtin tests
+
+ case $o in
+ api) ;;
+ cmd) case $p in
+ ?*) continue ;;
+ esac
+ is $o $a
+ k=1
+ for j in "" usr
+ do case $j in
+ "") d= s= ;;
+ *) d=/$j s=_$j ;;
+ esac
+ for i in bin etc ucb
+ do if test -f $d/$i/$a
+ then case $k in
+ 1) k=0
+ case $M in
+ *-*) ;;
+ *) usr="$usr$nl#define $m 1"
+ case $define in
+ 1) echo "#define $m 1 /* $a in ?(/usr)/(bin|etc|ucb) */" ;;
+ n) echo "$m=1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ c=${s}_${i}_${v}
+ usr="$usr$nl#define $c 1"
+ case $define in
+ 1) echo "#define $c 1 /* $d/$i/$a found */" ;;
+ n) echo "$c=1" ;;
+ esac
+ fi
+ done
+ done
+ case $k in
+ 0) success ;;
+ 1) failure ;;
+ esac
+ ;;
+ dat) case $p in
+ ?*) continue ;;
+ esac
+ {
+ copy - "
+$tst
+$ext
+$std
+$usr
+$pre
+"
+ case $inc in
+ ?*) echo "$inc"
+ ;;
+ *) echo "_BEGIN_EXTERNS_
+extern int $v;
+_END_EXTERNS_"
+ ;;
+ esac
+ echo "
+#ifdef _DLL
+#define _REF_
+#else
+#define _REF_ &
+#endif
+int main(){char* i = (char*) _REF_ $v; return ((unsigned int)i)^0xaaaa;}"
+ } > $tmp.c
+ is $o $v
+ rm -f $tmp.exe
+ compile $cc -c $tmp.c <&$nullin >&$nullout &&
+ compile $cc $static -o $tmp.exe $tmp.o $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ report $? 1 "$v in default lib(s)" "$v not in default lib(s)"
+ ;;
+ dfn) case $p in
+ ?*) continue ;;
+ esac
+ is dfn $v
+ echo "$pre
+$tst
+$ext
+$inc
+#ifdef $v
+<<\"#ifndef $v\">>
+<<\"#define $v\">> $v <<\"/* native $v */\">>
+<<\"#endif\">>
+#endif" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then sed -e '/<<[ ]*".*"[ ]*>>/!d' -e 's/<<[ ]*"//g' -e 's/"[ ]*>>//g' $tmp.i > $tmp.t
+ if test -s $tmp.t
+ then success
+ cat $tmp.t
+ else failure
+ fi
+ else failure
+ fi
+ ;;
+ exp) case $test in
+ '') echo "$command: $file$sline: test expression expected for $o" >&$stderr
+ exit 1
+ ;;
+ esac
+ case $a in
+ -|'') ;;
+ *) eval x='$'$a
+ case $x in
+ 1) result=FAILURE
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ case $test in
+ [01]|'"'*'"'|'<'*'>')
+ case $a in
+ -|'') ;;
+ *) case $define$note in
+ 1) echo "#define $a $test" ;;
+ 1*) echo "#define $a $test /* $note */" ;;
+ n) echo "$a=$test" ;;
+ esac
+ eval $a='$test'
+ ;;
+ esac
+ ;;
+ *) case $note in
+ '') note=$test ;;
+ esac
+ case $test in
+ '') c=1
+ ;;
+ *) is exp "$note"
+ x=
+ for i in `echo '' $test | sed 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], & ,g'`
+ do case $i in
+ [\ \ ])
+ ;;
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]*)
+ eval i='${'$i'}'
+ case $i in
+ '') i=0
+ ;;
+ '"'*'"');;
+ *[!-+0123456789]*)
+ case $i in
+ *'"'*) i=1 ;;
+ *) i='"'$i'"' ;;
+ esac
+ ;;
+ esac
+ x="$x $i"
+ ;;
+ '!') x="$x 0 ="
+ ;;
+ '&'|'|')case $x in
+ *"$i") ;;
+ *) x="$x \\$i" ;;
+ esac
+ ;;
+ *) x="$x \\$i"
+ ;;
+ esac
+ done
+ c=`eval expr $x 2>&$stderr`
+ ;;
+ esac
+ case $c in
+ 0) c=1 ;;
+ *) c=0 ;;
+ esac
+ M=$a
+ m=$a
+ report $c 1 "$note is true" "$note is false"
+ ;;
+ esac
+ ;;
+ hdr|lcl|nxt|sys)
+ case $o in
+ lcl|nxt)case $M in
+ *-*) continue ;;
+ esac
+ eval x='$'_$m
+ case $x in
+ ?*) continue ;;
+ esac
+ eval _$m=1
+ is $o $f
+ echo "$pre
+$tst
+$ext
+$inc
+#include <$f.h>" > $tmp.c
+ case $f in
+ sys/*) e= ;;
+ *) e='-e /[\\\\\/]sys[\\\\\/]'$f'\\.h"/d' ;;
+ esac
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then i=`sed -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:]*[\\\\\/].*[\\\\\/]'$f'\\.h"/!d' $e -e s'/.*"\\(.*\\)".*/\\1/' -e 's,\\\\,/,g' -e 's,///*,/,g' $tmp.i | sed 1q`
+ case $i in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]:[\\/]*)
+ ;;
+ */*/*) k=`echo "$i" | sed 's,.*/\([^/]*/[^/]*\)$,../\1,'`
+ echo "$pre
+$tst
+$ext
+$inc
+#include <$k>" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then j=`sed -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:]*[\\\\\/].*[\\\\\/]'$f'\\.h"/!d' $e -e s'/.*"\\(.*\\)".*/\\1/' -e 's,\\\\,/,g' -e 's,///*,/,g' $tmp.i | sed 1q`
+ wi=`wc < "$i"`
+ wj=`wc < "$j"`
+ case $wi in
+ $wj) i=$k ;;
+ esac
+ fi
+ ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+#include <../include/$f.h>" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >&$nullout
+ then i=../include/$f.h
+ fi
+ ;;
+ esac
+ else i=
+ fi
+ case $i in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]:[\\/]*|[\\/]*)
+ success
+ case $o in
+ lcl) echo "#if defined(__STDPP__directive)"
+ echo "__STDPP__directive pragma pp:hosted"
+ echo "#endif"
+ echo "#include <$i> /* the native <$f.h> */"
+ echo "#undef $m"
+ usr="$usr$nl#define $m 1"
+ echo "#define $m 1"
+ ;;
+ nxt) echo "#define $m <$i> /* include path for the native <$f.h> */"
+ echo "#define ${m}_str \"$i\" /* include string for the native <$f.h> */"
+ usr="$usr$nl#define $m <$i>$nl#define ${m}_str \"$i\""
+ eval $m=\\\<$i\\\>
+ ;;
+ esac
+ break
+ ;;
+ ../*/*) success
+ case $o in
+ lcl) echo "#include <$i> /* the native <$f.h> */"
+ echo "#undef $m"
+ usr="$usr$nl#define $m 1"
+ echo "#define $m 1"
+ eval $m=1
+ ;;
+ nxt) echo "#define $m <$i> /* include path for the native <$f.h> */"
+ echo "#define ${m}_str \"$i\" /* include string for the native <$f.h> */"
+ usr="$usr$nl#define $m <$i>$nl#define ${m}_str \"$i\""
+ eval $m=\\\<$i\\\>
+ ;;
+ esac
+ break
+ ;;
+ *) failure
+ case $o in
+ lcl) case $all$config$undef in
+ ?1?|??1)echo "#undef $m /* no native <$f.h> */" ;;
+ 1??) echo "#define $m 0 /* no native <$f.h> */" ;;
+ esac
+ eval $m=0
+ ;;
+ nxt) case $all$config$undef in
+ ?1?|??1)echo "#undef $m /* no include path for the native <$f.h> */" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $o in
+ hdr) x=$f.h ;;
+ sys) x=sys/$f.h ;;
+ esac
+ case " $gothdr " in
+ *" - $x "*)
+ failure +
+ ;;
+ *" + $x "*)
+ success +
+ ;;
+ *) echo "
+$tst
+$ext
+$allinc
+$inc
+#include <$x>" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ case $M in
+ *-*) ;;
+ *) case " $puthdr " in
+ *" $m "*)
+ ;;
+ *) puthdr="$puthdr $m"
+ usr="$usr$nl#define $m 1"
+ ;;
+ esac
+ case $define in
+ 1) echo "#define $m 1 /* #include <$x> ok */" ;;
+ n) echo "$m=1" ;;
+ esac
+ eval $m=1
+ ;;
+ esac
+ else gothdr="$gothdr - $x"
+ case $M in
+ *-*) ;;
+ *) case $define$all$config$undef in
+ 1?1?|1??1)echo "#undef $m /* #include <$x> not ok */" ;;
+ 11??) echo "#define $m 0 /* #include <$x> not ok */" ;;
+ n1?1) echo "$m=" ;;
+ n1??) echo "$m=0" ;;
+ esac
+ eval $m=0
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ ;;
+ iff) ;;
+ ini) ;;
+ key) case $p in
+ ?*) continue ;;
+ esac
+ w=$v
+ while :
+ do is $o $w
+ echo "$pre
+$tst
+$ext
+int f(){int $w = 1;return($w);}" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then failure
+ case $set in
+ *" ="|*" = "*)
+ set x $set
+ shift
+ w=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ =) break ;;
+ esac
+ case $w in
+ '') w=$1 ;;
+ *) w="$w $1" ;;
+ esac
+ shift
+ done
+ case $1 in
+ =) shift
+ case $# in
+ 0) set=" " ;;
+ *) set=$* ;;
+ esac
+ ;;
+ *) set=
+ ;;
+ esac
+ case $shell in
+ ksh) typeset -u u=$w ;;
+ *) u=`echo $w | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ u=_$u
+ M=$w
+ case $M in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ M=`echo "X$m" | sed -e 's,^.,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'`
+ ;;
+ esac
+ case $config in
+ 1) m=HAVE${u}_RESERVED ;;
+ *) m=_key_${w} ;;
+ esac
+ continue
+ ;;
+ esac
+ report - 1 - - "$w is not a reserved keyword" "default for reserved keyword $v"
+ else report 0 1 "$w is a reserved keyword" -
+ case $M in
+ *-*) ;;
+ *) case $define$w in
+ 1$v) ;;
+ 1*) echo "#define $v $w /* alternate for reserved keyword $v */" ;;
+ n*) echo "$v=$w" ;;
+ esac
+ ;;
+ esac
+ fi
+ break
+ done
+ ;;
+ lib|mth)case $p in
+ ?*) continue ;;
+ esac
+ case $v in
+ -) continue ;;
+ esac
+ is $o $v
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+typedef int (*_IFFE_fun)();
+#ifdef _IFFE_extern
+_BEGIN_EXTERNS_
+extern int $v();
+_END_EXTERNS_
+#endif
+static _IFFE_fun i=(_IFFE_fun)$v;int main(){return ((unsigned int)i)^0xaaaa;}
+"
+ d=-D_IFFE_extern
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then d=
+ elif compile $cc $d -c $tmp.c <&$nullin >&$nullout
+ then :
+ else d=error
+ fi
+ if test error != "$d"
+ then rm -f $tmp.exe
+ if compile $cc $d $static -o $tmp.exe $tmp.o $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ then case $o in
+ lib) c=0 ;;
+ *) c=1 ;;
+ esac
+ report $c 1 "$v() in default lib(s)" "$v() not in default lib(s)" "default for function $v()"
+ else case $o in
+ mth) rm -f $tmp.exe
+ compile $cc $d $static -o $tmp.exe $tmp.o -lm <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ report $? 1 "$v() in math lib" "$v() not in math lib" "default for function $v()"
+ ;;
+ *) report 1 1 - "$v() not in default lib(s)" "default for function $v()"
+ ;;
+ esac
+ fi
+ else case $intrinsic in
+ '') copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+_BEGIN_EXTERNS_
+extern int foo();
+_END_EXTERNS_
+static int ((*i)())=foo;int main(){return(i==0);}
+"
+ compile $cc -c $tmp.c <&$nullin >&$nullout
+ intrinsic=$?
+ ;;
+ esac
+ case $o in
+ mth) report $intrinsic 1 "$v() in math lib" "$v() not in math lib" "default for function $v()" ;;
+ *) report $intrinsic 1 "$v() in default lib(s)" "$v() not in default lib(s)" "default for function $v()" ;;
+ esac
+ fi
+ ;;
+ mac) case $p in
+ ?*) continue ;;
+ esac
+ is mac $v
+ echo "
+$tst
+$ext
+$pre
+$inc
+#ifdef $v
+'$m:$v'
+#endif" > $tmp.c
+ compile $cc -E $tmp.c <&$nullin | grep -c "'$m:$v'" >&$nullout
+ report $? 1 "$v is a macro" "$v is not a macro" "default for macro $v"
+ ;;
+ mem) case $p in
+ ?*) eval i='$'_iffe_typedef_$p
+ case $i in
+ 0|1) ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i);" > $tmp.c
+ is typ $p
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then success -
+ eval _iffe_typedef_$p=1
+ i=1
+ else failure -
+ eval _iffe_typedef_$p=0
+ i=0
+ fi
+ ;;
+ esac
+ case $i in
+ 0) i="$v is not a member of $p" p="struct $p" ;;
+ *) i=- ;;
+ esac
+ is mem $v "$p"
+ echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i.$v);" > $tmp.c
+ compile $cc -c $tmp.c <&$nullin >&$nullout
+ report $? 1 "$v is a member of $p" "$i"
+ ;;
+ *) p=$v
+ eval i='$'_iffe_typedef_$p
+ case $i in
+ 0|1) ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i);" > $tmp.c
+ is typ $p
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then success -
+ eval _iffe_typedef_$p=1
+ i=1
+ else failure -
+ eval _iffe_typedef_$p=0
+ i=0
+ fi
+ ;;
+ esac
+ case $i in
+ 0) i="$p is not a non-opaque struct" p="struct $p" ;;
+ *) i=- ;;
+ esac
+ is nos "$p"
+ echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i);" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+unsigned long f() { return (unsigned long)i; }" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then c=1
+ else c=0
+ fi
+ else c=1
+ fi
+ report $c 1 "$p is a non-opaque struct" "$i"
+ esac
+ ;;
+ nop) ;;
+ npt) is npt $v
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+_BEGIN_EXTERNS_
+struct _iffe_struct { int _iffe_member; };
+extern struct _iffe_struct* $v _ARG_((struct _iffe_struct*));
+_END_EXTERNS_
+"
+ # some compilers with -O only warn for invalid intrinsic prototypes
+ case " $cc " in
+ *" -O "*) xx=`echo $cc | sed 's/ -O / /g'` ;;
+ *) xx=$cc ;;
+ esac
+ compile $xx -c $tmp.c <&$nullin >&$nullout
+ report -$config $? 1 "$v() needs a prototype" "$v() does not need a prototype"
+ ;;
+ num) is num $v
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+_BEGIN_EXTERNS_
+int _iffe_int = $v / 2;
+_END_EXTERNS_
+"
+ compile $cc -c $tmp.c <&$nullin >&$nullout
+ report $? 1 "$v is a numeric constant" "$v is not a numeric constant"
+ ;;
+ one) for i in $a $hdr
+ do x="#include <$i>"
+ case " $gothdr " in
+ *" - $i "*)
+ continue
+ ;;
+ *" + $i "*)
+ ;;
+ *) echo "$x" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ else gothdr="$gothdr - $x"
+ continue
+ fi
+ ;;
+ esac
+ case $one in
+ "") one=$x
+ ;;
+ *"$x"*) break
+ ;;
+ *) echo "$one" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then c=$i
+ case $c in
+ *[\\/]*) c=`echo $c | sed 's,[\\\\/],[\\\\/],g'` ;;
+ esac
+ case `sed -e '/^#[line ]*1[ ][ ]*"[\\\\\/].*[\\\\\/]'$c'"/!d' $tmp.i` in
+ ?*) break ;;
+ esac
+ fi
+ one="$one$nl$x"
+ ;;
+ esac
+ echo "$x"
+ break
+ done
+ ;;
+ opt) M=$m
+ is opt $a
+ case " $PACKAGE_OPTIONS " in
+ *" $a "*) c=0 ;;
+ *) c=1 ;;
+ esac
+ report $c 1 "$a is set in \$PACKAGE_OPTIONS" "$a is not set in \$PACKAGE_OPTIONS"
+ ;;
+ out|output)
+ ;;
+ pth) is pth $a
+ pkg $pth
+ tab=" "
+ e=
+ f=
+ for i in $pth
+ do case $i in
+ '{') e="${nl}}"
+ l=
+ x=i
+ v="\$${x}"
+ t=${nl}${tab}
+ b="fnd()${nl}{${t}for ${x} in"
+ ;;
+ '}') b="${b}${t}do${tab}if $exists ${v}/\${1}${t}${tab}${tab}then${tab}f=${v}/\${1}${t}${tab}${tab}${tab}return${t}${tab}${tab}fi"
+ e="${t}done${e}"
+ eval "${b}${e}"
+ fnd $a
+ case $f in
+ ?*) break ;;
+ esac
+ ;;
+ -) b="${b}${t}do${tab}test \"${v}\" = '' -o -d \"${v}\" &&${t}${tab}${tab}"
+ x=${x}i
+ v="${v}\$${x}"
+ b="${b}for ${x} in"
+ e="${t}done${e}"
+ t="${t}${tab}${tab}"
+ ;;
+ *) case $e in
+ '') if $exists ${i}/${a}
+ then f=${i}/${a}
+ break
+ fi
+ ;;
+ *) case $i in
+ /|.) b="${b} ''" ;;
+ *) b="${b} /${i}" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $f in
+ '') case $set in
+ ' ') f=$a ;;
+ ?*) f=$set ;;
+ esac
+ ;;
+ esac
+ case $f in
+ '') c=1
+ ;;
+ *) c=0
+ f="\"$f\""
+ ;;
+ esac
+ report $c "$f" "${note:-$a path}" "$a path not found"
+ ;;
+ run) is run $a
+ if test ! -r $a
+ then failure not found
+ case $verbose in
+ 0) echo "$command: $file$line: $a: not found" >&$stderr ;;
+ esac
+ exit 1
+ fi
+ noisy
+ case $a in
+ *.c) rm -f $tmp.exe
+ {
+ echo "$tst
+$ext
+$std
+$usr
+$inc"
+ cat $a
+ } > $tmp.c
+ compile $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$stderr 2>&$stderr &&
+ $executable $tmp.exe &&
+ execute $tmp.exe $opt <&$nullin
+ ;;
+ *.sh) {
+ copy - ":
+set \"cc='$cc' executable='$executable' id='$m' static='$static' tmp='$tmp'\" $opt $hdr $test"
+ cat $a
+ } > $tmp.sh
+ chmod +x $tmp.sh
+ ( . $tmp.sh ) <&$nullin
+ ;;
+ *) false
+ ;;
+ esac
+ case $? in
+ 0) success
+ ;;
+ *) failure cannot run
+ case $verbose in
+ 0) echo "$command: $file$line: $a: cannot run" >&$stderr ;;
+ esac
+ exit 1
+ ;;
+ esac
+ ;;
+ siz) case $p in
+ "") x= ;;
+ *) x="$p " ;;
+ esac
+ is siz "$x$v"
+ {
+ case $p:$v in
+ long:*|*:*[_0123456789]int[_0123456789]*)
+ echo "$pre
+$tst
+$ext
+$inc
+static $x$v i;
+$x$v f() {
+$x$v v; i = 1; v = i;"
+ echo "i = v * i; i = i / v; v = v + i; i = i - v;"
+ case $v in
+ float|double) ;;
+ *) echo "v <<= 4; i = v >> 2; i = 10; i = v % i; i |= v; v ^= i; i = 123; v &= i;" ;;
+ esac
+ echo "return v; }"
+ ;;
+ *) echo "$pre
+$inc
+struct xxx { $x$v mem; };
+static struct xxx v;
+struct xxx* f() { return &v; }"
+ ;;
+ esac
+ case $x in
+ ""|"struct "|"union ")
+ echo "int g() { return 0; }"
+ ;;
+ *) echo "int g() { return sizeof($x$v)<=sizeof($v); }" ;;
+ esac
+ copy - "
+int main() {
+ f();
+ g();
+ printf(\"%u\\n\", sizeof($x$v));
+ return 0;
+}"
+ } > $tmp.c
+ rm -f $tmp.exe $tmp.dat
+ if compile $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe &&
+ execute $tmp.exe > $tmp.dat
+ then z=`cat $tmp.dat`
+ c=0
+ else z=0
+ c=1
+ fi
+ report $c "$z" "sizeof($x$v)" "$x$v not a type with known size"
+ ;;
+ sym) case $test in
+ "") x=$v ;;
+ *) x=$test ;;
+ esac
+ echo "$pre
+$tst
+$ext
+$inc
+'=' $x '='" > $tmp.c
+ compile $cc -E $tmp.c <&$nullin \
+ | sed \
+ -e "/'='/!d" \
+ -e "s/'='//g" \
+ -e 's/[ ]//g' \
+ -e 's/((([^()]*)))->/->/g' \
+ -e 's/(([^()]*))->/->/g' \
+ -e 's/([^()]*)->/->/g' \
+ -e 's/\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\)\[/\
+ary \1[/g' \
+ -e 's/\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\)(/\
+fun \1[/g' \
+ -e 's/\*->\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]\)/->\
+ptr \1/g' \
+ -e 's/->\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]\)/->\
+reg \1/g' \
+ -e "/^$v\$/d" \
+ -e 's/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*$/\
+nam &/g' \
+ | sed \
+ -e '/^... /!d' \
+ | LC_ALL=C sort \
+ -u \
+ | sed \
+ -e 's/\(...\) \([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\).*/#ifndef _\1_'$v'\
+#define _\1_'$v' \2\
+#define _\1_'$v'_str "\2"\
+#endif/'
+ ;;
+ typ) case $p in
+ "") x= ;;
+ *) x="$p " ;;
+ esac
+ is typ "$x$v"
+ {
+ case $p:$v in
+ long:*|*:*[_0123456789]int[_0123456789]*)
+ echo "$pre
+$tst
+$ext
+$inc
+static $x$v i;
+$x$v f() {
+$x$v v; i = 1; v = i;"
+ echo "i = v * i; i = i / v; v = v + i; i = i - v;"
+ case $v in
+ float|double) ;;
+ *) echo "v <<= 4; i = v >> 2; i = 10; i = v % i; i |= v; v ^= i; i = 123; v &= i;" ;;
+ esac
+ echo "return v; }"
+ ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+struct xxx { $x$v mem; };
+static struct xxx v;
+struct xxx* f() { return &v; }"
+ ;;
+ esac
+ case $x in
+ ""|"struct "|"union ")
+ echo "int main() { f(); return 0; }" ;;
+ *) echo "int main() { f(); return sizeof($x$v)<=sizeof($v); }" ;;
+ esac
+ } > $tmp.c
+ rm -f $tmp.exe
+ compile $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe &&
+ execute $tmp.exe
+ report $? 1 "$x$v is a type" "$x$v is not a type" "default for type $x$v"
+ ;;
+ val) case $arg in
+ '"'*'"')echo $arg=\'$val\' ;;
+ *) echo $arg=\"$val\" ;;
+ esac
+ ;;
+ ver) ;;
+ 0) result=FAILURE
+ ;;
+ 1) result=SUCCESS
+ ;;
+ :) ;;
+ -) ;;
+ *) echo "$command: $file$line: $o: unknown feature test" >&$stderr
+ status=1
+ ;;
+ esac
+ done
+ done
+ case $not in
+ 1) case $result in
+ FAILURE) result=SUCCESS ;;
+ *) result=FAILURE ;;
+ esac
+ ;;
+ esac
+ case $result in
+ FAILURE) user_pf=$fail user_yn=$no ;;
+ *) user_pf=$pass user_yn=$yes ;;
+ esac
+ case $user_pf in
+ ?*) eval "$user_pf" <&$nullin ;;
+ esac
+ case $user_yn in
+ ?*) case $def in
+ -) ;;
+ *) case $note in
+ ?*) case $user_yn in
+ *$nl*) user_yn="/* $note */$nl$user_yn" ;;
+ *) user_yn="$user_yn /* $note */" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ copy - "$user_yn"
+ ;;
+ esac
+ case $ifelse:$result in
+ TEST:SUCCESS) ifelse=KEEP ;;
+ TEST:*) ifelse=SKIP ;;
+ esac
+ case $group:$result in
+ :*|*:SUCCESS) break ;;
+ esac
+ set '' $groups '' "$@"
+ shift
+ case $1 in
+ '') shift; break ;;
+ esac
+ shift
+
+ # set up and try the next group
+
+ hdr=$com_hdr
+ lib=$com_lib
+ mac=$com_mac
+ opt=$com_opt
+ pth=$com_pth
+ test=$com_test
+ cc="$occ $includes"
+ group=
+ groups=
+ while :
+ do case $1 in
+ '') shift; break ;;
+ esac
+ case $1 in
+ *[\"\'\(\)\{\}\ \ ]*)
+ case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ -) group=$group$1
+ groups="$groups $1"
+ ;;
+ -l*) case $group in
+ -*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ +l*) case $shell in
+ bsh) x=`echo X$1 | sed 's/X+/-/'` ;;
+ *) eval 'x=-${1#+}' ;;
+ esac
+ case $group in
+ -*) groups="$groups $x" ;;
+ *) lib="$lib $x" ;;
+ esac
+ ;;
+ -*|+*) case $group in
+ -*) groups="$groups $1"
+ ;;
+ *) case $op in
+ run) opt="$opt $1"
+ ;;
+ *) case $1 in
+ -D*) mac="$mac $1" ;;
+ *) cc="$cc $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *.[aAxX]|*.[dD][lL][lL]|*.[lL][iI][bB])
+ case $group in
+ -*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ *[.\\/]*)
+ case $group in
+ -*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1" ;;
+ *) hdr="$hdr $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $group in
+ -*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ shift
+ done
+ done
+done
diff --git a/src/cmd/INIT/iffe.tst b/src/cmd/INIT/iffe.tst
new file mode 100644
index 0000000..115ef62
--- /dev/null
+++ b/src/cmd/INIT/iffe.tst
@@ -0,0 +1,1943 @@
+# regression tests for the iffe command
+
+TEST 01 'command line basics'
+
+ EXEC -r -v - hdr stdio
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - hdr stdio
+
+ EXEC -r -v - hdr stdio,limits
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _hdr_limits 1 /* #include <limits.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is limits.h a header ... yes'
+
+ EXEC -r -v -s bsh - hdr stdio,limits
+
+ EXEC -r -v - hdr,lib no_foo_bar,no_bar_foo stdio.h
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is no_foo_bar.h a header ... no
+iffe: test: is no_bar_foo.h a header ... no
+iffe: test: is no_foo_bar a library function ... no
+iffe: test: is no_bar_foo a library function ... no'
+
+ EXEC -r -v -s bsh - hdr,lib no_foo_bar,no_bar_foo stdio.h
+
+ EXEC -r -v - hdr no_foo_bar,no_bar_foo stdio.h : lib no_foo_bar,no_bar_foo stdio.h
+
+ EXEC -r -v -s bsh - hdr no_foo_bar,no_bar_foo stdio.h : lib no_foo_bar,no_bar_foo stdio.h
+
+TEST 02 'file input basics'
+
+ EXEC -r -v - t1.iffe
+ INPUT t1.iffe $'hdr stdio'
+ OUTPUT - $'/* : : generated from t1.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - t1.iffe
+
+ EXEC -r -v - t2.iffe
+ INPUT t2.iffe $'hdr stdio,limits'
+ OUTPUT - $'/* : : generated from t2.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _hdr_limits 1 /* #include <limits.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is limits.h a header ... yes'
+
+ EXEC -r -v -s bsh - t2.iffe
+
+ EXEC -r -v - t3.iffe
+ INPUT t3.iffe $'hdr,lib no_foo_bar,no_bar_foo stdio.h'
+ OUTPUT - $'/* : : generated from t3.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is no_foo_bar.h a header ... no
+iffe: test: is no_bar_foo.h a header ... no
+iffe: test: is no_foo_bar a library function ... no
+iffe: test: is no_bar_foo a library function ... no'
+
+ EXEC -r -v -s bsh - t3.iffe
+
+ EXEC -r -v - t3.iffe
+ INPUT t3.iffe $'hdr no_foo_bar,no_bar_foo stdio.h
+lib no_foo_bar,no_bar_foo stdio.h'
+
+ EXEC -r -v -s bsh - t3.iffe
+
+TEST 03 'nested if'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr stdio
+ if lib open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _lib_open 1 /* open() in default lib(s) */
+ HIT 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is open a library function ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr _XXX_stdio
+ if lib open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_limits 1 /* #include <limits.h> ok */
+HIT 4
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is _XXX_stdio.h a header ... no
+iffe: test: is limits.h a header ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr _XXX_stdio
+ if lib open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr _XXX_limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+HIT 5
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is _XXX_stdio.h a header ... no
+iffe: test: is _XXX_limits.h a header ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr stdio
+ if lib _XXX_open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _lib_close 1 /* close() in default lib(s) */
+ HIT 2
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is _XXX_open a library function ... no
+iffe: test: is close a library function ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr stdio
+ if lib _XXX_open {
+ HIT 1
+ }
+ elif lib _XXX_close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+ HIT 3
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is _XXX_open a library function ... no
+iffe: test: is _XXX_close a library function ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define _mem_st_atime_stat 1 /* st_atime is a member of struct stat */
+#define ATIME 1
+
+#define YESTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_atime a member of struct stat ... yes
+iffe: test: is ( !no_stat_time ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem foo_stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define _mem_st_ctime_stat 1 /* st_ctime is a member of struct stat */
+#define CTIME 1
+
+#define YESTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is foo_stat a type or typedef ... no
+iffe: test: is st_atime a member of struct foo_stat ... no
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_ctime a member of struct stat ... yes
+iffe: test: is ( !no_stat_time ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem foo_stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem foo_stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define _mem_st_mtime_stat 1 /* st_mtime is a member of struct stat */
+#define MTIME 1
+
+#define YESTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is foo_stat a type or typedef ... no
+iffe: test: is st_atime a member of struct foo_stat ... no
+iffe: test: is st_ctime a member of struct foo_stat ... no
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_mtime a member of struct stat ... yes
+iffe: test: is ( !no_stat_time ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem foo_stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem foo_stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem foo_stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define NOTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is foo_stat a type or typedef ... no
+iffe: test: is st_atime a member of struct foo_stat ... no
+iffe: test: is st_ctime a member of struct foo_stat ... no
+iffe: test: is st_mtime a member of struct foo_stat ... no
+iffe: test: is ( !no_stat_time ) true ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'set explicit
+iff previous
+hdr stdio
+if hdr stdio {
+ OK
+}
+else {
+ OK
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _previous_H
+#define _previous_H 1
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+OK
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 04 'test variable/macro override'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+HAVE_STDIO = hdr stdio'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if hdr - stdio {
+ #define HIT 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HIT 1
+
+#endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if - hdr stdio {
+ #define HIT 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if ? hdr stdio {
+ #define HIT 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if hdr - stdio {
+ #define HIT 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if HAVE_STDIO = hdr stdio {
+ #define HIT 1
+}
+endif
+if ( HAVE_STDIO ) {
+ #define TOO ALSO
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#define HIT 1
+
+#define TOO ALSO
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is ( HAVE_STDIO ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if HAVE_STDIO = hdr stdio {
+ #define HIT 1
+}
+endif
+exp ALSO HAVE_STDIO'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#define HIT 1
+
+#define ALSO 1 /* HAVE_STDIO is true */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is HAVE_STDIO true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if HAVE_STDIO = hdr stdio {
+ #define HIT 1
+}
+endif
+ALSO = ( HAVE_STDIO )'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#define HIT 1
+
+#define ALSO 1 /* ( HAVE_STDIO ) is true */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is ( HAVE_STDIO ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 05 'test code option sequence'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 1 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _seq 1 /* long int type */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 2
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 1 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+/* long int type */
+#define seq 1
+
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 2
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+/* long int type */
+#define seq 1
+
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 2
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 3
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ...
+iffe: test: long int type ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 06 'block side effects'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff -
+tst output{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 0;
+ }
+}end'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#define _sys_types 1 /* #include <sys/types.h> ok */
+HIT'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff
+tst - output{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 0;
+ }
+}end'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff
+tst - output{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 1;
+ }
+}end'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff
+tst - nooutput{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 1;
+ }
+}end'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#define _sys_types 1 /* #include <sys/types.h> ok */
+HIT'
+
+ EXEC -r -s bsh - t.iffe
+
+TEST 07 'diagnostics'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'tst foo'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - $'iffe: t.iffe:1: tst: unknown feature test'
+ EXIT 1
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'if (1)'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+ ERROR - $'iffe: t.iffe:1: missing endif'
+ EXIT 1
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'if'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+ ERROR - $'iffe: t.iffe:1: missing endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'endif'
+ ERROR - $'iffe: t.iffe:1: endif: no matching if'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'if {
+}end'
+ ERROR - $'iffe: t.iffe:2: missing }'
+
+ EXEC -r -s bsh - t.iffe
+
+TEST 08 'negation consternation'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'npt fopen,fooon stdio.h'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _npt_fooon 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -u - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#undef _npt_fopen /* fopen() does not need a prototype */
+#define _npt_fooon 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -a - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _npt_fopen 0 /* fopen() does not need a prototype */
+#define _npt_fooon 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -C - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define HAVE_SYS_TYPES_H 1 /* #include <sys/types.h> ok */
+#define HAVE_STDLIB_H 1 /* #include <stdlib.h> ok */
+#define HAVE_UNISTD_H 1 /* #include <unistd.h> ok */
+#define HAVE_STDIO_H 1 /* #include <stdio.h> ok */
+#define HAVE_FOPEN_DECL 1 /* fopen() does not need a prototype */
+#undef HAVE_FOOON_DECL /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'NEED_FOPEN = npt fopen stdio.h
+HAVE_FOPEN = ! npt fopen stdio.h
+NEED_FOOON = npt fooon stdio.h
+HAVE_FOOON = ! npt fooon stdio.h'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define HAVE_FOPEN 1 /* fopen() does not need a prototype */
+#define NEED_FOOON 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -u - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#undef NEED_FOPEN /* fopen() does not need a prototype */
+#define HAVE_FOPEN 1 /* fopen() does not need a prototype */
+#define NEED_FOOON 1 /* fooon() needs a prototype */
+#undef HAVE_FOOON /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -C - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define HAVE_SYS_TYPES_H 1 /* #include <sys/types.h> ok */
+#define HAVE_STDLIB_H 1 /* #include <stdlib.h> ok */
+#define HAVE_UNISTD_H 1 /* #include <unistd.h> ok */
+#define HAVE_STDIO_H 1 /* #include <stdio.h> ok */
+#undef NEED_FOPEN /* fopen() does not need a prototype */
+#define HAVE_FOPEN 1 /* fopen() does not need a prototype */
+#define NEED_FOOON 1 /* fooon() needs a prototype */
+#undef HAVE_FOOON /* fooon() needs a prototype */
+#endif'
+
+TEST 09 'exp vs. if'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_false {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_false is true */
+/* !_tst_false */
+ONE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&_tst_true is true */
+TWO 0 1
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&_tst_true is true */
+/* !_tst_hit&_tst_true */
+THREE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_false {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_false {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_false is true */
+/* !_tst_false */
+ONE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&&_tst_true is true */
+TWO 0 1
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&&_tst_true is true */
+/* !_tst_hit&&_tst_true */
+THREE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_false {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_false ) {
+ ONE
+}
+elif ( _tst_true ) pass{
+cat <<!
+ TWO
+!
+}end
+else {
+ THREE
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+ONE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ ONE
+}
+elif ( _tst_true ) pass{
+cat <<!
+ TWO
+!
+}end
+else {
+ THREE
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+TWO
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ ONE
+}
+elif ( _tst_false ) pass{
+cat <<!
+ TWO
+!
+}end
+else {
+ THREE
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+THREE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) yes{
+ typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ } DIR;
+}end
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ } DIR;
+}
+else {
+ OK
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+OK
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ };
+}
+else {
+ OK
+}
+endif'
+
+ EXEC -r -s bsh - t.iffe
+
+TEST 10 'exp details'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'_str = "string"
+_hdr = <header>
+_aaa = ( 0 )
+_zzz = ( 1 )
+( _str )
+( ! _str )
+( _hdr )
+( ! _hdr )
+( _aaa )
+( ! _aaa )
+( _zzz )
+( ! _zzz )'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _str "string"
+#define _hdr <header>
+#define _zzz 1 /* ( 1 ) is true */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( 0 ) true ... no
+iffe: test: is ( 1 ) true ... yes
+iffe: test: is ( _str ) true ... yes
+iffe: test: is ( ! _str ) true ... no
+iffe: test: is ( _hdr ) true ... yes
+iffe: test: is ( ! _hdr ) true ... no
+iffe: test: is ( _aaa ) true ... no
+iffe: test: is ( ! _aaa ) true ... yes
+iffe: test: is ( _zzz ) true ... yes
+iffe: test: is ( ! _zzz ) true ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 11 'set [no]define'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'set nodefine
+mem stat.st_mtime sys/types.h sys/stat.h
+set define
+mem stat.st_mode sys/types.h sys/stat.h
+if ( _mem_st_mtime_stat ) {
+ 1
+}
+endif
+if ( _mem_st_mode_stat ) {
+ 2
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _mem_st_mode_stat 1 /* st_mode is a member of struct stat */
+1
+
+2
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_mtime a member of struct stat ... yes
+iffe: test: is st_mode a member of struct stat ... yes
+iffe: test: is ( _mem_st_mtime_stat ) true ... yes
+iffe: test: is ( _mem_st_mode_stat ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 12 'non-opaque mem'
+
+ EXEC -r -v - mem OPAQUE -I. t.h
+ INPUT t.h $'typedef struct opaque OPAQUE;'
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_t 1 /* #include <t.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is t.h a header ... yes
+iffe: test: is OPAQUE a type or typedef ... no
+iffe: test: is struct OPAQUE a non-opaque struct ... no'
+
+ EXEC -r -v - mem NONOPAQUE -I. t.h
+ INPUT t.h $'struct nonopaque { int pad; };
+typedef struct nonopaque NONOPAQUE;'
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_t 1 /* #include <t.h> ok */
+#define _mem_NONOPAQUE 1 /* NONOPAQUE is a non-opaque struct */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is t.h a header ... yes
+iffe: test: is NONOPAQUE a type or typedef ... yes
+iffe: test: is NONOPAQUE a non-opaque struct ... yes'
+
+TEST 13 'key states'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'key int
+key const =
+key foo
+key bar =
+key aha = huh = int
+key chr = char = int'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _key_int 1 /* int is a reserved keyword */
+#define _key_const 1 /* const is a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#define aha int /* default for reserved keyword aha */
+#define _key_char 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is int a reserved keyword ... yes
+iffe: test: is const a reserved keyword ... yes
+iffe: test: is foo a reserved keyword ... no
+iffe: test: is bar a reserved keyword ... no
+iffe: test: is aha a reserved keyword ... no
+iffe: test: is huh a reserved keyword ... no
+iffe: test: is chr a reserved keyword ... no
+iffe: test: is char a reserved keyword ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -u -r -v - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _key_int 1 /* int is a reserved keyword */
+#define _key_const 1 /* const is a reserved keyword */
+#undef _key_foo /* foo is not a reserved keyword */
+#undef _key_bar /* bar is not a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#undef _key_huh /* huh is not a reserved keyword */
+#define aha int /* default for reserved keyword aha */
+#define _key_char 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+
+ EXEC -u -r -v -s bsh - t.iffe
+
+ EXEC -a -r -v - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _key_int 1 /* int is a reserved keyword */
+#define _key_const 1 /* const is a reserved keyword */
+#define _key_foo 0 /* foo is not a reserved keyword */
+#define _key_bar 0 /* bar is not a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#define _key_huh 0 /* huh is not a reserved keyword */
+#define aha int /* default for reserved keyword aha */
+#define _key_char 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+
+ EXEC -a -r -v -s bsh - t.iffe
+
+ EXEC -C -r -v - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define HAVE_SYS_TYPES_H 1 /* #include <sys/types.h> ok */
+#define HAVE_INT_RESERVED 1 /* int is a reserved keyword */
+#define HAVE_CONST_RESERVED 1 /* const is a reserved keyword */
+#undef HAVE_FOO_RESERVED /* foo is not a reserved keyword */
+#undef HAVE_BAR_RESERVED /* bar is not a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#undef HAVE_HUH_RESERVED /* huh is not a reserved keyword */
+#define aha int /* default for reserved keyword aha */
+#define HAVE_CHAR_RESERVED 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+
+ EXEC -C -r -v -s bsh - t.iffe
+
+TEST 14 'inc file'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc t_lib.h
+if ( bar_foo ) {
+ #define all 1
+}
+elif ( _foo_bar ) {
+ #define some 1
+}
+endif'
+ INPUT t_lib.h '#define bar_foo ALL
+#define _foo_bar SOME'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define some 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( bar_foo ) true ... no
+iffe: test: is ( _foo_bar ) true ... yes'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc t_lib.h .
+if ( bar_foo ) {
+ #define all 1
+}
+elif ( _foo_bar ) {
+ #define ok 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define all 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( bar_foo ) true ... yes'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc t_lib.h . ?
+if ( bar_foo ) {
+ #define all 1
+}
+elif ( _foo_bar ) {
+ #define ok 1
+}
+endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: t.iffe:1: warning: ?: operands ignored
+iffe: test: is ( bar_foo ) true ... yes'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc foo_lib.h'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: t.iffe:1: foo_lib.h: file not found'
+ EXIT 1
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: t.iffe:1: path expected'
+
+TEST 15 'KnR compatibility'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'
+if ( 1 ) {
+ #define all 1
+}
+endif
+if ( 2 ) {
+ #define some 1
+}
+endif
+cat{
+#define a 1
+ #define b 2
+ #define c 3
+ #define d 4
+}end'
+#define _foo_bar SOME'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define some 1
+
+#endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define all 1
+
+#define some 1
+
+#define a 1
+#define b 2
+#define c 3
+#define d 4
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( 1 ) true ... yes
+iffe: test: is ( 2 ) true ... yes
+iffe: test: cat{ ... }end ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v -s osh - t.iffe
+
+TEST 16 '{ define extern include print }'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'
+print /* test header */
+header stdio.h
+define EOF -1
+define FoobaR (a,b) ((a)+(b))
+define FoomaC -1
+extern fopen FILE* (char*, char*)
+extern BarfoO struct barfoo* (int)
+extern Tab_lE struct barfoo* [10]'
+ OUTPUT - $'/* test header */
+/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#include <stdio.h>
+#define FoobaR(a,b) ((a)+(b))
+#define FoomaC -1
+extern struct barfoo* BarfoO(int);
+extern struct barfoo* Tab_lE[10];
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is EOF a macro ... yes
+iffe: test: is FoobaR a macro ... no
+iffe: test: is FoomaC a macro ... no
+iffe: test: is fopen a symbol that needs a prototype ... no
+iffe: test: is BarfoO a symbol that needs a prototype ... yes
+iffe: test: is Tab_lE a symbol that needs a prototype ... yes'
+
+TEST 17 'features/* => FEATURE/*'
+
+ EXEC -r -v run features/stdio
+ INPUT features/stdio $'set prototyped
+header stdio.h'
+ OUTPUT FEATURE/stdio $'
+/* : : generated by proto : : */
+/* : : generated from features/stdio by iffe version 1995-03-19 : : */
+
+#ifndef _REGRESS
+#if !defined(__PROTO__)
+# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
+# if defined(__cplusplus)
+# define __LINKAGE__ "C"
+# else
+# define __LINKAGE__
+# endif
+# define __STDARG__
+# define __PROTO__(x) x
+# define __OTORP__(x)
+# define __PARAM__(n,o) n
+# if !defined(__STDC__) && !defined(__cplusplus)
+# if !defined(c_plusplus)
+# define const
+# endif
+# define signed
+# define void int
+# define volatile
+# define __V_ char
+# else
+# define __V_ void
+# endif
+# else
+# define __PROTO__(x) ()
+# define __OTORP__(x) x
+# define __PARAM__(n,o) o
+# define __LINKAGE__
+# define __V_ char
+# define const
+# define signed
+# define void int
+# define volatile
+# endif
+# define __MANGLE__ __LINKAGE__
+# if defined(__cplusplus) || defined(c_plusplus)
+# define __VARARG__ ...
+# else
+# define __VARARG__
+# endif
+# if defined(__STDARG__)
+# define __VA_START__(p,a) va_start(p,a)
+# else
+# define __VA_START__(p,a) va_start(p)
+# endif
+# if !defined(__INLINE__)
+# if defined(__cplusplus)
+# define __INLINE__ extern __MANGLE__ inline
+# else
+# if defined(_WIN32) && !defined(__GNUC__)
+# define __INLINE__ __inline
+# endif
+# endif
+# endif
+#endif
+#if !defined(__LINKAGE__)
+#define __LINKAGE__ /* 2004-08-11 transition */
+#endif
+
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#include <stdio.h>
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+TEST 18 'api + ver'
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff api
+ver foo 20100606
+ver bar 19840919
+
+api foo 19991231 dis dat tother
+api foo 20100601 dat
+api foo 20100606 dis
+api bar 19991231 moe larry shemp
+api bar 20020202 curly
+api bar 20030303 shemp
+api bar 20040404 joe_b
+api bar 20050505 joe_d
+'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _api_H
+#define _api_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+
+#define FOO_VERSION 20100606
+#define BAR_VERSION 19840919
+
+#if !defined(_API_foo) && defined(_API_DEFAULT)
+#define _API_foo _API_DEFAULT
+#endif
+
+#if ( _BLD_foo || !_API_foo || _API_foo >= 20100601 )
+#undef dat
+#define dat dat_20100601
+#elif _API_foo >= 19991231
+#undef dat
+#define dat dat_19991231
+#endif
+
+#if ( _BLD_foo || !_API_foo || _API_foo >= 20100606 )
+#undef dis
+#define dis dis_20100606
+#elif _API_foo >= 19991231
+#undef dis
+#define dis dis_19991231
+#endif
+
+#if ( _BLD_foo || !_API_foo || _API_foo >= 19991231 )
+#undef tother
+#define tother tother_19991231
+#endif
+
+#define _API_foo_MAP "dat_20100601 dat_19991231 dis_20100606 dis_19991231 tother_19991231"
+
+#if !defined(_API_bar) && defined(_API_DEFAULT)
+#define _API_bar _API_DEFAULT
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20020202 )
+#undef curly
+#define curly curly_20020202
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20040404 )
+#undef joe_b
+#define joe_b joe_b_20040404
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20050505 )
+#undef joe_d
+#define joe_d joe_d_20050505
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 19991231 )
+#undef larry
+#define larry larry_19991231
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 19991231 )
+#undef moe
+#define moe moe_19991231
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20030303 )
+#undef shemp
+#define shemp shemp_20030303
+#elif _API_bar >= 19991231
+#undef shemp
+#define shemp shemp_19991231
+#endif
+
+#define _API_bar_MAP "curly_20020202 joe_b_20040404 joe_d_20050505 larry_19991231 moe_19991231 shemp_20030303 shemp_19991231"
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes'
diff --git a/src/cmd/INIT/ignore.sh b/src/cmd/INIT/ignore.sh
new file mode 100644
index 0000000..2999645
--- /dev/null
+++ b/src/cmd/INIT/ignore.sh
@@ -0,0 +1,43 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+# non-ksh script for the nmake ignore prefix
+# @(#)ignore (AT&T Research) 1992-08-11
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
+exit 0
diff --git a/src/cmd/INIT/intl.c b/src/cmd/INIT/intl.c
new file mode 100644
index 0000000..1623dd6
--- /dev/null
+++ b/src/cmd/INIT/intl.c
@@ -0,0 +1,29 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef gettext
+#include <libintl.h>
+#endif
+
+int
+main()
+{
+ gettext(0);
+ return 0;
+}
diff --git a/src/cmd/INIT/ld.hp.pa b/src/cmd/INIT/ld.hp.pa
new file mode 100755
index 0000000..99d39f0
--- /dev/null
+++ b/src/cmd/INIT/ld.hp.pa
@@ -0,0 +1,5 @@
+: hp.pa ld wrapper for reasonable warning defaults
+
+# @(#)ld.hp.pa (AT&T Labs Research) 1998-01-23
+
+/bin/ld +s +vnocompatwarnings "$@"
diff --git a/src/cmd/INIT/ldd.cygwin.i386 b/src/cmd/INIT/ldd.cygwin.i386
new file mode 100755
index 0000000..5976b1f
--- /dev/null
+++ b/src/cmd/INIT/ldd.cygwin.i386
@@ -0,0 +1,22 @@
+#!/bin/env sh
+: cygwin.i386 ldd -- how many ways does this confirm the windows bias?
+for f
+do case $f in
+ *.exe) ;;
+ *) f=$f.exe ;;
+ esac
+ p=$(type $f)
+ case $p in
+ *" not found"*)
+ ;;
+ *) p=${p##* }
+ case $p in
+ ?*) f=$p ;;
+ esac
+ ;;
+ esac
+ cygcheck $(cygpath -aw $f) |
+ for w in $(sed -e 's/^[[:space:]]*//' -e '/^$/d' -e '/^Use /d')
+ do cygpath -u "$w"
+ done
+done
diff --git a/src/cmd/INIT/ldd.darwin b/src/cmd/INIT/ldd.darwin
new file mode 100755
index 0000000..ec75f7b
--- /dev/null
+++ b/src/cmd/INIT/ldd.darwin
@@ -0,0 +1,2 @@
+: mac os10 ldd
+otool -L "$@"
diff --git a/src/cmd/INIT/ldd.hp.pa b/src/cmd/INIT/ldd.hp.pa
new file mode 100755
index 0000000..34874b4
--- /dev/null
+++ b/src/cmd/INIT/ldd.hp.pa
@@ -0,0 +1,21 @@
+: hp.pa ldd
+while :
+do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -*|+*) ;;
+ *) break ;;
+ esac
+ shift
+done
+trap ':' 15
+for cmd
+do case $# in
+ 1) ;;
+ *) echo $cmd: ;;
+ esac
+ _HP_DLDOPTS=-ldd "$cmd" < /dev/null 2> /dev/null | sort -u
+ # chatr "$cmd" |
+ # sed -e '/^[ ]*dynamic[ ][ ]*/!d' -e 's// /'
+done
diff --git a/src/cmd/INIT/ldd.ibm.risc b/src/cmd/INIT/ldd.ibm.risc
new file mode 100755
index 0000000..984ef6d
--- /dev/null
+++ b/src/cmd/INIT/ldd.ibm.risc
@@ -0,0 +1,16 @@
+: ibm.risc ldd
+case $# in
+1) header=0 ;;
+*) header=1 ;;
+esac
+for file
+do case $header in
+ 1) echo "$file:"
+ header=2
+ ;;
+ 2) echo
+ echo "$file:"
+ ;;
+ esac
+ dump -H "$file" | sed '1,/\*\*\*Import/d'
+done
diff --git a/src/cmd/INIT/ldd.lynxos b/src/cmd/INIT/ldd.lynxos
new file mode 100755
index 0000000..43904a8
--- /dev/null
+++ b/src/cmd/INIT/ldd.lynxos
@@ -0,0 +1 @@
+elflook -L "$@" | sed -e '/^NEEDED:/!d' -e 's/.*: *//'
diff --git a/src/cmd/INIT/ldd.mvs.390 b/src/cmd/INIT/ldd.mvs.390
new file mode 100755
index 0000000..341c4cc
--- /dev/null
+++ b/src/cmd/INIT/ldd.mvs.390
@@ -0,0 +1,18 @@
+: mvs.390 ldd
+case $# in
+1) header=0 ;;
+*) header=1 ;;
+esac
+for file
+do case $header in
+ 1) echo "$file:"
+ header=2
+ ;;
+ 2) echo
+ echo "$file:"
+ ;;
+ esac
+ strings $file |
+ sed -e '/\<[[:lower:]][[:alnum:]]*\.dll\>/!d' -e 's/^/ /' |
+ sort -u
+done
diff --git a/src/cmd/INIT/ldd.sgi b/src/cmd/INIT/ldd.sgi
new file mode 100755
index 0000000..d3c5347
--- /dev/null
+++ b/src/cmd/INIT/ldd.sgi
@@ -0,0 +1,2 @@
+: sgi.mips ldd
+odump -Dl "$@"
diff --git a/src/cmd/INIT/m.c b/src/cmd/INIT/m.c
new file mode 100644
index 0000000..b56b99b
--- /dev/null
+++ b/src/cmd/INIT/m.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #1
+ */
+
+#ifndef sin
+#include <math.h>
+#endif
+
+int
+main()
+{
+ sin(0.0);
+ fmod(100.234, 11.0);
+ return 0;
+}
diff --git a/src/cmd/INIT/m2.c b/src/cmd/INIT/m2.c
new file mode 100644
index 0000000..cad12b1
--- /dev/null
+++ b/src/cmd/INIT/m2.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #2
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ double value = 0;
+ int exp = 0;
+ int r = 0;
+
+ r |= ldexp(value, exp) != 0;
+ r |= frexp(value, &exp) != 0;
+ return r;
+}
diff --git a/src/cmd/INIT/m3.c b/src/cmd/INIT/m3.c
new file mode 100644
index 0000000..5d89991
--- /dev/null
+++ b/src/cmd/INIT/m3.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #3
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ long double value = 0;
+ int exp = 0;
+ int r = 0;
+
+ r |= ldexpl(value, exp) != 0;
+ r |= frexpl(value, &exp) != 0;
+ return r;
+}
diff --git a/src/cmd/INIT/m4.c b/src/cmd/INIT/m4.c
new file mode 100644
index 0000000..79b87f0
--- /dev/null
+++ b/src/cmd/INIT/m4.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #4
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ double value = 0;
+
+ return isnan(value);
+}
diff --git a/src/cmd/INIT/m5.c b/src/cmd/INIT/m5.c
new file mode 100644
index 0000000..f853921
--- /dev/null
+++ b/src/cmd/INIT/m5.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #5
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ long double value = 0;
+
+ return isnanl(value);
+}
diff --git a/src/cmd/INIT/m6.c b/src/cmd/INIT/m6.c
new file mode 100644
index 0000000..4387ea0
--- /dev/null
+++ b/src/cmd/INIT/m6.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #6
+ */
+
+#define _ISOC99_SOURCE 1
+
+#include <math.h>
+
+int
+main()
+{
+ double value = -0.0;
+
+ return !signbit(value);
+}
diff --git a/src/cmd/INIT/make.probe b/src/cmd/INIT/make.probe
new file mode 100644
index 0000000..8a3c383
--- /dev/null
+++ b/src/cmd/INIT/make.probe
@@ -0,0 +1,2242 @@
+:
+### this script contains archaic constructs that work with all sh variants ###
+# Glenn Fowler
+# AT&T Research
+#
+# @(#)make.probe (AT&T Research) 2011-06-01
+#
+# C probe for make
+#
+# NOTE: C.probe must be included or .'d here
+#
+
+cc_dll_def=-D_BLD_DLL
+
+probe_ar_arflags="-Xany"
+probe_arflags="-xar"
+probe_ccs="strip size nm ld ar" # longest to shortest
+probe_debug="-g"
+probe_dll="'-G 0' -Wc,dll,exportall,longname,rent -Wc,exportall -dynamic $cc_dll_def"
+probe_export_dynamic="-rdynamic -export-dynamic -Wl,-export-dynamic -Wl,-E -bexpall -force_flat_namespace"
+probe_gcc_optimize="-O2"
+probe_gcc_version="*[Gg][Cc][Cc]*"
+probe_include_local="'-ignore-source-dir -iquote' -iquote -I-"
+probe_ldlazy='-zlazyload -znolazyload -Wl,-zlazyload -Wl,-znolazyload'
+probe_ldlib="LD_LIBRARY_PATH LIBPATH LPATH"
+probe_ldmap="'-Wl,-M' '-Qoption ld -M' '-Wl,-m' '-m'"
+probe_ldorigin="-Wl,-z,origin"
+probe_ldrecord='-zrecord -zignore -Wl,-zrecord -Wl,-zignore'
+probe_ldrunpath="-Wl,-R, -R -Wl,-rpath, -L"
+probe_ldstrip="'-s -mr' -Wl,-s"
+probe_lib="a lib"
+probe_lib_append="/usr/lib/pa1.1"
+probe_lib_all_undef="-all -notall -all -none -Bwhole-archive -Bno-whole-archive -whole-archive -no-whole-archive -Wl,-whole-archive -Wl,-no-whole-archive -all_load '' -Wl,-zallextract -Wl,-zdefaultextract +forceload +noforceload"
+probe_lib_multiple="-Wl,-zmuldefs"
+probe_libdir="shlib lib"
+probe_nmflags="'' -p -B"
+probe_optimize="-O"
+probe_pic="-Kpic -KPIC -fpic -fPIC -pic -PIC +z +Z"
+probe_no_protect="'-fno-stack-protector -fno-stack-protector-all' -GS-"
+probe_readonly="-R -Krodata -xMerge -Wa,-r"
+probe_shared="'' -G -b -c -shared -Wl,dll"
+probe_shared_name="-Wl,-soname= -h"
+probe_shared_nostart="-nostartfiles"
+probe_shared_registry='"-update_registry $probe_shared_registry_file"'
+probe_shared_registry_file='registry.ld'
+probe_shared_registry_path="\$(LIBDIR)/$probe_shared_registry_file"
+probe_strict="'-ansi -pedantic' '-ansi -strict' -strict -ansi"
+probe_stripflags="'-f -s' -f -s"
+probe_unresolved="'-expect_unresolved \"*\"'"
+probe_warn="-Wall -fullwarn -w3 '-A -A' +w1"
+
+echo '#pragma pp:version' > libpp.$src
+echo '#define dDflag on' > dDflag.$src
+echo 'int main(){return 0;}' > doti.$src
+echo 'int code(){return 0;} int main(){return code();}' > export.$src
+echo '#include <stdio.h>' > imstd.$src
+echo '#include "_i_.h"' > imusr.$src
+echo 'int x;' > _i_.h
+mkdir im
+echo '(' > im/stdio.h
+echo '#include "implc_x.h"
+int main(){f(1);return 0;}' > implc.$src
+echo 'template <class T> void f(T){}' > implc_x.$src
+echo 'template <class T> void f(T);' > implc_x.h
+echo 'extern int NotalL(){return(0);}' > notall.$src
+echo '#include <stdio.h>
+extern int i;
+int i = 1;
+extern int f(){return(!i);}
+int main(){FILE* fp=stdin;return(f());}' > pic.$src
+echo 'class x {int n;} m;' > plusplus.$src
+echo 'int prefix(){return 0;}' > prefix.$src
+echo 'template<class T> int gt(T a, T b);
+template<class T> int gt(T a, T b) { return a > b; }
+int main () { return gt(2,1); }' > ptr.$src
+echo 'int main(){return 0;}' > require.$src
+echo '#if mips && !sgi || __CYGWIN__
+( /* some systems choke on this probe */
+#else
+#if test_const
+#define CONST const
+#else
+#define CONST
+#endif
+CONST char x[]={1,2,3,4,5,6,7,8,9,0};
+int main(){*(char*)x=0; return x[0];}
+#endif' > readonly.$src
+# NOTE: sfclose() defined on uwin, not defined on all other systems
+echo 'extern int sfclose(); extern int ShareD(){return(sfclose());}' > shared.$src
+echo '#define g(a,b) a ## b
+volatile int a;
+const int g(x,y)=1;
+extern int c(int);' > stdc.$src
+echo 'extern int f(); int main() { return f(); }' > sovmain.$src
+echo 'int f() { return 0; }' > sovlib.$src
+echo '#include <stdio.h>
+int i;
+int main(){int j;j = i * 10;return j;}' > strip.$src
+echo 'template <class T> void f(T){}
+int main(){f(1);return 0;}' > toucho.$src
+echo '#if defined(__STDC__) || defined(__cplusplus)
+extern type call(int);
+#endif
+int main() {call(0);return(0);}' > tstlib.$src
+echo 'int main(){return 0;}' > warn.$src
+echo 'int f(){return 0;}' > warn1.$src
+echo 'int f(){}' > warn2.$src
+echo 'int f(){int i; return 0;}' > warn3.$src
+echo 'int f(){int i; return i;}' > warn4.$src
+echo 'int f(){return g();}' > warn5.$src
+warn_enum="1 2 3 4 5"
+
+chmod -w *.$src
+
+ar_arflags=
+arflags=
+cc_dll=
+cc_pic=
+cc_PIC=
+dDflag=
+debug=
+dialect=
+dll_dir='$(LIBDIR)'
+dll_libraries=
+dll_variants=
+doti=
+exectype=
+export_dynamic=
+gnu=
+implicitc=
+include_local=
+lddynamic=
+ldlazy=
+ldnolazy=
+ldnorecord=
+ldorigin=
+ldrecord=
+ldrunpath=
+ldscript=
+ldstatic=
+ldstrip=
+Lflag=
+lib_dll=
+lib_all=
+lib_undef=
+libpath=
+libpp=
+makeoptions=
+nmedit=
+nmflags=
+no_protect=
+optimize=
+plusplus=
+prefix_archive=lib
+prefix_dynamic=
+prefix_shared=lib
+ptrcopy=
+ptrimplicit=
+ptrmkdir=
+readonly=
+repository=
+require=
+runpath=
+shared=
+shared_name=
+shared_registry=
+shellmagic=
+soversion=
+stdc=
+strict=
+stripflags=
+symprefix=
+toucho=
+warn=
+
+set $probe_lib
+lib=$1
+
+d=
+for f in $stdinclude $usrinclude
+do case $f in
+ -I*) ;;
+ *) d="$d $f" ;;
+ esac
+done
+stdinclude=$d
+
+set x $cc
+cc_dir=`echo $2 | sed -e 's,/*[^/]*$,,'`
+for c in $probe_ccs
+do if $executable $cc_dir/$c
+ then x=$cc_dir/$c
+ else x=$c
+ fi
+ eval $c='$x'
+done
+ld_dir=
+rm -f doti.$obj
+if $cc -c doti.$src
+then eval set x $probe_verbose
+ shift
+ for o
+ do $cc $o doti.$obj
+ $cc $o doti.$obj -lF0oB@r
+ done 2>&1 | sed -e 's/^[+ ]*//' -e 's/[ ].*//' -e '/^\//!d' -e 's/:$//' -e '/ld[a-zA-Z0-9.]*$/!d' -e 's,///*,/,g' > t
+ for i in `cat t`
+ do rm -f t.$obj
+ if test -x $i && $i -r -o t.$obj doti.$obj && test -f t.$obj
+ then case $ld in
+ ld) ld=$i ;;
+ esac
+ ld_dir=`echo $i | sed 's,/[^/]*$,,'`
+ break
+ fi
+ done
+fi
+IFS=:
+set x $PATH
+IFS=$ifs
+path=$*
+m=
+for c in $probe_ccs
+do eval o='$'$c
+ case $o in
+ $c) ;;
+ *) continue ;;
+ esac
+ C='${c}'
+ for x in $cc_dir $ld_dir
+ do cd $x
+ for p in "${C}" "${C}[!a-zA-Z]*" "*[!a-zA-Z]${C}" "*[!a-zA-Z]${C}[!a-zA-Z]*"
+ do eval set x $p
+ case $# in
+ 2) if $executable $2
+ then case $2 in
+ *$c*$c*);;
+ *) m=$p
+ break 3
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ done
+ done
+done
+cd $tmpdir
+for c in $probe_ccs
+do eval o='$'$c
+ case $o in
+ $c) ;;
+ *) continue ;;
+ esac
+ for x in $cc_dir $ld_dir
+ do if $executable $x/$c
+ then eval $c='$x/$c'
+ continue 2
+ fi
+ case $m in
+ ?*) eval set x $x/$m
+ case $# in
+ 2) if $executable $2
+ then eval $c='$2'
+ continue 2
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ done
+ for x in $path
+ do if $executable $x/$c
+ then eval $c='$x/$c'
+ break
+ fi
+ done
+done
+dld=$cc
+
+rm -f dynamic.$exe
+if $cc -o dynamic.$exe dynamic.$obj && $executable dynamic.$exe
+then mkdir mylib
+ echo > mylib/libc.$lib
+ eval set x $probe_ldlib
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f dynamic.$exe
+ if eval $1=./mylib '$'cc -o dynamic.$exe dynamic.$obj
+ then :
+ else libpath=$1
+ break
+ fi
+ done
+fi
+test `$cc -E libpp.$src | grep -c '^#pragma pp:version "libpp '` -eq 1 && libpp=1
+$cc -E doti.$src > doti.i && $cc -c doti.i && test -s doti.$obj && doti=1
+if $cc -c imusr.$src
+then eval set x $probe_include_local
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ if $cc -c $1 imusr.$src
+ then : "$1 should skip \"_i_.h\" in ."
+ elif $cc -c imstd.$src
+ then if $cc -c -Iim imstd.$src
+ then : '-Idir should find <stdio.h> in dir'
+ elif $cc -c $1 -Iim imstd.$src
+ then : "$1 -Idir should find <stdio.h> in dir"
+ elif $cc -c -Iim $1 imstd.$src
+ then include_local=$1
+ break
+ else : "-Idir $1 should skip <stdio.h> in dir"
+ fi
+ else : should find stdio.h
+ fi
+ done
+else : 'should find "_i_.h" in .'
+fi
+
+if $cc -c pic.$src 2>e
+then e=`wc -l e`
+ s=`$size pic.$obj; wc pic.$obj`
+ eval set x $probe_pic
+ shift
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ pic=$1
+ shift
+ PIC=$1
+ shift
+ rm -f pic.$obj
+ $cc $pic -c pic.$src 2>e && test -f pic.$obj || continue
+ $cc $pic -o pic.$exe pic.$obj && test -f pic.$exe || {
+ rm -f pic.$exe
+ $cc -o pic.$exe pic.$obj && test -f pic.$exe && continue
+ }
+ case `wc -l e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case $pic in
+ ???*) m=`echo " $pic" | sed -e 's/^ [-+]//g' -e 's/./-& /g' -e 's/[-+] //g'`
+ rm -f pic.$obj pic1.$exe
+ if $cc $m -c pic.$src 2>e && test -f pic.$obj &&
+ $cc -o pic1.$exe pic.$obj && test -f pic1.$exe
+ then case `wc -l e` in
+ $e) cc_pic=$m
+ break
+ ;;
+ esac
+ fi
+ cc_pic=$pic
+ break
+ ;;
+ *) case `$size pic.$obj; wc pic.$obj` in
+ $s) ;;
+ *) cc_pic=$pic
+ break
+ ;;
+ esac
+ ;;
+ esac
+ done
+ # this works around gcc 2.95 sun4 -fpic a.out core dump after exit
+ case $hosted:$cc_pic in
+ 1:?*) if ./pic.$exe
+ then # this catches lynxos.ppc gcc that dumps -fpic and not -mshared
+ echo 'static int* f() { static int v; return &v; }
+int main() { f(); return 0; }' > picok.$src
+ $cc $cc_pic -o picok.$exe picok.$src && ./picok.$exe || cc_pic=
+ else cc_pic=
+ fi
+ ;;
+ esac
+ case $cc_pic in
+ ?*) rm -f pic.$obj
+ if $cc $PIC -c pic.$src 2>e && test -f pic.$obj
+ then cc_PIC=$PIC
+ else cc_PIC=$cc_pic
+ fi
+ ;;
+ *) eval set x $probe_dll
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f pic.$obj pic.$exe
+ $cc $1 -c pic.$src 2>e && test -f pic.$obj || continue
+ $cc $1 -o pic.$exe pic.$obj && test -f pic.$exe || {
+ rm -f pic.$exe
+ $cc -o pic.$exe pic.$obj && test -f pic.$exe && continue
+ }
+ case $1 in
+ -Wc,*exportall*)
+ # get specific since sgi gets this far too
+ rm -f pic.$exe pic.x
+ $cc -Wl,dll -o pic.$exe pic.$obj || continue
+ test -f pic.$exe || continue
+ test -f pic.x || continue
+ cc_dll="-D_SHARE_EXT_VARS $1"
+ so=.x
+ sd=.dll
+ dld=$cc
+ shared=-Wl,dll
+ prefix_shared=
+ probe_sd=
+ probe_shared=
+ #unused# lddynamic=-Bdynamic
+ #unused# ldstatic=-Bstatic
+ lib_dll=SYMBOL
+ break
+ ;;
+ esac
+ case `wc -l e` in
+ $e) cc_dll=$1
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+fi
+
+$cc -c plusplus.$src && plusplus=1
+$cc -E -dD dDflag.$src > t
+case `grep '#define[ ][ ]*dDflag[ ][ ]*on' t` in
+?*) dDflag=1 ;;
+esac
+case `grep '#define.*_GNUC_' t` in
+?*) gnu=1 ;;
+esac
+case $plusplus in
+"") $cc -c stdc.$src && stdc=1 ;;
+*) mkdir ptr
+ cd ptr
+ $cc -c ../ptr.$src &
+ NFS_locks_are_botched=$!
+ cd ..
+ if $cc -c require.$src && $cc require.$obj
+ then set x `$cc require.$obj 2>&1`
+ d=
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -l*) d="$d $1" ;;
+ esac
+ done
+ for f in ++
+ do if $cc require.$obj -l$f
+ then set x `$cc require.$obj -l$f 2>&1`
+ r=
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -l*) case " $d $r " in
+ *" "$1" "*) ;;
+ *) r="$r $1" ;;
+ esac
+ esac
+ done
+ case $r in
+ ?*) require="$require $f"
+ echo '' $r > req.$f
+ ;;
+ esac
+ fi
+ done
+ fi
+ cd ptr
+ for i in *
+ do if test -d $i
+ then repository=$i
+ break
+ fi
+ done
+ cd ..
+ kill -9 $NFS_locks_are_botched
+ rm -rf ptr
+ case $repository in
+ *?) mkdir ptr
+ cd ptr
+ i=PTR
+ case $repository in
+ $i) i=$i$i ;;
+ esac
+ $cc -ptr$i -c ../ptr.$src &
+ NFS_locks_are_botched=$!
+ cd ..
+ sleep 5
+ if test -d ptr/$i/$repository
+ then ptrimplicit=1
+ fi
+ kill -9 $NFS_locks_are_botched
+ rm -rf ptr
+ ;;
+ esac
+ $cc -o implc implc.$src && $executable implc && implicitc=1
+ if $cc -c toucho.$src && test -f toucho.$obj
+ then o=`ls -l toucho.$obj`
+ if $cc -o toucho toucho.$obj && $executable toucho
+ then n=`ls -l touch.$obj`
+ case $n in
+ "$o") ;;
+ *) toucho=1 ;;
+ esac
+ fi
+ fi
+ ;;
+esac
+
+if $cc -c pic.$src
+then eval set x $probe_nmflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case `$nm $1 pic.$obj | grep -c '[0123456789][ ][ ]*T[ ][ ]*[_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'` in
+ 0) ;;
+ *) nmflags=$1
+ break
+ ;;
+ esac
+ done
+ case $# in
+ 0) case `$nm -gh pic.$obj | grep -c '|\.*[TtDdBbC][EeAaSsOo][XxTtSsMm]'` in
+ 0) ;;
+ *) nmflags=-gh
+ nmedit="-e '/\.*[TtDdBbC][EeAaSsOo][XxTtSsMm]/!d' -e 's/[| ].*//'"
+ ;;
+ esac
+ ;;
+ *) nmedit="-e '/[ ]T[ ][ ]*[_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]/!d' -e 's/.*[ ]T[ ][ ]*//'"
+ ;;
+ esac
+fi
+
+if $cc -c doti.$src
+then eval set x $probe_stripflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ if $strip $1 doti.$obj
+ then stripflags=$1
+ break
+ fi
+ done
+fi
+
+rm -f export.$obj export.exe
+if $cc -c export.$src
+then lm=
+ if $cc -o export.exe export.$obj -lm 2>e && lm=-lm ||
+ $cc -o export.exe export.$obj 2>e
+ then z=`wc -c < export.exe; $size export.exe 2>/dev/null`
+ eval set x $probe_export_dynamic
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f export.exe
+ if $cc -o export.exe $1 export.$obj $lm 2>f && $executable export.exe
+ then y=`wc -c < export.exe; $size export.exe 2>/dev/null`
+ case $y in
+ $z) ;;
+ *) if cmp -s e f
+ then export_dynamic=$1
+ break
+ fi
+ ;;
+ esac
+ fi
+ done
+ fi
+fi
+rm -f export.$obj export.exe
+
+rm -f strip.exe
+if $cc -o strip.exe strip.$src
+then z=`wc -c < strip.exe`
+ eval set x $probe_ldstrip
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f strip.exe
+ if $cc -o strip.exe $1 strip.$src
+ then case `wc -c < strip.exe` in
+ $z) ;;
+ *) ldstrip=$1
+ break
+ ;;
+ esac
+ fi
+ done
+fi
+
+rm -f strip.exe strip.$obj
+if $cc -c strip.$src && $cc -o strip.exe strip.$obj 2>e
+then eval set x x $probe_ldlazy
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f strip.$exe
+ $cc -o strip.$exe $1 strip.$obj $2 2>f && test -f strip.$exe || continue
+ cmp -s e f || continue
+ ldlazy=$1
+ ldnolazy=$2
+ break
+ done
+ eval set x x $probe_ldrecord
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f strip.$exe
+ $cc -o strip.$exe $1 strip.$obj $2 2>f && test -f strip.$exe || continue
+ cmp -s e f || continue
+ ldrecord=$1
+ ldnorecord=$2
+ break
+ done
+fi
+
+case $cc_dll:$cc_pic:$so:$dynamic:$static in
+::::|$cc_dll_def::::)
+ : last chance dynamic checks
+ while :
+ do
+ echo '__declspec(dllexport) int fun() { return 0; }' > exp.$src
+ if $cc -c $cc_dll_def exp.$src
+ then rm -f xxx.dll xxx.lib
+ if $cc -shared -Wl,--enable-auto-image-base -Wl,--out-implib=xxx.lib -o xxx.dll exp.$obj &&
+ test -f xxx.lib -a -f xxx.dll
+ then
+ : cygwin
+ cc_dll=$cc_dll_def
+ dll_dir='$(BINDIR)'
+ sd=.dll
+ so=.dll.a
+ ldscript=".def .exp .ign .res"
+ lib_dll=option
+ lib_all=-Wl,-whole-archive
+ lib_undef=-Wl,-no-whole-archive
+ dld=$cc
+ shared='-shared -Wl,--enable-auto-image-base -Wl,--out-implib=$(<:N=*'$so')'
+ prefix_dynamic=cyg
+ prefix_shared=lib
+ break
+ fi
+ fi
+ break
+ done
+ ;;
+*) if $cc -c $cc_dll $cc_pic shared.$src && $cc -c $cc_dll $cc_pic notall.$src
+ then for xx in "$cc" "$ld"
+ do eval set x $probe_shared
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ # UNDENT ...
+
+ if $xx $1 -o xxx$dll shared.$obj 2>e && test -r xxx$dll
+ then if test -s e && egrep -i 'unknown|invalid|option' e > /dev/null
+ then continue
+ fi
+ case `PATH=/bin:/usr/bin:$PATH file xxx$dll` in
+ *lib*|*obj*|*shared*)
+ ;;
+ "") $executable xxx$dll || continue
+ ;;
+ *ELF*|*elf*)
+ $executable xxx$dll || continue
+ case `strings xxx$dll | sed -e 's,.*[ |],,' | sort -u | egrep -i '^([._](dynamic|dynstr|dynsym))$'` in
+ [012]) continue ;;
+ esac
+ ;;
+ *archive*not*stripped*|*data*dynamic*not*stripped*)
+ $executable xxx$dll || continue
+ ;;
+ *) continue
+ ;;
+ esac
+ dld=$xx
+ shared=$1
+ # does -nostartfiles make sense for C?
+ case $plusplus in
+ '') z=`wc -c < xxx$dll`
+ eval set x $probe_shared_nostart
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared $1 -o xxx$dll shared.$obj 2>e && test -r xxx$dll
+ then case `wc -c < xxx$dll` in
+ $z) ;;
+ *) if test -s e
+ then case `cat e` in
+ *[Ee][Rr][Rr][Oo][Rr]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*)
+ continue
+ ;;
+ esac
+ fi
+ case $shared in
+ '') shared=$1 ;;
+ *) shared="$shared $1" ;;
+ esac
+ break
+ ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+ case $cc_dll in
+ "") cc_dll=$cc_dll_def ;;
+ esac
+ eval set x x $probe_sd
+ while :
+ do shift
+ shift
+ case $# in
+ [01]) break ;;
+ esac
+ rm -f xxx xxx$1 xxx$2
+ if $dld $shared -o xxx shared.$obj 2>e
+ then if test -f xxx$1 -a \( -f xxx$2 -o "$cc_dll" = "$cc_dll_def" \)
+ then sd=$1
+ so=$2
+ lddynamic=-Bdynamic
+ ldstatic=-Bstatic
+ break 2
+ elif test -f xxx -a -f xxx$2
+ then sd=$1
+ so=$2
+ break 2
+ else case $so in
+ '') so=$1 ;;
+ esac
+ break
+ fi
+ fi
+ done
+ rm -f libxxx.$lib
+ $ar cr libxxx.$lib shared.$obj
+ ranlib libxxx.$lib
+ eval set x x $probe_lib_all_undef
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll libxxx.$lib && test -r xxx$dll
+ then if $nm $nmflags xxx$dll | grep ShareD
+ then lib_dll=OPTION
+ set x x
+ fi
+ fi
+ while :
+ do shift
+ shift
+ case $# in
+ 0|1) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll $1 libxxx.$lib $2 && test -r xxx$dll
+ then if $nm $nmflags xxx$dll | grep ShareD
+ then lib_dll=option
+ lib_all=$1
+ lib_undef=$2
+ break
+ fi
+ fi
+ case $2 in
+ ?*) if $dld $shared -o xxx$dll $1 libxxx.$lib && test -r xxx$dll
+ then if $nm $nmflags xxx$dll | grep ShareD
+ then lib_dll=option
+ lib_all=$1
+ break
+ fi
+ fi
+ ;;
+ esac
+ done
+ case $lib_dll in
+ OPTION) lib_dll=option
+ ;;
+ option) case $lib_undef in
+ "") rm -f libyyy.$lib
+ $ar cr libyyy.$lib notall.$obj
+ ranlib libyyy.$lib
+ $cc -c prefix.$src
+ eval set x x $probe_lib_all_undef
+ while :
+ do shift
+ shift
+ case $# in
+ 0|1) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll prefix.$obj $lib_all libxxx.$lib $2 libyyy.$lib && test -r xxx$dll
+ then rm -f t
+ $nm $nmflags xxx$dll > t
+ case `grep -c ShareD t`:`grep -c NotalL t` in
+ 0:*) ;;
+ *:0) lib_undef=$2
+ break
+ ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+ case $lib_undef in
+ "") eval set x $probe_lib_multiple
+ rm -f libyyy.$lib
+ cp libxxx.$lib libyyy.$lib
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll prefix.$obj $lib_all libxxx.$lib libyyy.$lib && test -r xxx$dll
+ then :
+ else while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll prefix.$obj $lib_all $1 libxxx.$lib libyyy.$lib && test -r xxx$dll
+ then rm -f t
+ $nm $nmflags xxx$dll > t
+ case `grep -c ShareD t` in
+ 0) ;;
+ *) lib_all="$lib_all $1"
+ break
+ ;;
+ esac
+ fi
+ done
+ fi
+ lib_dll=symbol
+ ;;
+ esac
+ ;;
+ *) lib_dll=symbol
+ ;;
+ esac
+ case `cat e` in
+ ?*) eval set x $probe_unresolved
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if eval '$dld $shared' $1 '-o xxx$dll shared.$obj 2>e && test -r xxx$dll'
+ then case `cat e` in
+ "") shared="$shared $1"; break ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+ r=
+ eval set x $probe_shared_registry
+ while :
+ do shift
+ r=x$r
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if eval \$dld \$shared -o xxx\$dll $1 shared.\$obj &&
+ test -r xxx$dll -a -r $probe_shared_registry_file
+ then probe_shared_registry_file='$(CC.SHARED.REGISTRY.PATH)'
+ eval set x $probe_shared_registry
+ i=
+ while :
+ do shift
+ i=x$i
+ case $i in
+ $r) break ;;
+ esac
+ done
+ shared_registry=$1
+ fi
+ done
+ break 2
+ fi
+
+ # ... INDENT
+ done
+ done
+ fi
+ case $so in
+ ?*) rm -f xxx*
+ if $dld $shared -g -o xxx shared.$obj 2>e
+ then set x $probe_sdb
+ while :
+ do shift
+ case $1 in
+ 0) break ;;
+ esac
+ if test -f xxx$1
+ then sdb=$1
+ break
+ fi
+ done
+ fi
+ if $cc -c require.$src
+ then p='
+/usr/proberun/lib:/local/runprobe/lib
+'
+ eval set x $probe_ldrunpath
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f require.exe
+ if $cc -o require.exe $1"$p" require.$obj &&
+ grep -c /proberun/ require.exe >/dev/null &&
+ grep -c /runprobe/ require.exe > /dev/null
+ then ldrunpath=$1
+ eval set x $probe_ldorigin
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f origin.exe
+ if $cc -o origin.exe $1 $ldrunpath'$ORIGIN' require.$obj
+ then if ./origin.exe > /dev/null 2>&1
+ then ldorigin="$1 $ldrunpath"'\$ORIGIN/$(BINDIR:P=R=$(DLLDIR))'
+ fi
+ break
+ fi
+ done
+ break
+ fi
+ done
+ fi
+ rm -f libxxx$so
+ if $cc -c sovmain.$src &&
+ $cc -c $cc_dll $cc_pic sovlib.c &&
+ $dld $shared -o libxxx$so sovlib.$obj &&
+ $cc -o sovmain.$exe -L. sovmain.$obj -lxxx
+ then rm -f sovmain.$exe
+ mv libxxx$so libxxx$so.5.6
+ if $cc -o sovmain.$exe -L. sovmain.$obj -lxxx
+ then soversion=1
+ fi
+ fi
+ rm -f doti.$obj
+ std64=/lib64
+ lcl64=/usr/local/lib64
+ if test -d $std64 -a -d $lcl64 && $cc -c doti.$src
+ then for i in `cd $lcl64; ls *$so 2>/dev/null | sed 's/lib\([^.]*\).*/\1/'`
+ do if $cc -o runpath.$exe doti.$obj -l$i >/dev/null 2>&1
+ then LD_LIBRARY_PATH= ./runpath.$exe >/dev/null 2>&1 && continue
+ if LD_LIBRARY_PATH=$lcl64 ./runpath.$exe >/dev/null 2>&1
+ then runpath=$lcl64
+ break
+ elif LD_LIBRARY_PATH=$std64 ./runpath.$exe >/dev/null 2>&1
+ then runpath=$std64
+ break
+ elif LD_LIBRARY_PATH=$lcl64:$std64 ./runpath.$exe >/dev/null 2>&1
+ then runpath=$lcl64:$std64
+ break
+ fi
+ fi
+ done
+ fi
+ ;;
+ esac
+ ;;
+esac
+
+rm -f shared.$obj
+if $cc -c shared.$src
+then eval set x $probe_ar_arflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f libxxx.$lib
+ if $ar $1 r libxxx.$lib shared.$obj && $ar $1 t libxxx.$lib 2>&1 | grep shared.$obj >/dev/null
+ then ar_arflags=$1
+ break
+ fi
+ done
+ eval set x $probe_arflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f libxxx.$lib
+ if $cc $1 -o libxxx.$lib shared.$obj && $ar t libxxx.$lib 2>&1 | grep shared.$obj >/dev/null
+ then arflags=$1
+ break
+ fi
+ done
+fi
+
+case $shared in
+-G) case $cc_dll in
+ "") cc_dll=$cc_dll_def ;;
+ esac
+ ;;
+*) case $lib_dll in
+ symbol) echo 'extern int f();
+ int main() { f(); return 0; }' > main.$src
+ echo '#include <stdio.h>
+ int f() { printf("hello world"); return 0; }' > member.$src
+ if $cc -c main.$src && $cc -c member.$src
+ then echo f > lib.exp
+ rm -f lib.$obj main.exe
+ if $ld -o lib.$obj -L: -bexport:lib.exp -berok -bmodtype:SRE -T512 -H512 -lm -lc member.$obj && $cc -o main.exe main.$obj lib.$obj
+ then dld=$ld
+ shared='-T512 -H512 -L$(LIBDIR): -berok -bmodtype:SRE'
+ lib_dll=export
+ dll_libraries='-lm -lc'
+ ldscript=.exp
+ case $cc_dll in
+ "") cc_dll=$cc_dll_def ;;
+ esac
+ case $so in
+ "") so=.$obj ;;
+ esac
+ fi
+ fi
+ ;;
+ esac
+ ;;
+esac
+case $shared in
+?*) if $cc -c $cc_dll $cc_pic shared.$src
+ then eval set x $probe_shared_name
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared ${1}libfoo.1.2 -o xxx$dll shared.$obj 2>e && test -r xxx$dll
+ then shared_name=$1
+ break
+ fi
+ done
+ fi
+ ;;
+esac
+case " $cc_dll " in
+*" $cc_dll_def "*)
+ ;;
+" ") ;;
+*) cc_dll="$cc_dll_def $cc_dll"
+ ;;
+esac
+
+case $hosttype in
+win32.*|cygwin.*|os2.*)
+ Lflag=1
+ ;;
+*) if $cc -c doti.$src
+ then if $cc -L. doti.$obj -lc >/dev/null
+ then case $cc_dll in
+ '') ;;
+ *) Lflag=1 ;;
+ esac
+ fi
+ fi
+ ;;
+esac
+
+case $lib_dll in
+option) case $hosttype in
+ linux.*) dll_libraries=-lc ;;
+ esac
+ ;;
+SYMBOL) lib_dll=symbol
+ ;;
+symbol) echo "#include <stdio.h>
+extern int fun()
+{
+ puts(\"fun\");
+ return 0;
+}" > dllib.$src
+ echo "extern int fun();
+int
+main()
+{
+ return fun();
+}" > dlmain.$src
+ pwd=`pwd`
+ while :
+ do
+ if $cc -c $cc_dll $cc_pic dlmain.$src &&
+ $cc -c $cc_dll $cc_pic dllib.$src
+ then rm -f libxxx$so
+ if $dld $shared -o libxxx$so dllib.$obj &&
+ chmod 555 libxxx$so
+ then rm -f dlmain.$exe
+ if $cc -o dlmain.$exe dlmain.$obj $pwd/libxxx$so &&
+ (./dlmain.$exe) >/dev/null 2>&1
+ then break
+ fi
+ fi
+ rm -f libxxx$so dlmain.$exe
+ if $dld $shared -o libxxx$so dllib.$obj -lm -lc &&
+ chmod 555 libxxx$so &&
+ $cc -o dlmain.$exe dlmain.$obj $pwd/libxxx$so &&
+ (./dlmain.$exe) >/dev/null 2>&1
+ then dll_libraries='-lm -lc'
+ fi
+ fi
+ break
+ done
+ # the dll_libraries probe is still lame
+ case $dll_libraries in
+ '') case $hosttype in
+ sco.*|sol*.*|sun*) ;;
+ *) dll_libraries='-lm -lc' ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+
+stdlib=
+a=`$cc -print-multi-directory 2>/dev/null`
+case $a in
+.) ;;
+*) for d in `$cc -print-search-dirs 2>/dev/null | sed -e '/^libraries:/!d' -e 's/.*=//' | tr : '\n' | grep /lib/`
+ do if [ -d ${d}${a} ]
+ then stdlib="$stdlib ${d}${a}"
+ else case $d in
+ */lib/) d=`echo '' $d | sed -e 's,/$,,'`
+ if [ -d ${d}${a} ]
+ then stdlib="$stdlib ${d}${a}"
+ fi
+ ;;
+ esac
+ fi
+ done
+ ;;
+esac
+case $stdlib in
+'') stdlib=`$cc -v doti.$src 2>&1 |
+ sed 's/ */\n/g' |
+ sed -e '/^-L/!d' -e 's/^-L//' |
+ while read dir
+ do if test -d "$dir"
+ then (cd "$dir"; pwd)
+ fi
+ done`
+ ;;
+*) eval set x $probe_verbose
+ shift
+ for o in "$@"
+ do stdlib="$stdlib "`$cc $o doti.$src 2>&1 |
+ sed 's/ */\n/g' |
+ sed -e '/^-L/!d' -e '/\/lib64$/!d' -e 's/^-L//'`
+ done
+ ;;
+esac
+case $stdlib in
+?*) keepstdlib=1
+ o=$stdlib
+ stdlib=
+ for dir in $o
+ do case " $stdlib " in
+ *" $o "*) continue ;;
+ esac
+ case $dir in
+ /usr/lib64)
+ i=/usr/local/lib64
+ a=/lib64
+ ;;
+ /lib64) i=/usr/local/lib64
+ a=/usr/lib64
+ ;;
+ /usr/lib)
+ i=/usr/local/lib
+ a=/lib
+ ;;
+ lib) i=/usr/local/lib
+ a=/usr/lib
+ ;;
+ *) i=
+ a=
+ ;;
+ esac
+ if test "" != "$i" -a -d "$i"
+ then case " $o " in
+ *" $i "*)
+ ;;
+ *) stdlib="$stdlib $i"
+ ;;
+ esac
+ fi
+ stdlib="$stdlib $dir"
+ if test "" != "$a" -a -d "$a"
+ then case " $o " in
+ *" $a "*)
+ ;;
+ *) stdlib="$stdlib $a"
+ ;;
+ esac
+ fi
+ done
+ case $hosted in
+ 1) case " $stdlib " in
+ *" /usr/lib "*)
+ ;;
+ *) case " $stdlib " in
+ *" /usr/local/lib "*)
+ ;;
+ *) stdlib="$stdlib /usr/local/lib"
+ ;;
+ esac
+ stdlib="$stdlib /usr/lib"
+ ;;
+ esac
+ case " $stdlib " in
+ *" /lib "*)
+ ;;
+ *) stdlib="$stdlib /lib"
+ ;;
+ esac
+ esac
+ ;;
+*) keepstdlib=0
+ case $dir in
+ */arch/$hosttype/lib/*)
+ notlib=`echo $dir | sed "s,/arch/$hosttype/lib/.*,/arch/$hosttype/lib,"`
+ ;;
+ *) notlib=////
+ ;;
+ esac
+ tstlib=
+ implib=
+ if $cc -c hosted.$src
+ then for f in `(
+ eval set x $probe_verbose
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ $cc $1 hosted.$obj
+ done
+ ) 2>&1 | sed -e 's/[ :]/\\
+ /g' -e 's/-L//g' -e 's/^P,//' -e "s/[\"']//g" -e 's,^[\\\\/]*[\\\\/],/,' | sed -e '/^\$/d' -e '/^[-+]/d' -e '/^[^\\\\\\/]/d' -e '/[\\\\\\/]tmp[\\\\\\/]/d' -e 's/:\$//' -e 's,//*$,,'`
+ do case " $tstlib $implib " in
+ *" $f "*) continue ;;
+ esac
+ case $f in
+ $notlib) continue ;;
+ esac
+ if test -d $f
+ then tstlib="$tstlib $f"
+ elif test -f $f
+ then d=`echo $f | sed -e 's,[\\\\/]*[^\\\\/]*\$,,'`
+ case " $tstlib $implib " in
+ *" $d "*) continue ;;
+ esac
+ case $d in
+ *[\\/]usr[\\/]lib)
+ x=$d
+ d="`echo $d | sed -e 's,[\\\\/][\\\\/]*usr[\\\\/]lib\$,/lib,'`"
+ case " $tstlib $implib " in
+ *" $d "*) ;;
+ *) implib="$implib $d" ;;
+ esac
+ implib="$implib $x"
+ ;;
+ *[\\/]lib)
+ implib="$implib $d"
+ d="`echo $d | sed -e 's,[\\\\/][\\\\/]*lib\$,/usr/lib,'`"
+ case " $tstlib $implib " in
+ *" $d "*) ;;
+ *) implib="$implib $d" ;;
+ esac
+ ;;
+ *) implib="$implib $d"
+ ;;
+ esac
+ fi
+ done
+ fi
+ tstlib="$tstlib $implib"
+ if $cc -Dtype=void -Dcall=exit -c tstlib.$src && mv tstlib.$obj tst.$obj
+ then case $plusplus in
+ '') probe_lxx= ;;
+ esac
+ l=
+ for sym in $probe_l $probe_lxx
+ do case $l in
+ "") l=$sym; continue ;;
+ esac
+ rm -f tstlib.$exe
+ if $cc -o tstlib.$exe tst.$obj -l$l
+ then eval set x $probe_ldmap
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ d=`$cc -Dtype=int -Dcall=$sym $static $1 tstlib.$src -l$l 2>&1 | sed -e '/[\\\\\\/].*[\\\\\\/]lib[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+]*\.[^\\\\\\/]*\$/!d' -e 's,^[^\\\\\/]*,,' -e 's,[\\\\\\/]lib[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+]*\.[^\\\\\\/]*\$,,' -e '/^[\\\\\\/]/!d' | sort -u`
+ case $d in
+ ?*) tstlib="$tstlib $d" ;;
+ esac
+ done
+ fi
+ l=
+ done
+ fi
+ libstd=
+ libset=
+ stdlibroot="/ /usr/"
+ for d in $tstlib
+ do case $d in
+ [\\/]lib|[\\/]usr[\\/]lib)
+ ;;
+ *) case " $stdlib " in
+ *\ $d\ *)
+ ;;
+ *) if ls $d ${PREROOT+$PREROOT/../$d} > tmp.tmp && test -s tmp.tmp
+ then for i in $probe_lib $obj
+ do if grep -i "\\.$i\$" tmp.tmp >/dev/null
+ then case " $probe_lib_append " in
+ *\ $d\ *)
+ libstd="$libstd $d"
+ ;;
+ *) stdlib="$stdlib $d"
+ case $d in
+ /usr/lib|/usr/lib/*)
+ ;;
+ /usr/lib?*)
+ e=`echo $d | sed -e 's,/usr,,'`
+ g=`echo $d/libc.* $e/libc.*`
+ case "$e $g " in
+ *".* "*);;
+ *) stdlib="$stdlib $e"
+ stdlibroot=
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $libset in
+ "") case $i in
+ $obj) ;;
+ *) libset=1
+ lib=$i
+ ;;
+ esac
+ ;;
+ esac
+ break
+ fi
+ done
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ done
+ for d in `$ld --verbose 2>&1 | sed -e '/SEARCH_DIR/!d' -e 's/[ ][ ][ ]*/ /g' -e 's/SEARCH_DIR(\([^ ]*\));/\1/g' -e 's, //[^ ]*,,' -e 's,",,g'`
+ do if test -d $d
+ then case " $stdlib $libstd " in
+ *\ ${d}\ *)
+ ;;
+ *) libstd="$libstd $d"
+ ;;
+ esac
+ fi
+ done
+ case $hosted in
+ "") tstlib= ;;
+ *) tstlib="$stdlibroot /usr/ccs/ /usr/local/" ;;
+ esac
+ case $stdlibroot in
+ ?*) d=
+ for f in $stdinclude
+ do f=`echo $f | sed -e 's,[^\\\\/]*\$,,'`
+ d="$d $f"
+ done
+ tstlib="$d $tstlib"
+ ;;
+ esac
+ $cc -c doti.$src > all.tmp
+ for f in $probe_libdir
+ do for d in $stdlib $libstd $tstlib
+ do if test -d ${d}${f}
+ then ls ${d}${f} ${PREROOT:+$PREROOT/../${d}${f}} |
+ while read i
+ do for j in ${d}${f}/${i} ${PREROOT:+$PREROOT/../${d}${f}/${i}}
+ do if test -f $j -a -r $j -a -s $j
+ then echo $i
+ break
+ fi
+ done
+ done > tmp.tmp
+ if test -s tmp.tmp
+ then if egrep -i "^${prefix_archive}[abcdefghijklmnopqrstuvwxyz0123456789_][abcdefghijklmnopqrstuvwxyz0123456789_]*\\.$lib\$" tmp.tmp >lib.tmp ||
+ egrep -i "\\.$obj\$" tmp.tmp >/dev/null ||
+ egrep -i "^${prefix_shared}[abcdefghijklmnopqrstuvwxyz0123456789_][abcdefghijklmnopqrstuvwxyz0123456789_]*\\$so(.[0-9]+)*\$" tmp.tmp >>lib.tmp
+ then if test -s lib.tmp
+ then sed -e "s,.*/,," -e 's,^'${prefix_archive}'\(.*\)\.'$lib'$,\1,g' -e 's,^'${prefix_shared}'\(.*\)\'$so'[.0-9]*,\1,g' lib.tmp | sort -u > tmp.tmp
+ xs=`sort all.tmp all.tmp tmp.tmp | uniq -u`
+ case $xs in
+ '') continue ;;
+ esac
+ ok=0
+ for x in $xs
+ do case $x in
+ *_p) continue ;; # linux gcc known to hang for -lc_p
+ esac
+ if $cc -o doti.$exe doti.$obj -l$x 2>e
+ then ok=1
+ else if test -s e && egrep -i ":.*[ ](find|found|locate|search|-l$x)[ ]" e > /dev/null
+ then if egrep -i ":.*[ ](access|permission)[ ]" e
+ then : maybe
+ else ok=0
+ break
+ fi
+ fi
+ case $Lflag in
+ 1) if $cc -L${d}${f} -o doti.$exe doti.$obj -l$x
+ then ok=0
+ break
+ fi
+ ;;
+ esac
+ fi
+ done
+ case $ok in
+ 0) continue ;;
+ esac
+ sort -u all.tmp tmp.tmp > lib.tmp
+ mv lib.tmp all.tmp
+ fi
+ case " $stdlib $libstd " in
+ *" ${d}${f} "*)
+ ;;
+ *) if test -d ${d}${f}/fsoft
+ then stdlib="$stdlib ${d}${f}/"'$(FLOAT_OPTION)'
+ fi
+ stdlib="$stdlib ${d}${f}"
+ ;;
+ esac
+ fi
+ fi
+ fi
+ done
+ done
+ stdlib="$stdlib $libstd"
+ case $stdlib in
+ */shlib*)
+ dy=
+ st=
+ for i in $stdlib $libstd
+ do case $i in
+ */shlib) dy="$dy $i" ;;
+ *) st="$st $i" ;;
+ esac
+ done
+ for i in /var
+ do if test -d $i/shlib
+ then dy="$dy $i/shlib"
+ fi
+ done
+ stdlib="$dy $st"
+ ;;
+ esac
+ ;;
+esac
+
+if $cc -c prefix.$src
+then eval set x $probe_symprefix
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ if $nm $nmflags prefix.$obj | grep -c ${1}prefix >/dev/null
+ then symprefix=$1
+ break
+ fi
+ done
+fi
+
+if $cc -c warn.$src 2>e && test -f warn.$obj
+then e=`wc -c < e`
+
+ eval set x $probe_debug
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ case `wc -c < e` in
+ $e) debug=$1; break ;;
+ esac
+ done
+
+ eval set x $probe_no_protect
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ case `wc -c < e` in
+ $e) no_protect=$1; break ;;
+ esac
+ done
+
+ case $version_string in
+ $probe_gcc_version) probe_optimize="$probe_gcc_optimize $probe_optimize" ;;
+ esac
+ eval set x $probe_optimize
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ case `wc -c < e` in
+ $e) optimize=$1; break ;;
+ esac
+ done
+
+ eval set x $probe_strict
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ n=`wc -c < e`
+ if test $n -ge $e
+ then strict=$1
+ break
+ fi
+ done
+
+ $cc -c warn1.$src 2>e
+ o=`wc -c < e`
+ eval set x $probe_warn
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj warn.$exe
+ $cc -o warn.$exe $1 warn.$src 2>e && test -f warn.$exe || continue
+ n=`wc -c < e`
+ for i in $warn_enum
+ do rm -f warn$i.$obj
+ $cc -c $1 warn$i.$src 2>e && test -f warn$i.$obj || continue
+ n=`wc -c < e`
+ if test $n -gt $o
+ then warn=$1
+ break 2
+ fi
+ done
+ done
+
+fi
+
+while :
+do case $hosted in
+ 1) rm -f readonly.$exe
+ eval set x '""' $probe_readonly
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ for co in '' -Dtest_const
+ do rm -f readonly.$exe
+ if $cc -o readonly.$exe $co $1 readonly.$src && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly=$1
+ break 3
+ fi
+ fi
+ done
+ done
+ rm -f readonly.$exe readonly.s
+ if $cc -S readonly.$src && test -f readonly.s
+ then if sed -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)data/\1text/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)zero[ ][ ]*/\1set .,.+/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*1/\1byte 0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*2/\1byte 0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*3/\1byte 0,0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*4/\1byte 0,0,0,0/' \
+ readonly.s > ro.s && $cc -o readonly.$exe ro.s && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly='-S.data'
+ break
+ fi
+ fi
+ rm -f readonly.$exe
+ if sed -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)idat/\1code/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)zero[ ][ ]*/\1set .,.+/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*1/\1byte 0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*2/\1byte 0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*3/\1byte 0,0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*4/\1byte 0,0,0,0/' \
+ readonly.s > ro.s && $cc -o readonly.$exe ro.s && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly='-S.idat'
+ break
+ fi
+ fi
+ if sed -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)data/\1rdata/' \
+ readonly.s > ro.s && $cc -o readonly.$exe ro.s && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly='-S.rdata'
+ break
+ fi
+ fi
+ fi
+ ;;
+ esac
+ break
+done
+
+case $stdc in
+?*) dialect="$dialect ANSI" ;;
+esac
+case $plusplus in
+?*) dialect="$dialect C++" ;;
+esac
+case $hosted in
+"") dialect="$dialect CROSS" ;;
+esac
+case $doti in
+?*) dialect="$dialect DOTI" ;;
+esac
+case $gnu in
+?*) dialect="$dialect GNU" ;;
+esac
+case $so:$dynamic:$static in
+::) ;;
+*) dialect="$dialect DYNAMIC"
+ case $soversion in
+ ?*) dialect="$dialect VERSION" ;;
+ esac
+ ;;
+esac
+case $implicitc in
+?*) dialect="$dialect IMPLICITC" ;;
+esac
+case $ptrcopy in
+?*) dialect="$dialect PTRCOPY" ;;
+esac
+case $ptrimplicit in
+?*) dialect="$dialect PTRIMPLICIT" ;;
+esac
+case $ptrmkdir in
+?*) dialect="$dialect PTRMKDIR" ;;
+esac
+case $libpp in
+?*) dialect="$dialect LIBPP" ;;
+esac
+case $toucho in
+?*) dialect="$dialect TOUCHO" ;;
+esac
+case $dDflag in
+?*) dialect="$dialect -dD" ;;
+esac
+# 2005-05-25 use $(CC.INCLUDE.LOCAL) instead
+case $include_local in
+?*) dialect="$dialect -I-" ;;
+esac
+case $Lflag in
+?*) dialect="$dialect -L" ;;
+esac
+
+ppcmd='$(CPP)'
+ppdir='$(CPP:D)'
+eval ppopt='"'$ppopt'"'
+eval ppenv='"'$ppenv'"'
+
+set x "" .$exe
+shift
+exe=
+for i
+do rm -f require$i
+done
+if $cc -o require require.$src
+then for i
+ do if $executable require$i
+ then exe=$i
+ break
+ fi
+ done
+fi
+case $sa:$sd:$so in
+::?*) eval set x $probe_sa
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ for i in $stdlib
+ do eval j="'" $i/lib*$1 "'"
+ case $j in
+ " $i/lib*$1 ")
+ eval j="'" $i/lib*$1.[0123456789]* "'"
+ case $j in
+ " $i/lib*$1.[0123456789]* ")
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ sa=$1
+ lddynamic=-Bdynamic
+ ldstatic=-Bstatic
+ break 2
+ done
+ done
+ ;;
+esac
+case $ldscript in
+"") case $so in
+ .lib) ldscript=".def .exp" ;;
+ *) ldscript=".ld" ;;
+ esac
+ ;;
+esac
+case $hosttype in
+'') hosttype=unknown ;;
+sgi.mips3) dll_variants='sgi.mips2:o32:-mips2 sgi.mips4:64:-mips4' ;;
+sgi.mips4) dll_variants='sgi.mips2:o32:-mips2 sgi.mips3:n32:-mips3' ;;
+esac
+
+case $hosted in
+"") ccnative=`echo $cc | sed -e 's,.*/,,'`
+ ccs=$ccnative
+ for c in cc gcc
+ do case " $ccs " in
+ *" $c "*) ;;
+ *) ccs="$ccs $c" ;;
+ esac
+ done
+ for p in $path
+ do for c in $ccs
+ do if $executable $p/$c
+ then rm -f native.$exe
+ if $p/$c -o native.$exe doti.$src && ./native.$exe
+ then ccnative=$p/$c
+ exectype=`package CC="$ccnative" || $SHELL -c "package CC='$ccnative'"`
+ case $exectype in
+ *[Uu][Ss][Aa][Gg][Ee]:*)
+ exectype=`PATH=$_probe_PATH; export PATH; package CC="$ccnative" || $SHELL -c "package CC='$ccnative'"`
+ ;;
+ esac
+ break 2
+ fi
+ fi
+ done
+ done
+ ;;
+*) ccnative=$cc
+ exectype=$hosttype
+ ;;
+esac
+
+# runtime shared lib exported symbol resolution
+
+case $cc_dll:$shared in
+:|:*|*:);;
+*) cat > cmd.c <<'!'
+#include <stdio.h>
+#include <dlfcn.h>
+typedef int (*Lib_f)(int**, int**, int**);
+int gbl_def = 1;
+int gbl_ref = 1;
+int gbl_ext;
+int main(int argc, char** argv)
+{
+ void* dll;
+ Lib_f lib;
+ int* def;
+ int* ref;
+ int* ext;
+
+ if (!(dll = dlopen(*++argv, RTLD_LAZY)))
+ fprintf(stderr, "library not found\n");
+ else if (!((lib = (Lib_f)dlsym(dll, "lib"))) && !(lib = (Lib_f)dlsym(dll, "_lib")))
+ fprintf(stderr, "symbol not found\n");
+ else if ((*lib)(&def, &ref, &ext))
+ fprintf(stderr, "function failed\n");
+ else if (def == &gbl_def && ref == &gbl_ref && ext == &gbl_ext)
+ printf("ALL\n");
+ else if (ref == &gbl_ref && ext == &gbl_ext)
+ printf("REF\n");
+ else if (ext == &gbl_ext)
+ printf("EXT\n");
+ return 0;
+}
+!
+ cat > lib.c <<'!'
+int gbl_def = 1;
+int gbl_ref;
+int gbl_ext;
+int lib(int** def, int** ref, int** ext)
+{
+ *def = &gbl_def;
+ *ref = &gbl_ref;
+ *ext = &gbl_ext;
+ return 0;
+}
+!
+ if $cc -c $cc_dll $cc_pic cmd.c &&
+ $cc -c $cc_dll $cc_pic lib.c && {
+ $cc $cc_dll $export_dynamic -o cmd.exe cmd.o ||
+ $cc $cc_dll $export_dynamic -o cmd.exe cmd.o -ldl
+ } &&
+ $dld $shared -o libgbl.dll lib.o
+ then x=`./cmd.exe ./libgbl.dll`
+ case $x in
+ ?*) dialect="$dialect EXPORT=$x" ;;
+ esac
+ else case $sd:$hosttype in
+ .dll:*win*) dialect="$dialect EXPORT=DLL" ;;
+ esac
+ fi
+ ;;
+esac
+
+# shellmagic defined if installed shell scripts need magic
+
+echo ': got magic :
+echo ok' > ok
+chmod +x ok
+case `(eval ./ok | /bin/sh) 2>/dev/null` in
+ok) ;;
+*) echo '#!/bin/env sh
+: got magic :
+echo ok' > ok
+ chmod +x ok
+ case `(eval ./ok | /bin/sh) 2>/dev/null` in
+ ok) shellmagic='$("#")!/bin/env sh'
+ ;;
+ *) for i in /emx/bin/bash.exe /emx/bin/sh.exe
+ do if test -x $i
+ then shellmagic='$("#")!'$i
+ break
+ fi
+ done
+ ;;
+ esac
+ ;;
+esac
+
+#
+# path cleanup
+#
+
+for i in ar ccnative dld ld nm size stdinclude stdlib strip
+do eval o='$'$i
+ v=$o
+ case $v in
+ *//*) v=`echo $v | sed 's,///*,/,g'` ;;
+ esac
+ if (test . -ef "`pwd`")
+ then k=
+ for x in $v
+ do case $x in
+ */../*|*/..)
+ case $x in
+ /*) a=/ ;;
+ *) a= ;;
+ esac
+ IFS=/
+ set '' $x
+ IFS=$ifs
+ r=
+ for d
+ do r="$d $r"
+ done
+ p=
+ g=
+ for d in $r
+ do case $d in
+ ..) g="$g $d" ;;
+ *) case $g in
+ '') case $p in
+ '') p=$d ;;
+ *) p=$d/$p ;;
+ esac
+ ;;
+ *) set $g
+ shift
+ g=$*
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $a in
+ '') for d in $g
+ do p=$d/$p
+ done
+ ;;
+ *) p=$a$p
+ ;;
+ esac
+ case $p in
+ /) continue ;;
+ esac
+ test $x -ef $p && x=$p
+ ;;
+ esac
+ k="$k $x"
+ done
+ set '' $k
+ shift
+ v=$1
+ case $# in
+ 0) ;;
+ *) shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ k=
+ for d
+ do for j in $v
+ do test $d -ef $j && continue 2
+ done
+ k="$k $d"
+ done
+ set '' $k
+ case $# in
+ 1) break ;;
+ esac
+ shift
+ v="$v $1"
+ shift
+ done
+ ;;
+ esac
+ fi
+ case $v in
+ $o) ;;
+ *) eval $i='$'v ;;
+ esac
+done
+
+case $keepstdlib in
+1) ;;
+*) #
+ # favor lib64 over lib
+ #
+ case $hosttype in
+ *64|*[!0-9]64[!a-zA-Z0-9]*)
+ o=$stdlib
+ stdlib=
+ for i in $o
+ do case " $stdlib " in
+ *" $i "*)
+ continue
+ ;;
+ esac
+ case $i in
+ *64) stdlib="$stdlib $i"
+ continue
+ ;;
+ esac
+ case " $o " in
+ *" ${i}64 "*)
+ case " $stdlib " in
+ *" ${i}64 "*)
+ ;;
+ *) stdlib="$stdlib ${i}64"
+ ;;
+ esac
+ ;;
+ esac
+ stdlib="$stdlib $i"
+ done
+ ;;
+ esac
+ ;;
+esac
+
+#
+# set up for local override
+#
+
+CC_VERSION_STAMP=$version_stamp
+CC_VERSION_STRING=$version_string
+CC_CC=$cc
+CC_NATIVE=$ccnative
+CC_EXECTYPE=$exectype
+CC_HOSTTYPE=$hosttype
+CC_ALTPP_FLAGS=$ppopt
+CC_ALTPP_ENV=$ppenv
+CC_AR=$ar
+CC_AR_ARFLAGS=$ar_arflags
+CC_ARFLAGS=$arflags
+CC_DEBUG=$debug
+CC_DIALECT=$dialect
+CC_PICBIG=$cc_PIC
+CC_PICSMALL=$cc_pic
+CC_PIC=$CC_PICBIG
+CC_DLL_ONLY=$cc_dll
+case $CC_DLL_ONLY in
+'') CC_DLLBIG=
+ CC_DLLSMALL=
+ CC_DLL=
+ ;;
+*) CC_DLLBIG="$CC_DLL_ONLY $CC_PICBIG"
+ CC_DLLSMALL="$CC_DLL_ONLY $CC_PICSMALL"
+ CC_DLL="$CC_DLL_ONLY $CC_PICBIG"
+ ;;
+esac
+CC_DLL_DIR=$dll_dir
+CC_DLL_LIBRARIES=$dll_libraries
+CC_DLL_VARIANTS=$dll_variants
+CC_DYNAMIC=$dynamic
+CC_EXPORT_DYNAMIC=$export_dynamic
+CC_INCLUDE_LOCAL=$include_local
+CC_LD=$ld
+CC_LD_DYNAMIC=$lddynamic
+CC_LD_LAZY=$ldlazy
+CC_LD_NOLAZY=$ldnolazy
+CC_LD_ORIGIN=$ldorigin
+CC_LD_RECORD=$ldrecord
+CC_LD_NORECORD=$ldnorecord
+CC_LD_RUNPATH=$ldrunpath
+CC_LD_STATIC=$ldstatic
+CC_LD_STRIP=$ldstrip
+CC_LIB_DLL=$lib_dll
+CC_LIB_ALL=$lib_all
+CC_LIB_UNDEF=$lib_undef
+CC_MAKE_OPTIONS=$makeoptions
+CC_NM=$nm
+CC_NMEDIT=$nmedit
+CC_NMFLAGS=$nmflags
+CC_NOPROTECT=$no_protect
+CC_OPTIMIZE=$optimize
+CC_READONLY=$readonly
+CC_REPOSITORY=$repository
+CC_REQUIRE=$require
+CC_RUNPATH=$runpath
+CC_SHARED=$shared
+CC_SHARED_LD=$dld
+CC_SHARED_NAME=$shared_name
+CC_SHARED_REGISTRY=$shared_registry
+CC_SHARED_REGISTRY_PATH=$probe_shared_registry_path
+CC_SHELLMAGIC=$shellmagic
+CC_SIZE=$size
+CC_STATIC=$static
+CC_STDINCLUDE=$stdinclude
+CC_STDLIB=$stdlib
+CC_STRICT=$strict
+CC_STRIP=$strip
+CC_STRIP_FLAGS=$stripflags
+CC_PREFIX_ARCHIVE=$prefix_archive
+CC_PREFIX_DYNAMIC=$prefix_dynamic
+CC_PREFIX_SHARED=$prefix_shared
+CC_PREFIX_SYMBOL=$symprefix
+CC_SUFFIX_ARCHIVE=.$lib
+CC_SUFFIX_COMMAND=$suffix_command
+CC_SUFFIX_DEBUG=$sdb
+CC_SUFFIX_DYNAMIC=$sd
+CC_SUFFIX_LD=$ldscript
+CC_SUFFIX_OBJECT=.$obj
+CC_SUFFIX_SHARED=$so
+CC_SUFFIX_SOURCE=.$src
+CC_SUFFIX_STATIC=$sa
+CC_VERSION=$version_flags
+CC_WARN=$warn
+CC_ATTRIBUTES=$ATTRIBUTES
+
+exec >&3
+
+#
+# check for local override
+# all CC_* but { CC_CC CC_VERSION_STAMP CC_VERSION_STRING } may be modified
+# additional CC.* may be printed on stdout
+#
+
+if test -f "$dir/probe.lcl"
+then . "$dir/probe.lcl"
+fi
+
+#
+# the payoff
+#
+
+case $version_stamp in
+?*) echo "# $version_stamp" ;;
+esac
+echo CC.CC = $cc
+echo CC.NATIVE = $CC_NATIVE
+echo CC.EXECTYPE = $CC_EXECTYPE
+echo CC.HOSTTYPE = $CC_HOSTTYPE
+echo CC.ALTPP.FLAGS = $CC_ALTPP_FLAGS
+echo CC.ALTPP.ENV = $CC_ALTPP_ENV
+echo CC.AR = $CC_AR
+echo CC.AR.ARFLAGS = $CC_AR_ARFLAGS
+echo CC.ARFLAGS = $CC_ARFLAGS
+echo CC.DEBUG = $CC_DEBUG
+echo CC.DIALECT = $CC_DIALECT
+echo CC.DLLBIG = $CC_DLLBIG
+echo CC.DLLSMALL = $CC_DLLSMALL
+echo CC.DLL = $CC_DLL
+echo CC.DLL.DEF = $cc_dll_def
+echo CC.DLL.DIR = $CC_DLL_DIR
+echo CC.DLL.LIBRARIES = $CC_DLL_LIBRARIES
+echo CC.DLL.VARIANTS = $CC_DLL_VARIANTS
+echo CC.DYNAMIC = $CC_DYNAMIC
+echo CC.EXPORT.DYNAMIC = $CC_EXPORT_DYNAMIC
+echo CC.INCLUDE.LOCAL = $CC_INCLUDE_LOCAL
+#
+# 2004-02-14 release workaround
+#
+case $CC_SHARED_LD in
+$CC_CC) echo if LDSHARED
+ echo CC.LD = $CC_LD
+ echo else
+ echo CC.LD = $CC_CC
+ echo end
+ ;;
+*) echo CC.LD = $CC_LD
+ ;;
+esac
+echo CC.LD.DYNAMIC = $CC_LD_DYNAMIC
+echo CC.LD.LAZY = $CC_LD_LAZY
+echo CC.LD.NOLAZY = $CC_LD_NOLAZY
+echo CC.LD.ORIGIN = $CC_LD_ORIGIN
+echo CC.LD.RECORD = $CC_LD_RECORD
+echo CC.LD.NORECORD = $CC_LD_NORECORD
+echo CC.LD.RUNPATH = $CC_LD_RUNPATH
+echo CC.LD.STATIC = $CC_LD_STATIC
+echo CC.LD.STRIP = $CC_LD_STRIP
+echo CC.LIB.DLL = $CC_LIB_DLL
+echo CC.LIB.ALL = $CC_LIB_ALL
+echo CC.LIB.UNDEF = $CC_LIB_UNDEF
+echo CC.MAKE.OPTIONS = $CC_MAKE_OPTIONS
+echo CC.NM = $CC_NM
+case $CC_NMEDIT in
+?*) CC_NMEDIT=" $CC_NMEDIT" ;;
+esac
+echo CC.NMEDIT ="$CC_NMEDIT"
+echo CC.NMFLAGS = $CC_NMFLAGS
+echo CC.NOPROTECT = $CC_NOPROTECT
+echo CC.OPTIMIZE = $CC_OPTIMIZE
+echo CC.PICBIG = $CC_PICBIG
+echo CC.PICSMALL = $CC_PICSMALL
+echo CC.PIC = $CC_PIC
+echo CC.READONLY = $CC_READONLY
+echo CC.REPOSITORY = $CC_REPOSITORY
+for f in $CC_REQUIRE
+do echo CC.REQUIRE.$f =`cat req.$f`
+done
+echo CC.RUNPATH = $CC_RUNPATH
+echo CC.SHARED = $CC_SHARED
+echo CC.SHARED.LD = $CC_SHARED_LD
+echo CC.SHARED.NAME = $CC_SHARED_NAME
+echo CC.SHARED.REGISTRY = $CC_SHARED_REGISTRY
+echo CC.SHARED.REGISTRY.PATH = $CC_SHARED_REGISTRY_PATH
+echo CC.SHELLMAGIC = $CC_SHELLMAGIC
+echo CC.SIZE = $CC_SIZE
+echo CC.STATIC = $CC_STATIC
+echo CC.STDINCLUDE = $CC_STDINCLUDE
+echo CC.STDLIB = $CC_STDLIB
+echo CC.STRICT = $CC_STRICT
+echo CC.STRIP = $CC_STRIP
+echo CC.STRIP.FLAGS = $CC_STRIP_FLAGS
+echo CC.PREFIX.ARCHIVE = $CC_PREFIX_ARCHIVE
+echo CC.PREFIX.DYNAMIC = $CC_PREFIX_DYNAMIC
+echo CC.PREFIX.SHARED = $CC_PREFIX_SHARED
+echo CC.PREFIX.SYMBOL = $CC_PREFIX_SYMBOL
+echo CC.SUFFIX.ARCHIVE = $CC_SUFFIX_ARCHIVE
+echo CC.SUFFIX.COMMAND = $CC_SUFFIX_COMMAND
+echo CC.SUFFIX.DEBUG = $CC_SUFFIX_DEBUG
+echo CC.SUFFIX.DYNAMIC = $CC_SUFFIX_DYNAMIC
+echo CC.SUFFIX.LD = $CC_SUFFIX_LD
+echo CC.SUFFIX.OBJECT = $CC_SUFFIX_OBJECT
+echo CC.SUFFIX.SHARED = $CC_SUFFIX_SHARED
+echo CC.SUFFIX.SOURCE = $CC_SUFFIX_SOURCE
+echo CC.SUFFIX.STATIC = $CC_SUFFIX_STATIC
+echo CC.VERSION = $CC_VERSION
+case $CC_VERSION_STRING in
+*\"*) i=`echo " $CC_VERSION_STRING" | sed -e 's,",\\\\",g' -e 's,^ ,,' -e 's,.*,"&",'` ;;
+*\'*) i=\"$CC_VERSION_STRING\" ;;
+*) i=$CC_VERSION_STRING ;;
+esac
+cat <<!
+CC.VERSION.STRING = $i
+!
+echo CC.WARN = $CC_WARN
+
+for i in $CC_ATTRIBUTES
+do eval echo CC.$i = \$$i
+done
diff --git a/src/cmd/INIT/mamake.c b/src/cmd/INIT/mamake.c
new file mode 100644
index 0000000..1f85240
--- /dev/null
+++ b/src/cmd/INIT/mamake.c
@@ -0,0 +1,2375 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * mamake -- MAM make
+ *
+ * coded for portability
+ */
+
+static char id[] = "\n@(#)$Id: mamake (AT&T Research) 2011-08-31 $\0\n";
+
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <error.h>
+
+static const char usage[] =
+"[-?\n@(#)$Id: mamake (AT&T Research) 2011-08-31 $\n]"
+USAGE_LICENSE
+"[+NAME?mamake - make abstract machine make]"
+"[+DESCRIPTION?\bmamake\b reads \amake abstract machine\a target and"
+" prerequisite file descriptions from a mamfile (see \b-f\b) and executes"
+" actions to update targets that are older than their prerequisites."
+" Mamfiles are generated by the \b--mam\b option of \bnmake\b(1) and"
+" \bgmake\b(1) and are portable to environments that only have"
+" \bsh\b(1) and \bcc\b(1).]"
+"[+?In practice \bmamake\b is used to bootstrap build \bnmake\b(1) and"
+" \bksh\b(1) in new environments. Mamfiles are used rather than"
+" old-\bmake\b makefiles because some features are not reliably supported"
+" across all \bmake\b variants:]{"
+" [+action execution?Multi-line actions are executed as a"
+" unit by \b$SHELL\b. There are some shell constructs"
+" that cannot be expressed in an old-\bmake\b makefile.]"
+" [+viewpathing?\bVPATH\b is properly interpreted. This allows"
+" source to be separate from generated files.]"
+" [+recursion?Ordered subdirectory recursion over unrelated"
+" makefiles.]"
+" }"
+"[+?\bmamprobe\b(1) is called to probe and generate system specific variable"
+" definitions. The probe information is regenerated when it is older"
+" than the \bmamprobe\b command.]"
+"[+?For compatibility with \bnmake\b(1) the \b-K\b option and the"
+" \brecurse\b and \bcc-*\b command line targets are ignored.]"
+"[e:?Explain reason for triggering action. Ignored if -F is on.]"
+"[f:?Read \afile\a instead of the default.]:[file:=Mamfile]"
+"[i:?Ignore action errors.]"
+"[k:?Continue after error with sibling prerequisites.]"
+"[n:?Print actions but do not execute. Recursion actions (see \b-r\b) are still"
+" executed. Use \b-N\b to disable recursion actions too.]"
+"[r:?Recursively make leaf directories matching \apattern\a. Only leaf"
+" directories containing a makefile named \bNmakefile\b, \bnmakefile\b,"
+" \bMakefile\b or \bmakefile\b are considered. The first makefile"
+" found in each leaf directory is scanned for leaf directory"
+" prerequisites; the recusion order is determined by a topological sort"
+" of these prerequisites.]:[pattern]"
+"[C:?Do all work in \adirectory\a. All messages will mention"
+" \adirectory\a.]:[directory]"
+"[D:?Set the debug trace level to \alevel\a. Higher levels produce more"
+" output.]#[level]"
+"[F:?Force all targets to be out of date.]"
+"[K:?Ignored.]"
+"[N:?Like \b-n\b but recursion actions (see \b-r\b) are also disabled.]"
+"[V:?Print the program version and exit.]"
+"[G:debug-symbols?Compile and link with debugging symbol options enabled.]"
+"[S:strip-symbols?Strip link-time static symbols from executables.]"
+
+"\n"
+"\n[ target ... ] [ name=value ... ]\n"
+"\n"
+
+"[+SEE ALSO?\bgmake\b(1), \bmake\b(1), \bmamprobe\b(1),"
+" \bnmake\b(1), \bsh\b(1)]"
+;
+
+#else
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
+
+#define NiL ((char*)0)
+
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#if !_PACKAGE_ast && defined(__STDC__)
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define delimiter(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)==';'||(c)=='('||(c)==')'||(c)=='`'||(c)=='|'||(c)=='&'||(c)=='=')
+
+#define add(b,c) (((b)->nxt >= (b)->end) ? append(b, "") : NiL, *(b)->nxt++ = (c))
+#define get(b) ((b)->nxt-(b)->buf)
+#define set(b,o) ((b)->nxt=(b)->buf+(o))
+#define use(b) (*(b)->nxt=0,(b)->nxt=(b)->buf)
+
+#define CHUNK 1024
+#define KEY(a,b,c,d) ((((unsigned long)(a))<<15)|(((unsigned long)(b))<<10)|(((unsigned long)(c))<<5)|(((unsigned long)(d))))
+#define NOW ((unsigned long)time((time_t*)0))
+#define ROTATE(p,l,r,t) ((t)=(p)->l,(p)->l=(t)->r,(t)->r=(p),(p)=(t))
+
+#define RULE_active 0x0001 /* active target */
+#define RULE_dontcare 0x0002 /* ok if not found */
+#define RULE_error 0x0004 /* not found or not generated */
+#define RULE_exists 0x0008 /* target file exists */
+#define RULE_generated 0x0010 /* generated target */
+#define RULE_ignore 0x0020 /* ignore time */
+#define RULE_implicit 0x0040 /* implicit prerequisite */
+#define RULE_made 0x0080 /* already made */
+#define RULE_virtual 0x0100 /* not a file */
+
+#define STREAM_KEEP 0x0001 /* don't fclose() on pop() */
+#define STREAM_MUST 0x0002 /* push() file must exist */
+#define STREAM_PIPE 0x0004 /* pclose() on pop() */
+
+#ifndef S_IXUSR
+#define S_IXUSR 0100 /* owner execute permission */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010 /* group execute permission */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001 /* other execute permission */
+#endif
+
+struct Rule_s;
+
+typedef struct stat Stat_t;
+typedef FILE Stdio_t;
+
+typedef struct Buf_s /* buffer stream */
+{
+ struct Buf_s* old; /* next dropped buffer */
+ char* end; /* 1 past end of buffer */
+ char* nxt; /* next char to add */
+ char* buf; /* buffer space */
+} Buf_t;
+
+typedef struct Dict_item_s /* dictionary item */
+{
+ struct Dict_item_s* left; /* left child */
+ struct Dict_item_s* right; /* right child */
+ void* value; /* user defined value */
+ char name[1];/* 0 terminated name */
+} Dict_item_t;
+
+typedef struct Dict_s /* dictionary handle */
+{
+ Dict_item_t* root; /* root item */
+} Dict_t;
+
+typedef struct List_s /* Rule_t list */
+{
+ struct List_s* next; /* next in list */
+ struct Rule_s* rule; /* list item */
+} List_t;
+
+typedef struct Rule_s /* rule item */
+{
+ char* name; /* unbound name */
+ char* path; /* bound path */
+ List_t* prereqs; /* prerequisites */
+ struct Rule_s* leaf; /* recursion leaf alias */
+ int flags; /* RULE_* flags */
+ int making; /* currently make()ing */
+ unsigned long time; /* modification time */
+} Rule_t;
+
+typedef struct Stream_s /* input file stream stack */
+{
+ Stdio_t* fp; /* read stream */
+ char* file; /* stream path */
+ unsigned long line; /* stream line */
+ int flags; /* stream flags */
+} Stream_t;
+
+typedef struct View_s /* viewpath level */
+{
+ struct View_s* next; /* next level in viewpath */
+ int node; /* viewpath node path length */
+ char dir[1]; /* viewpath level dir prefix */
+} View_t;
+
+static struct /* program state */
+{
+ Buf_t* buf; /* work buffer */
+ Buf_t* old; /* dropped buffers */
+ Buf_t* opt; /* option buffer */
+
+ Dict_t* leaf; /* recursion leaf dictionary */
+ Dict_t* libs; /* library dictionary */
+ Dict_t* rules; /* rule dictionary */
+ Dict_t* vars; /* variable dictionary */
+
+ View_t* view; /* viewpath levels */
+
+ char* directory; /* work in this directory */
+ char* id; /* command name */
+ char* file; /* first input file */
+ char* pwd; /* current directory */
+ char* recurse; /* recursion pattern */
+ char* shell; /* ${SHELL} */
+
+ int active; /* targets currently active */
+ int debug; /* negative of debug level */
+ int errors; /* some error(s) occurred */
+ int exec; /* execute actions */
+ int explain; /* explain actions */
+ int force; /* all targets out of date */
+ int ignore; /* ignore command errors */
+ int indent; /* debug indent */
+ int keepgoing; /* do siblings on error */
+ int never; /* never execute */
+ int peek; /* next line already in input */
+ int probed; /* probe already done */
+ int verified; /* don't bother with verify() */
+
+ Stream_t streams[4]; /* input file stream stack */
+ Stream_t* sp; /* input stream stack pointer */
+
+ char input[8*CHUNK]; /* input buffer */
+} state;
+
+static unsigned long make(Rule_t*);
+
+static char mamfile[] = "Mamfile";
+static char sh[] = "/bin/sh";
+
+extern char** environ;
+
+#if !_PACKAGE_ast
+
+#if defined(NeXT) || defined(__NeXT)
+#define getcwd(a,b) getwd(a)
+#endif
+
+/*
+ * emit usage message and exit
+ */
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: %s [-iknFKNV] [-f mamfile] [-r pattern] [-C directory] [-D level] [target ...] [name=value ...]\n", state.id);
+ exit(2);
+}
+
+#endif
+
+/*
+ * output error message identification
+ */
+
+static void
+identify(Stdio_t* sp)
+{
+ if (state.directory)
+ fprintf(sp, "%s [%s]: ", state.id, state.directory);
+ else
+ fprintf(sp, "%s: ", state.id);
+}
+
+/*
+ * emit error message
+ * level:
+ * <0 debug
+ * 0 info
+ * 1 warning
+ * 2 error
+ * >2 exit(level-2)
+ */
+
+static void
+report(int level, char* text, char* item, unsigned long stamp)
+{
+ int i;
+
+ if (level >= state.debug)
+ {
+ if (level)
+ identify(stderr);
+ if (level < 0)
+ {
+ fprintf(stderr, "debug%d: ", level);
+ for (i = 1; i < state.indent; i++)
+ fprintf(stderr, " ");
+ }
+ else
+ {
+ if (state.sp && state.sp->line)
+ {
+ if (state.sp->file)
+ fprintf(stderr, "%s: ", state.sp->file);
+ fprintf(stderr, "%ld: ", state.sp->line);
+ }
+ if (level == 1)
+ fprintf(stderr, "warning: ");
+ else if (level > 1)
+ state.errors = 1;
+ }
+ if (item)
+ fprintf(stderr, "%s: ", item);
+ fprintf(stderr, "%s", text);
+ if (stamp && state.debug <= -2)
+ fprintf(stderr, " %10lu", stamp);
+ fprintf(stderr, "\n");
+ if (level > 2)
+ exit(level - 2);
+ }
+}
+
+/*
+ * don't know how to make or exit code making
+ */
+
+static void
+dont(Rule_t* r, int code, int keepgoing)
+{
+ identify(stderr);
+ if (!code)
+ fprintf(stderr, "don't know how to make %s\n", r->name);
+ else
+ {
+ fprintf(stderr, "*** exit code %d making %s%s\n", code, r->name, state.ignore ? " ignored" : "");
+ unlink(r->name);
+ if (state.ignore)
+ return;
+ }
+ if (!keepgoing)
+ exit(1);
+ state.errors++;
+ r->flags |= RULE_error;
+}
+
+/*
+ * local strrchr()
+ */
+
+static char*
+last(register char* s, register int c)
+{
+ register char* r = 0;
+
+ for (r = 0; *s; s++)
+ if (*s == c)
+ r = s;
+ return r;
+}
+
+/*
+ * open a buffer stream
+ */
+
+static Buf_t*
+buffer(void)
+{
+ register Buf_t* buf;
+
+ if (buf = state.old)
+ state.old = state.old->old;
+ else if (!(buf = newof(0, Buf_t, 1, 0)) || !(buf->buf = newof(0, char, CHUNK, 0)))
+ report(3, "out of space [buffer]", NiL, (unsigned long)0);
+ buf->end = buf->buf + CHUNK;
+ buf->nxt = buf->buf;
+ return buf;
+}
+
+/*
+ * close a buffer stream
+ */
+
+static void
+drop(Buf_t* buf)
+{
+ buf->old = state.old;
+ state.old = buf;
+}
+
+/*
+ * append str length n to buffer and return the buffer base
+ */
+
+static char*
+appendn(Buf_t* buf, char* str, int n)
+{
+ int m;
+ int i;
+
+ if ((n + 1) >= (buf->end - buf->nxt))
+ {
+ i = buf->nxt - buf->buf;
+ m = (((buf->end - buf->buf) + n + CHUNK + 1) / CHUNK) * CHUNK;
+ if (!(buf->buf = newof(buf->buf, char, m, 0)))
+ report(3, "out of space [buffer resize]", NiL, (unsigned long)0);
+ buf->end = buf->buf + m;
+ buf->nxt = buf->buf + i;
+ }
+ memcpy(buf->nxt, str, n + 1);
+ buf->nxt += n;
+ return buf->buf;
+}
+
+/*
+ * append str to buffer and return the buffer base
+ * if str==0 then next pointer reset to base
+ */
+
+static char*
+append(Buf_t* buf, char* str)
+{
+ if (str)
+ return appendn(buf, str, strlen(str));
+ buf->nxt = buf->buf;
+ return buf->buf;
+}
+
+/*
+ * allocate space for s and return the copy
+ */
+
+static char*
+duplicate(char* s)
+{
+ char* t;
+ int n;
+
+ n = strlen(s);
+ if (!(t = newof(0, char, n, 1)))
+ report(3, "out of space [duplicate]", s, (unsigned long)0);
+ strcpy(t, s);
+ return t;
+}
+
+/*
+ * open a new dictionary
+ */
+
+static Dict_t*
+dictionary(void)
+{
+ Dict_t* dict;
+
+ if (!(dict = newof(0, Dict_t, 1, 0)))
+ report(3, "out of space [dictionary]", NiL, (unsigned long)0);
+ return dict;
+}
+
+/*
+ * return the value for item name in dictionary dict
+ * if value!=0 then name entry value is created if necessary and set
+ * uses top-down splaying (ala Tarjan and Sleator)
+ */
+
+static void*
+search(register Dict_t* dict, char* name, void* value)
+{
+ register int cmp;
+ register Dict_item_t* root;
+ register Dict_item_t* t;
+ register Dict_item_t* left;
+ register Dict_item_t* right;
+ register Dict_item_t* lroot;
+ register Dict_item_t* rroot;
+
+ root = dict->root;
+ left = right = lroot = rroot = 0;
+ while (root)
+ {
+ if (!(cmp = strcmp(name, root->name)))
+ break;
+ else if (cmp < 0)
+ {
+ if (root->left && (cmp = strcmp(name, root->left->name)) <= 0)
+ {
+ ROTATE(root, left, right, t);
+ if (!cmp)
+ break;
+ }
+ if (right)
+ right->left = root;
+ else
+ rroot = root;
+ right = root;
+ root = root->left;
+ right->left = 0;
+ }
+ else
+ {
+ if (root->right && (cmp = strcmp(name, root->right->name)) >= 0)
+ {
+ ROTATE(root, right, left, t);
+ if (!cmp)
+ break;
+ }
+ if (left)
+ left->right = root;
+ else
+ lroot = root;
+ left = root;
+ root = root->right;
+ left->right = 0;
+ }
+ }
+ if (root)
+ {
+ if (right)
+ right->left = root->right;
+ else
+ rroot = root->right;
+ if (left)
+ left->right = root->left;
+ else
+ lroot = root->left;
+ }
+ else if (value)
+ {
+ if (!(root = newof(0, Dict_item_t, 1, strlen(name))))
+ report(3, "out of space [dictionary]", name, (unsigned long)0);
+ strcpy(root->name, name);
+ }
+ if (root)
+ {
+ if (value)
+ root->value = value;
+ root->left = lroot;
+ root->right = rroot;
+ dict->root = root;
+ return value ? (void*)root->name : root->value;
+ }
+ if (left)
+ {
+ left->right = rroot;
+ dict->root = lroot;
+ }
+ else if (right)
+ {
+ right->left = lroot;
+ dict->root = rroot;
+ }
+ return 0;
+}
+
+/*
+ * low level for walk()
+ */
+
+static int
+apply(Dict_t* dict, Dict_item_t* item, int (*func)(Dict_item_t*, void*), void* handle)
+{
+ register Dict_item_t* right;
+
+ do
+ {
+ right = item->right;
+ if (item->left && apply(dict, item->left, func, handle))
+ return -1;
+ if ((*func)(item, handle))
+ return -1;
+ } while (item = right);
+ return 0;
+}
+
+/*
+ * apply func to each dictionary item
+ */
+
+static int
+walk(Dict_t* dict, int (*func)(Dict_item_t*, void*), void* handle)
+{
+ return dict->root ? apply(dict, dict->root, func, handle) : 0;
+}
+
+/*
+ * return a rule pointer for name
+ */
+
+static Rule_t*
+rule(char* name)
+{
+ Rule_t* r;
+
+ if (!(r = (Rule_t*)search(state.rules, name, NiL)))
+ {
+ if (!(r = newof(0, Rule_t, 1, 0)))
+ report(3, "out of space [rule]", name, (unsigned long)0);
+ r->name = (char*)search(state.rules, name, (void*)r);
+ }
+ return r;
+}
+
+/*
+ * prepend p onto rule r prereqs
+ */
+
+static void
+cons(Rule_t* r, Rule_t* p)
+{
+ register List_t* x;
+
+ for (x = r->prereqs; x && x->rule != p; x = x->next);
+ if (!x)
+ {
+ if (!(x = newof(0, List_t, 1, 0)))
+ report(3, "out of space [list]", r->name, (unsigned long)0);
+ x->rule = p;
+ x->next = r->prereqs;
+ r->prereqs = x;
+ }
+}
+
+/*
+ * initialize the viewpath
+ */
+
+static void
+view(void)
+{
+ register char* s;
+ register char* t;
+ register char* p;
+ register View_t* vp;
+
+ View_t* zp;
+ int c;
+ int n;
+
+ Stat_t st;
+ Stat_t ts;
+
+ char buf[CHUNK];
+
+ if (stat(".", &st))
+ report(3, "cannot stat", ".", (unsigned long)0);
+ if ((s = (char*)search(state.vars, "PWD", NiL)) && !stat(s, &ts) &&
+ ts.st_dev == st.st_dev && ts.st_ino == st.st_ino)
+ state.pwd = s;
+ if (!state.pwd)
+ {
+ if (!getcwd(buf, sizeof(buf) - 1))
+ report(3, "cannot determine PWD", NiL, (unsigned long)0);
+ state.pwd = duplicate(buf);
+ search(state.vars, "PWD", state.pwd);
+ }
+ if ((s = (char*)search(state.vars, "VPATH", NiL)) && *s)
+ {
+ zp = 0;
+ for (;;)
+ {
+ for (t = s; *t && *t != ':'; t++);
+ if (c = *t)
+ *t = 0;
+ if (!state.view)
+ {
+ /*
+ * determine the viewpath offset
+ */
+
+ if (stat(s, &st))
+ report(3, "cannot stat top view", s, (unsigned long)0);
+ if (stat(state.pwd, &ts))
+ report(3, "cannot stat", state.pwd, (unsigned long)0);
+ if (ts.st_dev == st.st_dev && ts.st_ino == st.st_ino)
+ p = ".";
+ else
+ {
+ p = state.pwd + strlen(state.pwd);
+ while (p > state.pwd)
+ if (*--p == '/')
+ {
+ if (p == state.pwd)
+ report(3, ". not under VPATH", s, (unsigned long)0);
+ *p = 0;
+ if (stat(state.pwd, &ts))
+ report(3, "cannot stat", state.pwd, (unsigned long)0);
+ *p = '/';
+ if (ts.st_dev == st.st_dev && ts.st_ino == st.st_ino)
+ {
+ p++;
+ break;
+ }
+ }
+ if (p <= state.pwd)
+ report(3, "cannot determine viewpath offset", s, (unsigned long)0);
+ }
+ }
+ n = strlen(s);
+ if (!(vp = newof(0, View_t, 1, strlen(p) + n + 1)))
+ report(3, "out of space [view]", s, (unsigned long)0);
+ vp->node = n + 1;
+ strcpy(vp->dir, s);
+ *(vp->dir + n) = '/';
+ strcpy(vp->dir + n + 1, p);
+ report(-4, vp->dir, "view", (unsigned long)0);
+ if (!state.view)
+ state.view = zp = vp;
+ else
+ zp = zp->next = vp;
+ if (!c)
+ break;
+ *t++ = c;
+ s = t;
+ }
+ }
+}
+
+/*
+ * return next '?' or '}' in nested '}'
+ */
+
+static char*
+cond(register char* s)
+{
+ register int n;
+
+ if (*s == '?')
+ s++;
+ n = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case '{':
+ n++;
+ continue;
+ case '}':
+ if (!n--)
+ break;
+ continue;
+ case '?':
+ if (!n)
+ break;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ return s - 1;
+}
+
+/*
+ * expand var refs from s into buf
+ */
+
+static void
+substitute(Buf_t* buf, register char* s)
+{
+ register char* t;
+ register char* v;
+ register char* q;
+ register char* b;
+ register int c;
+ register int n;
+ int a = 0;
+ int i;
+
+ while (c = *s++)
+ {
+ if (c == '$' && *s == '{')
+ {
+ b = s - 1;
+ i = 1;
+ for (n = *(t = ++s) == '-' ? 0 : '-'; (c = *s) && c != '?' && c != '+' && c != n && c != ':' && c != '=' && c != '[' && c != '}'; s++)
+ if (!isalnum(c) && c != '_')
+ i = 0;
+ *s = 0;
+ if (c == '[')
+ {
+ append(buf, b);
+ *s = c;
+ continue;
+ }
+ v = (char*)search(state.vars, t, NiL);
+ if ((c == ':' || c == '=') && (!v || c == ':' && !*v))
+ {
+ append(buf, b);
+ *s = c;
+ continue;
+ }
+ if (t[0] == 'A' && t[1] == 'R' && t[2] == 0)
+ a = 1;
+ *s = c;
+ if (c && c != '}')
+ {
+ n = 1;
+ for (t = ++s; *s; s++)
+ if (*s == '{')
+ n++;
+ else if (*s == '}' && !--n)
+ break;
+ }
+ switch (c)
+ {
+ case '?':
+ q = cond(t - 1);
+ if (v)
+ {
+ if (((q - t) != 1 || *t != '*') && strncmp(v, t, q - t))
+ v = 0;
+ }
+ else if (q == t)
+ v = s;
+ t = cond(q);
+ if (v)
+ {
+ if (t > q)
+ {
+ c = *t;
+ *t = 0;
+ substitute(buf, q + 1);
+ *t = c;
+ }
+ }
+ else
+ {
+ q = cond(t);
+ if (q > t)
+ {
+ c = *q;
+ *q = 0;
+ substitute(buf, t + 1);
+ *q = c;
+ }
+ }
+ break;
+ case '+':
+ case '-':
+ if ((v == 0 || *v == 0) == (c == '-'))
+ {
+ c = *s;
+ *s = 0;
+ substitute(buf, t);
+ *s = c;
+ break;
+ }
+ if (c != '-')
+ break;
+ /*FALLTHROUGH*/
+ case 0:
+ case '=':
+ case '}':
+ if (v)
+ {
+ if (a && t[0] == 'm' && t[1] == 'a' && t[2] == 'm' && t[3] == '_' && t[4] == 'l' && t[5] == 'i' && t[6] == 'b')
+ {
+ for (t = v; *t == ' '; t++);
+ for (; *t && *t != ' '; t++);
+ if (*t)
+ *t = 0;
+ else
+ t = 0;
+ substitute(buf, v);
+ if (t)
+ *t = ' ';
+ }
+ else
+ substitute(buf, v);
+ }
+ else if (i)
+ {
+ c = *s;
+ *s = 0;
+ append(buf, b);
+ *s = c;
+ continue;
+ }
+ break;
+ }
+ if (*s)
+ s++;
+ }
+ else
+ add(buf, c);
+ }
+}
+
+/*
+ * expand var refs from s into buf and return buf base
+ */
+
+static char*
+expand(Buf_t* buf, char* s)
+{
+ substitute(buf, s);
+ return use(buf);
+}
+
+/*
+ * stat() with .exe check
+ */
+
+static char*
+status(Buf_t* buf, int off, char* path, struct stat* st)
+{
+ int r;
+ char* s;
+ Buf_t* tmp;
+
+ if (!stat(path, st))
+ return path;
+ if (!(tmp = buf))
+ {
+ tmp = buffer();
+ off = 0;
+ }
+ if (off)
+ set(tmp, off);
+ else
+ append(tmp, path);
+ append(tmp, ".exe");
+ s = use(tmp);
+ r = stat(s, st);
+ if (!buf)
+ {
+ drop(tmp);
+ s = path;
+ }
+ if (r)
+ {
+ if (off)
+ s[off] = 0;
+ s = 0;
+ }
+ return s;
+}
+
+/*
+ * return path to file
+ */
+
+static char*
+find(Buf_t* buf, char* file, struct stat* st)
+{
+ char* s;
+ View_t* vp;
+ int node;
+ int c;
+ int o;
+
+ if (s = status(buf, 0, file, st))
+ {
+ report(-3, s, "find", (unsigned long)0);
+ return s;
+ }
+ if (vp = state.view)
+ {
+ node = 0;
+ if (*file == '/')
+ {
+ do
+ {
+ if (!strncmp(file, vp->dir, vp->node))
+ {
+ file += vp->node;
+ node = 2;
+ break;
+ }
+ } while (vp = vp->next);
+ }
+ else
+ vp = vp->next;
+ if (vp)
+ do
+ {
+ if (node)
+ {
+ c = vp->dir[vp->node];
+ vp->dir[vp->node] = 0;
+ append(buf, vp->dir);
+ vp->dir[vp->node] = c;
+ }
+ else
+ {
+ append(buf, vp->dir);
+ append(buf, "/");
+ }
+ append(buf, file);
+ o = get(buf);
+ s = use(buf);
+ if (s = status(buf, o, s, st))
+ {
+ report(-3, s, "find", (unsigned long)0);
+ return s;
+ }
+ } while (vp = vp->next);
+ }
+ return 0;
+}
+
+/*
+ * bind r to a file and return the modify time
+ */
+
+static unsigned long
+bind(Rule_t* r)
+{
+ char* s;
+ Buf_t* buf;
+ struct stat st;
+
+ buf = buffer();
+ if (s = find(buf, r->name, &st))
+ {
+ if (s != r->name)
+ r->path = duplicate(s);
+ r->time = st.st_mtime;
+ r->flags |= RULE_exists;
+ }
+ drop(buf);
+ return r->time;
+}
+
+/*
+ * pop the current input file
+ */
+
+static int
+pop(void)
+{
+ int r;
+
+ if (!state.sp)
+ report(3, "input stack underflow", NiL, (unsigned long)0);
+ if (!state.sp->fp || (state.sp->flags & STREAM_KEEP))
+ r = 0;
+ else if (state.sp->flags & STREAM_PIPE)
+ r = pclose(state.sp->fp);
+ else
+ r = fclose(state.sp->fp);
+ if (state.sp == state.streams)
+ state.sp = 0;
+ else
+ state.sp--;
+ return r;
+}
+
+/*
+ * push file onto the input stack
+ */
+
+static int
+push(char* file, Stdio_t* fp, int flags)
+{
+ char* path;
+ Buf_t* buf;
+ struct stat st;
+
+ if (!state.sp)
+ state.sp = state.streams;
+ else if (++state.sp >= &state.streams[elementsof(state.streams)])
+ report(3, "input stream stack overflow", NiL, (unsigned long)0);
+ if (state.sp->fp = fp)
+ state.sp->file = "pipeline";
+ else if (flags & STREAM_PIPE)
+ report(3, "pipe error", file, (unsigned long)0);
+ else if (!file || !strcmp(file, "-") || !strcmp(file, "/dev/stdin"))
+ {
+ flags |= STREAM_KEEP;
+ state.sp->file = "/dev/stdin";
+ state.sp->fp = stdin;
+ }
+ else
+ {
+ buf = buffer();
+ if (path = find(buf, file, &st))
+ {
+ if (!(state.sp->fp = fopen(path, "r")))
+ report(3, "cannot read", path, (unsigned long)0);
+ state.sp->file = duplicate(path);
+ drop(buf);
+ }
+ else
+ {
+ drop(buf);
+ pop();
+ if (flags & STREAM_MUST)
+ report(3, "not found", file, (unsigned long)0);
+ return 0;
+ }
+ }
+ state.sp->flags = flags;
+ state.sp->line = 0;
+ return 1;
+}
+
+/*
+ * return the next input line
+ */
+
+static char*
+input(void)
+{
+ char* e;
+
+ if (!state.sp)
+ report(3, "no input file stream", NiL, (unsigned long)0);
+ if (state.peek)
+ state.peek = 0;
+ else if (!fgets(state.input, sizeof(state.input), state.sp->fp))
+ return 0;
+ else if (*state.input && *(e = state.input + strlen(state.input) - 1) == '\n')
+ *e = 0;
+ state.sp->line++;
+ return state.input;
+}
+
+/*
+ * pass shell action s to ${SHELL:-/bin/sh}
+ * the -c wrapper ensures that scripts are run in the selected shell
+ * even on systems that otherwise demand #! magic (can you say cygwin)
+ */
+
+static int
+execute(register char* s)
+{
+ register int c;
+ Buf_t* buf;
+
+ if (!state.shell && (!(state.shell = (char*)search(state.vars, "SHELL", NiL)) || !strcmp(state.shell, sh)))
+ state.shell = sh;
+ buf = buffer();
+ append(buf, state.shell);
+ append(buf, " -c '");
+ while (c = *s++)
+ {
+ if (c == '\'')
+ {
+ add(buf, c);
+ for (s--; *s == c; s++)
+ {
+ add(buf, '\\');
+ add(buf, c);
+ }
+ }
+ add(buf, c);
+ }
+ add(buf, '\'');
+ s = use(buf);
+ report(-5, s, "exec", (unsigned long)0);
+ if ((c = system(s)) > 255)
+ c >>= 8;
+ drop(buf);
+ return c;
+}
+
+/*
+ * run action s to update r
+ */
+
+static unsigned long
+run(Rule_t* r, register char* s)
+{
+ register Rule_t* q;
+ register char* t;
+ register int c;
+ register View_t* v;
+ int i;
+ int j;
+ int x;
+ Stat_t st;
+ Buf_t* buf;
+
+ if (r->flags & RULE_error)
+ return r->time;
+ buf = buffer();
+ if (!strncmp(s, "mamake -r ", 10))
+ {
+ state.verified = 1;
+ x = !state.never;
+ }
+ else
+ x = state.exec;
+ if (x)
+ append(buf, "trap - 1 2 3 15\nPATH=.:$PATH\nset -x\n");
+ if (state.view)
+ {
+ do
+ {
+ for (; delimiter(*s); s++)
+ add(buf, *s);
+ for (t = s; *s && !delimiter(*s); s++);
+ c = *s;
+ *s = 0;
+ if (c == '=')
+ {
+ append(buf, t);
+ continue;
+ }
+ if ((q = (Rule_t*)search(state.rules, t, NiL)) && q->path && !(q->flags & RULE_generated))
+ append(buf, q->path);
+ else
+ {
+ append(buf, t);
+ if (*t == '-' && *(t + 1) == 'I' && (*(t + 2) || c))
+ {
+ if (*(t + 2))
+ i = 2;
+ else
+ {
+ for (i = 3; *(t + i) == ' ' || *(t + i) == '\t'; i++);
+ *s = c;
+ for (s = t + i; *s && *s != ' ' && *s != '\t' && *s != '\n'; s++);
+ c = *s;
+ *s = 0;
+ append(buf, t + 2);
+ }
+ if (*(t + i) && *(t + i) != '/')
+ {
+ v = state.view;
+ while (v = v->next)
+ {
+ add(buf, ' ');
+ for (j = 0; j < i; j++)
+ add(buf, *(t + j));
+ append(buf, v->dir);
+ if (*(t + i) != '.' || *(t + i + 1))
+ {
+ add(buf, '/');
+ append(buf, t + i);
+ }
+ }
+ }
+ }
+ }
+ } while (*s = c);
+ s = use(buf);
+ }
+ else if (x)
+ {
+ append(buf, s);
+ s = use(buf);
+ }
+ if (x)
+ {
+ if (c = execute(s))
+ dont(r, c, state.keepgoing);
+ if (status((Buf_t*)0, 0, r->name, &st))
+ {
+ r->time = st.st_mtime;
+ r->flags |= RULE_exists;
+ }
+ else
+ r->time = NOW;
+ }
+ else
+ {
+ fprintf(stdout, "%s\n", s);
+ if (state.debug)
+ fflush(stdout);
+ r->time = NOW;
+ r->flags |= RULE_exists;
+ }
+ drop(buf);
+ return r->time;
+}
+
+/*
+ * return the full path for s using buf workspace
+ */
+
+static char*
+path(Buf_t* buf, char* s, int must)
+{
+ register char* p;
+ register char* d;
+ register char* x;
+ char* e;
+ register int c;
+ int t;
+ int o;
+ Stat_t st;
+
+ for (e = s; *e && *e != ' ' && *e != '\t'; e++);
+ t = *e;
+ if ((x = status(buf, 0, s, &st)) && (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ return x;
+ if (!(p = (char*)search(state.vars, "PATH", NiL)))
+ report(3, "variable not defined", "PATH", (unsigned long)0);
+ do
+ {
+ for (d = p; *p && *p != ':'; p++);
+ c = *p;
+ *p = 0;
+ if (*d && (*d != '.' || *(d + 1)))
+ {
+ append(buf, d);
+ add(buf, '/');
+ }
+ *p = c;
+ if (t)
+ *e = 0;
+ append(buf, s);
+ if (t)
+ *e = t;
+ o = get(buf);
+ x = use(buf);
+ if ((x = status(buf, o, x, &st)) && (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ return x;
+ } while (*p++);
+ if (must)
+ report(3, "command not found", s, (unsigned long)0);
+ return 0;
+}
+
+/*
+ * generate (if necessary) and read the MAM probe information
+ * done on the first `setv CC ...'
+ */
+
+static void
+probe(void)
+{
+ register char* cc;
+ register char* s;
+ unsigned long h;
+ unsigned long q;
+ Buf_t* buf;
+ Buf_t* pro;
+ Buf_t* tmp;
+ struct stat st;
+
+ static char let[] = "ABCDEFGHIJKLMNOP";
+ static char cmd[] = "mamprobe";
+
+ if (!(cc = (char*)search(state.vars, "CC", NiL)))
+ cc = "cc";
+ buf = buffer();
+ s = path(buf, cmd, 1);
+ q = stat(s, &st) ? (unsigned long)0 : (unsigned long)st.st_mtime;
+ pro = buffer();
+ s = cc = path(pro, cc, 1);
+ for (h = 0; *s; s++)
+ h = h * 0x63c63cd9L + *s + 0x9c39c33dL;
+ if (!(s = (char*)search(state.vars, "INSTALLROOT", NiL)))
+ report(3, "variable must be defined", "INSTALLROOT", (unsigned long)0);
+ append(buf, s);
+ append(buf, "/lib/probe/C/mam/");
+ for (h &= 0xffffffffL; h; h >>= 4)
+ add(buf, let[h & 0xf]);
+ s = use(buf);
+ h = stat(s, &st) ? (unsigned long)0 : (unsigned long)st.st_mtime;
+ if (h < q || !push(s, (Stdio_t*)0, 0))
+ {
+ tmp = buffer();
+ append(tmp, cmd);
+ add(tmp, ' ');
+ append(tmp, s);
+ add(tmp, ' ');
+ append(tmp, cc);
+ if (execute(use(tmp)))
+ report(3, "cannot generate probe info", s, (unsigned long)0);
+ drop(tmp);
+ if (!push(s, (Stdio_t*)0, 0))
+ report(3, "cannot read probe info", s, (unsigned long)0);
+ }
+ drop(pro);
+ drop(buf);
+ make(rule(""));
+ pop();
+}
+
+/*
+ * add attributes in s to r
+ */
+
+static void
+attributes(register Rule_t* r, register char* s)
+{
+ register char* t;
+ register int n;
+
+ for (;;)
+ {
+ for (; *s == ' '; s++);
+ for (t = s; *s && *s != ' '; s++);
+ if (!(n = s - t))
+ break;
+ switch (*t)
+ {
+ case 'd':
+ if (n == 8 && !strncmp(t, "dontcare", n))
+ r->flags |= RULE_dontcare;
+ break;
+ case 'g':
+ if (n == 9 && !strncmp(t, "generated", n))
+ r->flags |= RULE_generated;
+ break;
+ case 'i':
+ if (n == 6 && !strncmp(t, "ignore", n))
+ r->flags |= RULE_ignore;
+ else if (n == 8 && !strncmp(t, "implicit", n))
+ r->flags |= RULE_implicit;
+ break;
+ case 'v':
+ if (n == 7 && !strncmp(t, "virtual", n))
+ r->flags |= RULE_virtual;
+ break;
+ }
+ }
+}
+
+/*
+ * define ${mam_libX} for library reference lib
+ */
+
+static char*
+require(char* lib, int dontcare)
+{
+ register int c;
+ char* s;
+ char* r;
+ FILE* f;
+ Buf_t* buf;
+ Buf_t* tmp;
+ struct stat st;
+
+ static int dynamic = -1;
+
+ if (dynamic < 0)
+ dynamic = (s = search(state.vars, "mam_cc_L", NiL)) ? atoi(s) : 0;
+ if (!(r = search(state.vars, lib, NiL)))
+ {
+ buf = buffer();
+ tmp = buffer();
+ s = 0;
+ for (;;)
+ {
+ if (s)
+ append(buf, s);
+ if (r = search(state.vars, "mam_cc_PREFIX_ARCHIVE", NiL))
+ append(buf, r);
+ append(buf, lib + 2);
+ if (r = search(state.vars, "mam_cc_SUFFIX_ARCHIVE", NiL))
+ append(buf, r);
+ r = expand(tmp, use(buf));
+ if (!stat(r, &st))
+ break;
+ if (s)
+ {
+ r = lib;
+ break;
+ }
+ s = "${INSTALLROOT}/lib/";
+ if (dynamic)
+ {
+ append(buf, s);
+ if (r = search(state.vars, "mam_cc_PREFIX_SHARED", NiL))
+ append(buf, r);
+ append(buf, lib + 2);
+ if (r = search(state.vars, "mam_cc_SUFFIX_SHARED", NiL))
+ append(buf, r);
+ r = expand(tmp, use(buf));
+ if (!stat(r, &st))
+ {
+ r = lib;
+ break;
+ }
+ }
+ }
+ if (r != lib)
+ r = duplicate(r);
+ search(state.vars, lib, r);
+ append(tmp, lib + 2);
+ append(tmp, ".req");
+ if (!(f = fopen(use(tmp), "r")))
+ {
+ append(tmp, "${INSTALLROOT}/lib/lib/");
+ append(tmp, lib + 2);
+ f = fopen(expand(buf, use(tmp)), "r");
+ }
+ if (f)
+ {
+ for (;;)
+ {
+ while ((c = fgetc(f)) == ' ' || c == '\t' || c == '\n');
+ if (c == EOF)
+ break;
+ do
+ {
+ add(tmp, c);
+ } while ((c = fgetc(f)) != EOF && c != ' ' && c != '\t' && c != '\n');
+ s = use(tmp);
+ if (s[0] && (s[0] != '-' || s[1]))
+ {
+ add(buf, ' ');
+ append(buf, require(s, 0));
+ }
+ }
+ fclose(f);
+ r = use(buf);
+ }
+ else if (dontcare)
+ {
+ append(tmp, "set -\n");
+ append(tmp, "cd /tmp\n");
+ append(tmp, "echo 'int main(){return 0;}' > x.${!-$$}.c\n");
+ append(tmp, "${CC} ${CCFLAGS} -o x.${!-$$}.x x.${!-$$}.c ");
+ append(tmp, r);
+ append(tmp, " >/dev/null 2>&1\n");
+ append(tmp, "c=$?\n");
+ append(tmp, "rm -f x.${!-$$}.[cox]\n");
+ append(tmp, "exit $c\n");
+ if (execute(expand(buf, use(tmp))))
+ r = "";
+ }
+ r = duplicate(r);
+ search(state.vars, lib, r);
+ append(tmp, "mam_lib");
+ append(tmp, lib + 2);
+ search(state.vars, use(tmp), r);
+ drop(tmp);
+ drop(buf);
+ }
+ return r;
+}
+
+/*
+ * input() until `done r'
+ */
+
+static unsigned long
+make(Rule_t* r)
+{
+ register char* s;
+ register char* t;
+ register char* u;
+ register char* v;
+ register Rule_t* q;
+ unsigned long z;
+ unsigned long x;
+ Buf_t* buf;
+ Buf_t* cmd;
+
+ r->making++;
+ if (r->flags & RULE_active)
+ state.active++;
+ if (*r->name)
+ {
+ z = bind(r);
+ state.indent++;
+ report(-1, r->name, "make", r->time);
+ }
+ else
+ z = 0;
+ buf = buffer();
+ cmd = 0;
+ while (s = input())
+ {
+ for (; *s == ' '; s++);
+ for (; isdigit(*s); s++);
+ for (; *s == ' '; s++);
+ for (u = s; *s && *s != ' '; s++);
+ if (*s)
+ {
+ for (*s++ = 0; *s == ' '; s++);
+ for (t = s; *s && *s != ' '; s++);
+ if (*s)
+ for (*s++ = 0; *s == ' '; s++);
+ v = s;
+ }
+ else
+ t = v = s;
+ switch (KEY(u[0], u[1], u[2], u[3]))
+ {
+ case KEY('b','i','n','d'):
+ if ((t[0] == '-' || t[0] == '+') && t[1] == 'l' && (s = require(t, !strcmp(v, "dontcare"))) && strncmp(r->name, "FEATURE/", 8) && strcmp(r->name, "configure.h"))
+ for (;;)
+ {
+ for (t = s; *s && *s != ' '; s++);
+ if (*s)
+ *s = 0;
+ else
+ s = 0;
+ if (*t)
+ {
+ q = rule(expand(buf, t));
+ attributes(q, v);
+ x = bind(q);
+ if (z < x)
+ z = x;
+ if (q->flags & RULE_error)
+ r->flags |= RULE_error;
+ }
+ if (!s)
+ break;
+ for (*s++ = ' '; *s == ' '; s++);
+ }
+ continue;
+ case KEY('d','o','n','e'):
+ q = rule(expand(buf, t));
+ if (q != r)
+ report(2, "improper done statement", t, (unsigned long)0);
+ attributes(r, v);
+ if (cmd && state.active && (state.force || r->time < z || !r->time && !z))
+ {
+ if (state.explain && !state.force)
+ {
+ if (!r->time)
+ fprintf(stderr, "%s [not found]\n", r->name);
+ else
+ fprintf(stderr, "%s [%lu] older than prerequisites [%lu]\n", r->name, r->time, z);
+ }
+ substitute(buf, use(cmd));
+ x = run(r, use(buf));
+ if (z < x)
+ z = x;
+ }
+ r->flags |= RULE_made;
+ if (!(r->flags & (RULE_dontcare|RULE_error|RULE_exists|RULE_generated|RULE_implicit|RULE_virtual)))
+ dont(r, 0, state.keepgoing);
+ break;
+ case KEY('e','x','e','c'):
+ r->flags |= RULE_generated;
+ if (r->path)
+ {
+ free(r->path);
+ r->path = 0;
+ r->time = 0;
+ }
+ if (state.active)
+ {
+ if (cmd)
+ add(cmd, '\n');
+ else
+ cmd = buffer();
+ append(cmd, v);
+ }
+ continue;
+ case KEY('m','a','k','e'):
+ q = rule(expand(buf, t));
+ if (!q->making)
+ {
+ attributes(q, v);
+ x = make(q);
+ if (!(q->flags & RULE_ignore) && z < x)
+ z = x;
+ if (q->flags & RULE_error)
+ r->flags |= RULE_error;
+ }
+ continue;
+ case KEY('p','r','e','v'):
+ q = rule(expand(buf, t));
+ if (!q->making)
+ {
+ if (!(q->flags & RULE_ignore) && z < q->time)
+ z = q->time;
+ if (q->flags & RULE_error)
+ r->flags |= RULE_error;
+ state.indent++;
+ report(-2, q->name, "prev", q->time);
+ state.indent--;
+ }
+ continue;
+ case KEY('s','e','t','v'):
+ if (!search(state.vars, t, NiL))
+ {
+ if (*v == '"')
+ {
+ s = v + strlen(v) - 1;
+ if (*s == '"')
+ {
+ *s = 0;
+ v++;
+ }
+ }
+ search(state.vars, t, duplicate(expand(buf, v)));
+ }
+ if (!state.probed && t[0] == 'C' && t[1] == 'C' && !t[2])
+ {
+ state.probed = 1;
+ probe();
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ drop(buf);
+ if (cmd)
+ drop(cmd);
+ if (*r->name)
+ {
+ report(-1, r->name, "done", z);
+ state.indent--;
+ }
+ if (r->flags & RULE_active)
+ state.active--;
+ r->making--;
+ return r->time = z;
+}
+
+/*
+ * verify that active targets were made
+ */
+
+static int
+verify(Dict_item_t* item, void* handle)
+{
+ Rule_t* r = (Rule_t*)item->value;
+
+ if ((r->flags & (RULE_active|RULE_error|RULE_made)) == RULE_active)
+ dont(r, 0, 1);
+ return 0;
+}
+
+/*
+ * return 1 if name is an initializer
+ */
+
+static int
+initializer(char* name)
+{
+ register char* s;
+
+ if (s = last(name, '/'))
+ s++;
+ else
+ s = name;
+ return s[0] == 'I' && s[1] == 'N' && s[2] == 'I' && s[3] == 'T';
+}
+
+/*
+ * update recursion leaf r and its prerequisites
+ */
+
+static int
+update(register Rule_t* r)
+{
+ register List_t* x;
+ Buf_t* buf;
+
+ static char cmd[] = "${MAMAKE} -C ";
+ static char arg[] = " ${MAMAKEARGS}";
+
+ r->flags |= RULE_made;
+ if (r->leaf)
+ r->leaf->flags |= RULE_made;
+ for (x = r->prereqs; x; x = x->next)
+ if (x->rule->leaf && !(x->rule->flags & RULE_made))
+ update(x->rule);
+ buf = buffer();
+ substitute(buf, cmd);
+ append(buf, r->name);
+ substitute(buf, arg);
+ run(r, use(buf));
+ drop(buf);
+ return 0;
+}
+
+/*
+ * scan makefile prereqs
+ */
+
+static int
+scan(Dict_item_t* item, void* handle)
+{
+ register Rule_t* r = (Rule_t*)item->value;
+ register char* s;
+ register char* t;
+ register char* u;
+ register char* w;
+ Rule_t* q;
+ int i;
+ int j;
+ int k;
+ int p;
+ Buf_t* buf;
+
+ static char* files[] =
+ {
+ "Nmakefile",
+ "nmakefile",
+ "Makefile",
+ "makefile"
+ };
+
+ /*
+ * drop non-leaf rules
+ */
+
+ if (!r->leaf)
+ return 0;
+
+ /*
+ * always make initializers
+ */
+
+ if (initializer(r->name))
+ {
+ if (!(r->flags & RULE_made))
+ update(r);
+ return 0;
+ }
+ buf = buffer();
+ for (i = 0; i < elementsof(files); i++)
+ {
+ append(buf, r->name);
+ add(buf, '/');
+ append(buf, files[i]);
+ if (push(use(buf), (Stdio_t*)0, 0))
+ {
+ while (s = input())
+ {
+ j = p = 0;
+ while (*s)
+ {
+ for (k = 1; (i = *s) == ' ' || i == '\t' || i == '"' || i == '\''; s++);
+ for (t = s; (i = *s) && i != ' ' && i != '\t' && i != '"' && i != '\'' && i != '\\' && i != ':'; s++)
+ if (i == '/')
+ t = s + 1;
+ else if (i == '.' && *(s + 1) != 'c' && *(s + 1) != 'C' && *(s + 1) != 'h' && *(s + 1) != 'H' && t[0] == 'l' && t[1] == 'i' && t[2] == 'b')
+ *s = 0;
+ if (*s)
+ *s++ = 0;
+ if (!t[0])
+ k = 0;
+ else if ((t[0] == '-' || t[0] == '+') && t[1] == 'l' && t[2])
+ {
+ append(buf, "lib");
+ append(buf, t + 2);
+ t = use(buf);
+ }
+ else if (p)
+ {
+ if (t[0] == '+' && !t[1])
+ p = 2;
+ else if (p == 1)
+ {
+ if (i != ':' || strncmp(s, "command", 7))
+ {
+ append(buf, "lib");
+ append(buf, t);
+ t = use(buf);
+ }
+ if (i == ':')
+ while (*s && (*s == ' ' || *s == '\t'))
+ s++;
+ }
+ }
+ else if (i == ':')
+ {
+ if (j != ':' || !isupper(*t))
+ k = 0;
+ else if (!strcmp(t, "PACKAGE"))
+ {
+ p = 1;
+ k = 0;
+ }
+ else
+ for (u = t; *u; u++)
+ if (isupper(*u))
+ *u = tolower(*u);
+ else if (!isalnum(*u))
+ {
+ k = 0;
+ break;
+ }
+ }
+ else if (t[0] != 'l' || t[1] != 'i' || t[2] != 'b')
+ k = 0;
+ else
+ for (u = t + 3; *u; u++)
+ if (!isalnum(*u))
+ {
+ k = 0;
+ break;
+ }
+ if (k && ((q = (Rule_t*)search(state.leaf, t, NiL)) && q != r || *t++ == 'l' && *t++ == 'i' && *t++ == 'b' && *t && (q = (Rule_t*)search(state.leaf, t, NiL)) && q != r))
+ {
+ for (t = w = r->name; *w; w++)
+ if (*w == '/')
+ t = w + 1;
+ if (t[0] == 'l' && t[1] == 'i' && t[2] == 'b')
+ t += 3;
+ for (u = w = q->name; *w; w++)
+ if (*w == '/')
+ u = w + 1;
+ if (strcmp(t, u))
+ cons(r, q);
+ }
+ j = i;
+ }
+ }
+ pop();
+ for (s = 0, w = r->name; *w; w++)
+ if (*w == '/')
+ s = w;
+ if (s)
+ {
+ if ((s - r->name) > 3 && *(s - 1) == 'b' && *(s - 2) == 'i' && *(s - 3) == 'l' && *(s - 4) != '/')
+ {
+ /*
+ * foolib : foo : libfoo
+ */
+
+ *(s - 3) = 0;
+ q = (Rule_t*)search(state.leaf, r->name, NiL);
+ if (q && q != r)
+ cons(r, q);
+ for (t = w = r->name; *w; w++)
+ if (*w == '/')
+ t = w + 1;
+ append(buf, "lib");
+ append(buf, t);
+ q = (Rule_t*)search(state.leaf, use(buf), NiL);
+ if (q && q != r)
+ cons(r, q);
+ *(s - 3) = 'l';
+ }
+ else if (((s - r->name) != 3 || *(s - 1) != 'b' || *(s - 2) != 'i' || *(s - 3) != 'l') && (*(s + 1) != 'l' || *(s + 2) != 'i' || *(s + 3) != 'b'))
+ {
+ /*
+ * huh/foobar : lib/libfoo
+ */
+
+ s++;
+ t = s + strlen(s);
+ while (--t > s)
+ {
+ append(buf, "lib/lib");
+ appendn(buf, s, t - s);
+ q = (Rule_t*)search(state.leaf, use(buf), NiL);
+ if (q && q != r)
+ cons(r, q);
+ }
+ }
+ }
+ break;
+ }
+ }
+ drop(buf);
+ return 0;
+}
+
+/*
+ * descend into op and its prereqs
+ */
+
+static int
+descend(Dict_item_t* item, void* handle)
+{
+ Rule_t* r = (Rule_t*)item->value;
+
+ if (!state.active && (!(r->flags & RULE_active) || !(r = (Rule_t*)search(state.leaf, r->name, NiL))))
+ return 0;
+ return r->leaf && !(r->flags & RULE_made) ? update(r) : 0;
+}
+
+/*
+ * append the non-leaf active targets to state.opt
+ */
+
+static int
+active(Dict_item_t* item, void* handle)
+{
+ Rule_t* r = (Rule_t*)item->value;
+
+ if (r->flags & RULE_active)
+ {
+ if (r->leaf || search(state.leaf, r->name, NiL))
+ state.active = 0;
+ else
+ {
+ add(state.opt, ' ');
+ append(state.opt, r->name);
+ }
+ }
+ return 0;
+}
+
+/*
+ * recurse on mamfiles in subdirs matching pattern
+ */
+
+static int
+recurse(char* pattern)
+{
+ register char* s;
+ register char* t;
+ Rule_t* r;
+ Buf_t* buf;
+ Buf_t* tmp;
+ struct stat st;
+
+ /*
+ * first determine the MAM subdirs
+ */
+
+ tmp = buffer();
+ buf = buffer();
+ state.exec = !state.never;
+ state.leaf = dictionary();
+ append(buf, "ls -d ");
+ append(buf, pattern);
+ s = use(buf);
+ push("recurse", popen(s, "r"), STREAM_PIPE);
+ while (s = input())
+ {
+ append(buf, s);
+ add(buf, '/');
+ append(buf, mamfile);
+ if (find(tmp, use(buf), &st))
+ {
+ r = rule(s);
+ if (t = last(r->name, '/'))
+ t++;
+ else
+ t = r->name;
+ r->leaf = rule(t);
+ search(state.leaf, t, r);
+ }
+ }
+ pop();
+ drop(buf);
+ drop(tmp);
+
+ /*
+ * grab the non-leaf active targets
+ */
+
+ if (!state.active)
+ {
+ state.active = 1;
+ walk(state.rules, active, NiL);
+ }
+ search(state.vars, "MAMAKEARGS", duplicate(use(state.opt) + 1));
+
+ /*
+ * scan the makefile and descend
+ */
+
+ walk(state.rules, scan, NiL);
+ state.view = 0;
+ walk(state.rules, descend, NiL);
+ return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+ register char** e;
+ register char* s;
+ register char* t;
+ register char* v;
+ Buf_t* tmp;
+ int c;
+
+ /*
+ * initialize the state
+ */
+
+ state.id = "mamake";
+ state.active = 1;
+ state.exec = 1;
+ state.file = mamfile;
+ state.opt = buffer();
+ state.rules = dictionary();
+ state.vars = dictionary();
+ search(state.vars, "MAMAKE", *argv);
+
+ /*
+ * parse the options
+ */
+
+#if _PACKAGE_ast
+ error_info.id = state.id;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'e':
+ append(state.opt, " -e");
+ state.explain = 1;
+ continue;
+ case 'i':
+ append(state.opt, " -i");
+ state.ignore = 1;
+ continue;
+ case 'k':
+ append(state.opt, " -k");
+ state.keepgoing = 1;
+ continue;
+ case 'N':
+ state.never = 1;
+ /*FALLTHROUGH*/
+ case 'n':
+ append(state.opt, " -n");
+ state.exec = 0;
+ continue;
+ case 'F':
+ append(state.opt, " -F");
+ state.force = 1;
+ continue;
+ case 'K':
+ continue;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ exit(0);
+ case 'f':
+ append(state.opt, " -f ");
+ append(state.opt, opt_info.arg);
+ state.file = opt_info.arg;
+ continue;
+ case 'r':
+ state.recurse = opt_info.arg;
+ continue;
+ case 'C':
+ state.directory = opt_info.arg;
+ continue;
+ case 'D':
+ append(state.opt, " -D");
+ append(state.opt, opt_info.arg);
+ state.debug = -opt_info.num;
+ continue;
+ case 'G':
+ append(state.opt, " -G");
+ search(state.vars, "-debug-symbols", "1");
+ continue;
+ case 'S':
+ append(state.opt, " -S");
+ search(state.vars, "-strip-symbols", "1");
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ argv += opt_info.index;
+#else
+ while ((s = *++argv) && *s == '-')
+ {
+ if (*(s + 1) == '-')
+ {
+ if (!*(s + 2))
+ {
+ append(state.opt, " --");
+ argv++;
+ break;
+ }
+ for (t = s += 2; *t && *t != '='; t++);
+ if (!strncmp(s, "debug-symbols", t - s) && append(state.opt, " -G") || !strncmp(s, "strip-symbols", t - s) && append(state.opt, " -S"))
+ {
+ if (*t)
+ {
+ v = t + 1;
+ if (t > s && *(t - 1) == '+')
+ t--;
+ c = *t;
+ *t = 0;
+ }
+ else
+ {
+ c = 0;
+ v = "1";
+ }
+ search(state.vars, s - 1, v);
+ if (c)
+ *t = c;
+ continue;
+ }
+ usage();
+ break;
+ }
+ for (;;)
+ {
+ switch (*++s)
+ {
+ case 0:
+ break;
+ case 'e':
+ append(state.opt, " -e");
+ state.explain = 1;
+ continue;
+ case 'i':
+ append(state.opt, " -i");
+ state.ignore = 1;
+ continue;
+ case 'k':
+ append(state.opt, " -k");
+ state.keepgoing = 1;
+ continue;
+ case 'N':
+ state.never = 1;
+ /*FALLTHROUGH*/
+ case 'n':
+ append(state.opt, " -n");
+ state.exec = 0;
+ continue;
+ case 'F':
+ append(state.opt, " -F");
+ state.force = 1;
+ continue;
+ case 'G':
+ append(state.opt, " -G");
+ search(state.vars, "-debug-symbols", "1");
+ continue;
+ case 'K':
+ continue;
+ case 'S':
+ append(state.opt, " -S");
+ search(state.vars, "-strip-symbols", "1");
+ continue;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ exit(0);
+ case 'f':
+ case 'r':
+ case 'C':
+ case 'D':
+ t = s;
+ if (!*++s && !(s = *++argv))
+ {
+ report(2, "option value expected", t, (unsigned long)0);
+ usage();
+ }
+ else
+ switch (*t)
+ {
+ case 'f':
+ append(state.opt, " -f ");
+ append(state.opt, s);
+ state.file = s;
+ break;
+ case 'r':
+ state.recurse = s;
+ break;
+ case 'C':
+ state.directory = s;
+ break;
+ case 'D':
+ append(state.opt, " -D");
+ append(state.opt, s);
+ state.debug = -atoi(s);
+ break;
+ }
+ break;
+ default:
+ report(2, "unknown option", s, (unsigned long)0);
+ case '?':
+ usage();
+ break;
+ }
+ break;
+ }
+ }
+#endif
+
+ /*
+ * load the environment
+ */
+
+ for (e = environ; s = *e; e++)
+ for (t = s; *t; t++)
+ if (*t == '=')
+ {
+ *t = 0;
+ search(state.vars, s, t + 1);
+ *t = '=';
+ break;
+ }
+
+ /*
+ * grab the command line targets and variable definitions
+ */
+
+ while (s = *argv++)
+ {
+ for (t = s; *t; t++)
+ if (*t == '=')
+ {
+ v = t + 1;
+ if (t > s && *(t - 1) == '+')
+ t--;
+ c = *t;
+ *t = 0;
+ search(state.vars, s, v);
+ tmp = buffer();
+ append(tmp, s);
+ append(tmp, ".FORCE");
+ search(state.vars, use(tmp), v);
+ drop(tmp);
+ *t = c;
+ break;
+ }
+ if (!*t)
+ {
+ /*
+ * handle a few targets for nmake compatibility
+ */
+
+ if (*s == 'e' && !strncmp(s, "error 0 $(MAKEVERSION:", 22))
+ exit(1);
+ if (*s == 'r' && !strcmp(s, "recurse") || *s == 'c' && !strncmp(s, "cc-", 3))
+ continue;
+ rule(s)->flags |= RULE_active;
+ state.active = 0;
+ if (state.recurse)
+ continue;
+ }
+ add(state.opt, ' ');
+ add(state.opt, '\'');
+ append(state.opt, s);
+ add(state.opt, '\'');
+ }
+
+ /*
+ * initialize the views
+ */
+
+ if (state.directory && chdir(state.directory))
+ report(3, "cannot change working directory", NiL, (unsigned long)0);
+ view();
+
+ /*
+ * recursion drops out here
+ */
+
+ if (state.recurse)
+ return recurse(state.recurse);
+
+ /*
+ * read the mamfile(s) and bring the targets up to date
+ */
+
+ search(state.vars, "MAMAKEARGS", duplicate(use(state.opt) + 1));
+ push(state.file, (Stdio_t*)0, STREAM_MUST);
+ make(rule(""));
+ pop();
+
+ /*
+ * verify that active targets were made
+ */
+
+ if (!state.active && !state.verified)
+ walk(state.rules, verify, NiL);
+
+ /*
+ * done
+ */
+
+ return state.errors != 0;
+}
diff --git a/src/cmd/INIT/mamake.rt b/src/cmd/INIT/mamake.rt
new file mode 100644
index 0000000..5f7603d
--- /dev/null
+++ b/src/cmd/INIT/mamake.rt
@@ -0,0 +1,40 @@
+NOTE regression tests for the mamake command
+
+UNIT mamake
+
+TEST macros
+
+DATA Mamfile <<'!'
+info mam static 00000 1994-07-17 make (AT&T Research) 5.3 2009-05-05
+setv DEFINED defined
+setv EMPTY
+make all
+
+exec - echo DEFINED ${DEFINED}
+exec - echo DEFINED:VALUE ${DEFINED:VALUE}
+exec - echo DEFINED:-VALUE ${DEFINED:-VALUE}
+exec - echo DEFINED=VALUE ${DEFINED=VALUE}
+exec - echo DEFINED[VALUE] ${DEFINED[VALUE]}
+exec - echo DEFINED.COMPONENT ${DEFINED.COMPONENT}
+exec - echo DEFINED.COMPONENT[VALUE] ${DEFINED.COMPONENT[VALUE]}
+
+exec - echo EMPTY ${EMPTY}
+exec - echo EMPTY:VALUE ${EMPTY:VALUE}
+exec - echo EMPTY:-VALUE ${EMPTY:-VALUE}
+exec - echo EMPTY=VALUE ${EMPTY=VALUE}
+exec - echo EMPTY[VALUE] ${EMPTY[VALUE]}
+exec - echo EMPTY.COMPONENT ${EMPTY.COMPONENT}
+exec - echo EMPTY.COMPONENT[VALUE] ${EMPTY.COMPONENT[VALUE]}
+
+exec - echo __NoT_DeFiNeD__ ${__NoT_DeFiNeD__}
+exec - echo __NoT_DeFiNeD__:VALUE ${__NoT_DeFiNeD__:VALUE}
+exec - echo __NoT_DeFiNeD__:-VALUE ${__NoT_DeFiNeD__:-VALUE}
+exec - echo __NoT_DeFiNeD__=VALUE ${__NoT_DeFiNeD__=VALUE}
+exec - echo __NoT_DeFiNeD__[VALUE] ${__NoT_DeFiNeD__[VALUE]}
+exec - echo __NoT_DeFiNeD__.COMPONENT ${__NoT_DeFiNeD__.COMPONENT}
+exec - echo __NoT_DeFiNeD__.COMPONENT[VALUE] ${__NoT_DeFiNeD__.COMPONENT[VALUE]}
+
+done all generated virtual
+!
+
+EXEC -n
diff --git a/src/cmd/INIT/mamake.tst b/src/cmd/INIT/mamake.tst
new file mode 100644
index 0000000..3c7f94d
--- /dev/null
+++ b/src/cmd/INIT/mamake.tst
@@ -0,0 +1,63 @@
+# : : generated from mamake.rt by mktest : : #
+
+# regression tests for the mamake command
+
+UNIT mamake
+
+TEST 01 macros
+
+ EXEC -n
+ INPUT -n -
+ INPUT Mamfile $'info mam static 00000 1994-07-17 make (AT&T Research) 5.3 2009-05-05
+setv DEFINED defined
+setv EMPTY
+make all
+
+exec - echo DEFINED ${DEFINED}
+exec - echo DEFINED:VALUE ${DEFINED:VALUE}
+exec - echo DEFINED:-VALUE ${DEFINED:-VALUE}
+exec - echo DEFINED=VALUE ${DEFINED=VALUE}
+exec - echo DEFINED[VALUE] ${DEFINED[VALUE]}
+exec - echo DEFINED.COMPONENT ${DEFINED.COMPONENT}
+exec - echo DEFINED.COMPONENT[VALUE] ${DEFINED.COMPONENT[VALUE]}
+
+exec - echo EMPTY ${EMPTY}
+exec - echo EMPTY:VALUE ${EMPTY:VALUE}
+exec - echo EMPTY:-VALUE ${EMPTY:-VALUE}
+exec - echo EMPTY=VALUE ${EMPTY=VALUE}
+exec - echo EMPTY[VALUE] ${EMPTY[VALUE]}
+exec - echo EMPTY.COMPONENT ${EMPTY.COMPONENT}
+exec - echo EMPTY.COMPONENT[VALUE] ${EMPTY.COMPONENT[VALUE]}
+
+exec - echo __NoT_DeFiNeD__ ${__NoT_DeFiNeD__}
+exec - echo __NoT_DeFiNeD__:VALUE ${__NoT_DeFiNeD__:VALUE}
+exec - echo __NoT_DeFiNeD__:-VALUE ${__NoT_DeFiNeD__:-VALUE}
+exec - echo __NoT_DeFiNeD__=VALUE ${__NoT_DeFiNeD__=VALUE}
+exec - echo __NoT_DeFiNeD__[VALUE] ${__NoT_DeFiNeD__[VALUE]}
+exec - echo __NoT_DeFiNeD__.COMPONENT ${__NoT_DeFiNeD__.COMPONENT}
+exec - echo __NoT_DeFiNeD__.COMPONENT[VALUE] ${__NoT_DeFiNeD__.COMPONENT[VAL'\
+$'UE]}
+
+done all generated virtual'
+ OUTPUT - $'echo DEFINED defined
+echo DEFINED:VALUE
+echo DEFINED:-VALUE
+echo DEFINED=VALUE defined
+echo DEFINED[VALUE] ${DEFINED[VALUE]}
+echo DEFINED.COMPONENT
+echo DEFINED.COMPONENT[VALUE] ${DEFINED.COMPONENT[VALUE]}
+echo EMPTY
+echo EMPTY:VALUE ${EMPTY:VALUE}
+echo EMPTY:-VALUE ${EMPTY:-VALUE}
+echo EMPTY=VALUE
+echo EMPTY[VALUE] ${EMPTY[VALUE]}
+echo EMPTY.COMPONENT
+echo EMPTY.COMPONENT[VALUE] ${EMPTY.COMPONENT[VALUE]}
+echo __NoT_DeFiNeD__ ${__NoT_DeFiNeD__}
+echo __NoT_DeFiNeD__:VALUE ${__NoT_DeFiNeD__:VALUE}
+echo __NoT_DeFiNeD__:-VALUE ${__NoT_DeFiNeD__:-VALUE}
+echo __NoT_DeFiNeD__=VALUE ${__NoT_DeFiNeD__=VALUE}
+echo __NoT_DeFiNeD__[VALUE] ${__NoT_DeFiNeD__[VALUE]}
+echo __NoT_DeFiNeD__.COMPONENT
+echo __NoT_DeFiNeD__.COMPONENT[VALUE] ${__NoT_DeFiNeD__.COMPONENT[VALUE]}'
+ ERROR -n -
diff --git a/src/cmd/INIT/mamprobe.sh b/src/cmd/INIT/mamprobe.sh
new file mode 100644
index 0000000..6933bea
--- /dev/null
+++ b/src/cmd/INIT/mamprobe.sh
@@ -0,0 +1,267 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+### this script contains archaic constructs that work with all sh variants ###
+# mamprobe - generate MAM cc probe info
+# Glenn Fowler <gsf@research.att.com>
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+command=mamprobe
+
+# check the options
+
+opt=
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: mamprobe (AT&T Labs Research) 2011-02-11 $
+]
+[+NAME?mamprobe - generate MAM cc probe info]
+[+DESCRIPTION?\bmamprobe\b generates MAM (make abstract machine) \bcc\b(1)
+ probe information for use by \bmamake\b(1). \acc-path\a is the
+ absolute path of the probed compiler and \ainfo-file\a is where
+ the information is placed. \ainfo-file\a is usually
+ \b$INSTALLROOT/lib/probe/C/mam/\b\ahash\a, where \ahash\a is a hash
+ of \acc-path\a. Any \ainfo-file\a directories are created if needed.
+ If \ainfo-file\a is \b-\b then the probe information is written to
+ the standard output.]
+[+?\bmamprobe\b and \bmamake\b are used in the bootstrap phase of
+ \bpackage\b(1) installation before \bnmake\b(1) is built. The
+ probed variable names are the \bnmake\b(1) names with a \bmam_\b
+ prefix, \bCC\b converted to \bcc\b, and \b.\b converted to \b_\b.
+ Additional variables are:]{
+ [+_hosttype_?the \bpackage\b(1) host type]
+ [+mam_cc_L?\b-L\b\adir\a supported]
+ [+STDCAT?command to execute for \bcat\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCHMOD?command to execute for \bchmod\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCMP?command to execute for \bcmp\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCP?command to execute for \bcp\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDED?command to execute for \bed\b(1) or \bex\b(1)]
+ [+STDEDFLAGS?flags for \bSTDED\b]
+ [+STDLN?command to execute for \bln\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDMV?command to execute for \bmv\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDRM?command to execute for \brm\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+}
+[d:debug?Enable probe script debug trace.]
+
+info-file cc-path
+
+[+SEE ALSO?\bexecrate\b(1), \bpackage\b(1), \bmamake\b(1), \bnmake\b(1),
+ \bprobe\b(1)]
+'
+ while getopts -a "$command" "$USAGE" OPT
+ do case $OPT in
+ d) opt=-d ;;
+ esac
+ done
+ shift `expr $OPTIND - 1`
+ ;;
+*) while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ -) break
+ ;;
+ -d) opt=-d
+ ;;
+ -*) echo $command: $1: unknown option >&2
+ ;;
+ *) break
+ ;;
+ esac
+ set ''
+ break
+ done
+ ;;
+esac
+
+# check the args
+
+case $1 in
+-) ;;
+/*) ;;
+*) set '' ;;
+esac
+case $2 in
+/*) ;;
+*) set '' ;;
+esac
+case $# in
+0|1) echo "Usage: $command info-file cc-path" >&2; exit 2 ;;
+esac
+info=$1
+shift
+cc=$*
+
+# find the make probe script
+
+ifs=${IFS-'
+ '}
+IFS=:
+set $PATH
+IFS=$ifs
+script=lib/probe/C/make/probe
+while :
+do case $# in
+ 0) echo "$0: ../$script: probe script not found on PATH" >&2
+ exit 1
+ ;;
+ esac
+ case $1 in
+ '') continue ;;
+ esac
+ makeprobe=`echo $1 | sed 's,[^/]*$,'$script,`
+ if test -x $makeprobe
+ then break
+ fi
+ shift
+done
+
+# create the info dir if necessary
+
+case $info in
+/*) i=X$info
+ ifs=${IFS-'
+ '}
+ IFS=/
+ set $i
+ IFS=$ifs
+ while :
+ do i=$1
+ shift
+ case $i in
+ X) break ;;
+ esac
+ done
+ case $info in
+ //*) path=/ ;;
+ *) path= ;;
+ esac
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ comp=$1
+ shift
+ case $comp in
+ '') continue ;;
+ esac
+ path=$path/$comp
+ if test ! -d $path
+ then mkdir $path || exit
+ fi
+ done
+ ;;
+esac
+
+# generate info in a tmp file and rename when finished
+
+case $info in
+-) ;;
+*) tmp=/tmp/mam$$
+ trap "exec >/dev/null; rm -f $tmp" 0 1 2 3 15
+ exec > $tmp
+ echo "probing C language processor $cc for mam information" >&2
+ ;;
+esac
+
+echo "note generated by $0 for $cc"
+
+(
+ set '' $opt $cc
+ shift
+ . $makeprobe "$@"
+
+ case " $CC_DIALECT " in
+ *" -L "*) echo "CC.L = 1" ;;
+ esac
+
+) | sed \
+ -e '/^CC\./!d' \
+ -e 's/^CC./setv mam_cc_/' \
+ -e 's/^\([^=.]*\)\./\1_/' \
+ -e 's/^\([^=.]*\)\./\1_/' \
+ -e 's/ =//' \
+ -e 's/\$("\([^"]*\)")/\1/g' \
+ -e 's/\$(\([^)]*\))/${\1}/g' \
+ -e 's/\${CC\./${mam_cc_}/g'
+
+echo 'setv _hosttype_ ${mam_cc_HOSTTYPE}'
+
+# STD* are standard commands/flags with possible execrate(1)
+
+if (
+ed <<!
+q
+!
+) < /dev/null > /dev/null 2>&1
+then STDED=ed
+else STDED=ex
+fi
+STDEDFLAGS=-
+set STDCAT cat STDCHMOD chmod STDCMP cmp STDCP cp STDLN ln STDMV mv STDRM rm
+while :
+do case $# in
+ 0|1) break ;;
+ esac
+ p=$2
+ for d in /bin /usr/bin /usr/sbin
+ do if test -x $d/$p
+ then p=$d/$p
+ break
+ fi
+ done
+ eval $1=\$p
+ shift
+ shift
+done
+if execrate
+then for n in STDCAT STDCHMOD STDCMP STDCP STDLN STDMV STDRM
+ do eval $n=\"execrate \$$n\"
+ done
+fi
+for n in STDCAT STDCHMOD STDCMP STDCP STDED STDEDFLAGS STDLN STDMV STDRM
+do eval echo setv \$n \$$n
+done
+
+# all done
+
+case $info in
+-) ;;
+*) exec >/dev/null
+ test -f $info && rm -f $info
+ cp $tmp $info
+ chmod -w $info
+ ;;
+esac
diff --git a/src/cmd/INIT/mkdir.sh b/src/cmd/INIT/mkdir.sh
new file mode 100644
index 0000000..c929e95
--- /dev/null
+++ b/src/cmd/INIT/mkdir.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: mkdir for systems that do not support -p : 2002-09-01 :
+MKDIR=/bin/mkdir
+CHMOD=chmod
+mode=
+parents=
+while :
+do case $1 in
+ -m) case $# in
+ 1) echo "mkdir: -m: mode argument expected" >&2
+ exit 1
+ ;;
+ esac
+ shift
+ mode=$1
+ ;;
+ -m*) mode=`echo X$1 | sed 's/X-m//'`
+ ;;
+ -p) parents=1
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+done
+if test "" != "$parents"
+then for d
+ do if test ! -d $d
+ then ifs=${IFS-'
+ '}
+ IFS=/
+ set '' $d
+ IFS=$ifs
+ shift
+ dir=$1
+ shift
+ if test -n "$dir" -a ! -d "$dir"
+ then $MKDIR "$dir" || exit 1
+ if test "" != "$mode"
+ then $CHMOD "$mode" "$dir" || exit 1
+ fi
+ fi
+ for d
+ do dir=$dir/$d
+ if test ! -d "$dir"
+ then $MKDIR "$dir" || exit 1
+ if test "" != "$mode"
+ then $CHMOD "$mode" "$dir" || exit 1
+ fi
+ fi
+ done
+ fi
+ done
+else $MKDIR "$@" || exit 1
+ if test "" != "$mode"
+ then for d
+ do $CHMOD "$mode" "$d" || exit 1
+ done
+ fi
+fi
+exit 0
diff --git a/src/cmd/INIT/mktest.sh b/src/cmd/INIT/mktest.sh
new file mode 100755
index 0000000..f24183e
--- /dev/null
+++ b/src/cmd/INIT/mktest.sh
@@ -0,0 +1,641 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: mktest - generate regress or shell regression test scripts
+
+command=mktest
+stdin=8
+stdout=9
+PREFIX=test
+STYLE=regress
+WIDTH=80
+
+eval "exec $stdout>&1"
+
+case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: mktest (AT&T Labs Research) 2010-08-11 $
+]
+'$USAGE_LICENSE$'
+[+NAME?mktest - generate a regression test scripts]
+[+DESCRIPTION?\bmktest\b generates regression test scripts from test
+ template commands in the \aunit\a.\brt\b file. The generated test
+ script writes temporary output to '$PREFIX$'\aunit\a.tmp and compares
+ it to the expected output in '$PREFIX$'\aunit\a.out. Run the test
+ script with the \b--accept\b option to (re)generate the
+ '$PREFIX$'\aunit\a.out.]
+[s:style?The script style:]:[style:='$STYLE$']
+ {
+ [+regress?\bregress\b(1) command input.]
+ [+shell?Standalone test shell script.]
+ }
+[w:width?Set the output format width to approximately
+ \awidth\a.]:[width:='$WIDTH$']
+
+unit.rt [ unit [ arg ... ] ]
+
+[+INPUT FILES?The regression test command file \aunit\a\b.rt\b is a
+ \bksh\b(1) script that makes calls to the following functions:]
+ {
+ [+DATA \afile\a [ - | [ options ]] data]]?Create input data
+ \afile\a that is empty (-) or contains \adata\a subject to
+ \bprint\b(1) \aoptions\a or that is a copy of the DATA command
+ standard input. Set \afile\a to \b-\b to name the standard
+ input.]
+ [+DIAGNOSTICS?Diagnostic messages of unspecified format are
+ expected.]
+ [+DO \acommand\a [ \aarg\a ... ]]?Execute \acommand\a if the
+ current test is active.]
+ [+EXEC [ \aarg\a ... ]]?Run the command under test with
+ optional arguments. If the standard input is not specified then
+ the standard input of the previous EXEC is used. The standard
+ input of the first EXEC in a TEST group is an empty regular
+ file.]
+ [+EXPORT \aname\a=\avalue\a ...?Export list for subsequent
+ commands in the TEST group or for all TEST groups if before
+ the first TEST group.]
+ [+IGNORESPACE [ 0 | 1 ]
+ ?Ignore space differences when comparing expected output.]
+ [+KEEP \apattern\a ...?File match patterns of files to retain
+ between TEST groups.]
+ [+NOTE \acomment\a?\acomment\a is added to the current test
+ script.]
+ [+PROG \acommand\a [ \aarg\a ... ]]?Run \acommand\a with
+ optional arguments.]
+ [+TEST [ \anumber\a ]] [ \adescription\a ... ]]?Define a new
+ test group with optional \anumber\a and \adescripion\a.]
+ [+TWD [ \adir\a ... ]]?Set the temporary test dir to \adir\a.
+ The default is \aunit\a\b.tmp\b, where \aunit\a is the test
+ input file sans directory and suffix. If \adir\a matches \b/*\b
+ then it is the directory name; if \adir\a is non-null then the
+ prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is
+ omitted then
+ \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a is
+ used.]
+ [+UMASK [ \amask\a ]]?Run subsequent tests with \bumask\b(1)
+ \amask\a. If \amask\a is omitted then the original \bumask\b is
+ used.]
+ [+UNIT \acommand\a [ \aarg\a ... ]]?Define the command and
+ optional default arguments to be tested. \bUNIT\b explicitly
+ overrides the default command name derived from the test script
+ file name.]
+ [+WIDTH \awidth\a?Set the output format width to approximately
+ \awidth\a.]
+ }
+[+SEE ALSO?\bregress\b(1), \bksh\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE='s: unit.rt [ arg ... ]'
+ ;;
+esac
+
+typeset ARG SCRIPT UNIT TEMP=${TMPDIR:-/tmp}/$command.$$.tmp WORK
+typeset IO INPUT INPUT_N OUTPUT OUTPUT_N ERROR ERROR_N KEEP
+typeset -C STATE
+typeset -A DATA STATE.RESET REMOVE FORMAT
+integer KEEP_UNIT=0 SCRIPT_UNIT=0 TEST=0 CODE=0 EXIT=0 ACCEPT=0 DIAGNOSTICS=0 code
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ s) case $OPTARG in
+ regress|shell)
+ STYLE=$OPTARG
+ ;;
+ *) print -u2 -r -- $command: --style=$OPTARG: regress or shell expected
+ exit 1
+ ;;
+ esac
+ ;;
+ w) WIDTH=$OPTARG
+ ;;
+ *) OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+ ;;
+ esac
+done
+shift $OPTIND-1
+
+typeset SINGLE= quote='%${SINGLE}..${WIDTH}q'
+
+if [[ $1 == - ]]
+then shift
+fi
+if (( ! $# ))
+then
+ print -u2 -r -- $command: test command script path expected
+ exit 1
+fi
+SCRIPT=$1
+shift
+if [[ ! -r $SCRIPT ]]
+then print -u2 -r -- $command: $SCRIPT: cannot read
+ exit 1
+fi
+(ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0
+if (( $# ))
+then set -A UNIT -- "$@"
+ KEEP_UNIT=1
+else ARG=${SCRIPT##*/}
+ set -A UNIT -- "${ARG%.*}"
+fi
+WORK=${UNIT[0]}.tmp
+rm -rf $WORK
+mkdir $WORK || exit
+export PATH=$PWD:$PATH
+
+function LINE
+{
+ if [[ $STYLE == regress ]]
+ then print -u$stdout
+ fi
+}
+
+function NOTE
+{
+ case $STYLE in
+ regress)LINE
+ print -u$stdout -r -- '#' "$@"
+ ;;
+ shell) print -u$stdout -r -f ": $QUOTE"$'\n' -- "$*"
+ ;;
+ esac
+}
+
+function UNIT
+{
+ (( KEEP_UNIT )) || set -A UNIT -- "$@"
+ case $STYLE in
+ regress)LINE
+ print -u$stdout -r -f $'UNIT'
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ print -u$stdout
+ ;;
+ shell) print -u$stdout -r -f $'set x'
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ print -u$stdout
+ print -u$stdout shift
+ ;;
+ esac
+}
+
+function TEST
+{
+ typeset i
+ typeset -A REM
+ if (( ${#STATE.RESET[@]} ))
+ then unset ${!STATE.RESET[@]}
+ case $STYLE in
+ shell) print -u$stdout -r -- unset ${!STATE.RESET[@]} ;;
+ esac
+ unset STATE.RESET
+ typeset -A STATE.RESET
+ fi
+ if (( ${#REMOVE[@]} ))
+ then rm -f -- "${!REMOVE[@]}"
+ case $STYLE in
+ shell) print -u$stdout -r -f $'rm -f'
+ for i in ${!REMOVE[@]}
+ do print -u$stdout -r -f " $QUOTE" "$i"
+ done
+ print -u$stdout
+ ;;
+ esac
+ for i in ${!REMOVE[@]}
+ do unset REMOVE[$i]
+ done
+ fi
+ rm -rf $WORK/*
+ if [[ $1 == +([0-9]) ]]
+ then TEST=${1##0}
+ shift
+ else ((TEST++))
+ fi
+ LINE
+ case $STYLE in
+ regress)print -u$stdout -r -f "TEST %02d $QUOTE"$'\n' -- $TEST "$*"
+ ;;
+ shell) print -u$stdout -r -f ": TEST %02d $QUOTE"$'\n' -- $TEST "$*"
+ ;;
+ esac
+ : > $TEMP.INPUT > $TEMP.in
+ INPUT=
+ INPUT_N=
+ OUTPUT=
+ OUTPUT_N=
+ ERROR=
+ ERROR_N=
+ UMASK=$UMASK_ORIG
+ UMASK_DONE=$UMASK
+ CODE=0
+}
+
+function TWD
+{
+ case $STYLE in
+ regress)LINE
+ print -u$stdout -r -f $'TWD'
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ print -u$stdout
+ ;;
+ esac
+}
+
+function RUN
+{
+ typeset i n p op unit sep output=1 error=1 exitcode=1
+ op=$1
+ shift
+ while :
+ do case $1 in
+ ++NOOUTPUT) output= ;;
+ ++NOERROR) error= ;;
+ ++NOEXIT) exitcode= ;;
+ ++*) print -u2 -r -- $command: $0: $1: unknown option; exit 1 ;;
+ *) break ;;
+ esac
+ shift
+ done
+ if [[ $op == PROG ]]
+ then unit=$1
+ shift
+ elif (( ! ${#UNIT[@]} ))
+ then print -u2 -r -- $command: $SCRIPT: UNIT statement or operand expected
+ exit 1
+ fi
+ LINE
+ case $STYLE in
+ regress)if [[ $op == PROG ]]
+ then print -u$stdout -r -f $'\t'"$op"$'\t'"$unit"
+ sep=$' '
+ else print -u$stdout -r -f $'\t'"$op"
+ sep=$'\t'
+ fi
+ for ARG in "$@"
+ do LC_CTYPE=C print -u$stdout -r -f "$sep$QUOTE" -- "$ARG"
+ sep=$' '
+ done
+ print -u$stdout
+ [[ ${DATA[-]} || /dev/fd/0 -ef /dev/fd/$stdin ]] || cat > $TEMP.in
+ IO=$(cat $TEMP.in; print :)
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ {
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK
+ cd $WORK
+ if [[ $op == PROG ]]
+ then "$unit" "$@"
+ code=$?
+ else "${UNIT[@]}" "$@"
+ code=$?
+ fi
+ cd ..
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+ } < $TEMP.in > $TEMP.out 2> $TEMP.err
+ if [[ $IO != "$INPUT" || $n != "$INPUT_N" ]]
+ then INPUT=$IO
+ INPUT_N=$n
+ if [[ ${FORMAT[-]} ]]
+ then print -u$stdout -n -r -- $'\t\tINPUT'
+ print -u$stdout -r -f " $QUOTE" -- "${FORMAT[-]}"
+ print -u$stdout -r -f " $QUOTE" -- -
+ unset FORMAT[-]
+ else print -u$stdout -n -r -- $'\t\tINPUT' $n -
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ fi
+ print -u$stdout
+ unset DATA[-]
+ fi
+ for i in ${!DATA[@]}
+ do if [[ ${FORMAT[$i]} ]]
+ then print -u$stdout -n -r -- $'\t\tINPUT'
+ print -u$stdout -r -f " $QUOTE" -- "${FORMAT[$i]}"
+ print -u$stdout -r -f " $QUOTE" -- "$i"
+ unset FORMAT[$i]
+ else case $i in
+ -) p=$TEMP.in ;;
+ *) p=$WORK/$i ;;
+ esac
+ IO=$(cat $p; print :)
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ print -u$stdout -n -r -- $'\t\tINPUT' $n
+ print -u$stdout -r -f " $QUOTE" -- "$i"
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ fi
+ print -u$stdout
+ unset DATA[$i]
+ done
+ IO=$(cat $TEMP.out; print :)
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ if [[ $IO != "$OUTPUT" || $n != "$OUTPUT_N" ]]
+ then OUTPUT=$IO
+ OUTPUT_N=$n
+ if [[ $output ]]
+ then if [[ ! -s $TEMP.out ]]
+ then print -u$stdout -n -r -- $'\t\tOUTPUT' -
+ elif cmp -s $TEMP.in $TEMP.out
+ then OUTPUT=not-$OUTPUT
+ print -u$stdout -n -r -- $'\t\tSAME OUTPUT INPUT'
+ else print -u$stdout -n -r -- $'\t\tOUTPUT' $n -
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ fi
+ print -u$stdout
+ fi
+ fi
+ IO=$(cat $TEMP.err; print :)
+ IO=${IO//$command\[*([0-9])\]:\ .\[*([0-9])\]:\ @(EXEC|PROG)\[*([0-9])\]:\ /}
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ if [[ $IO != "$ERROR" || $n != "$ERROR_N" ]]
+ then ERROR=$IO
+ ERROR_N=$n
+ if [[ $error ]]
+ then print -u$stdout -n -r -- $'\t\tERROR' $n -
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ print -u$stdout
+ fi
+ fi
+ case $output:$error in
+ :) OUTPUT=
+ OUTPUT_N=
+ ERROR=
+ ERROR_N=
+ print -u$stdout -r -- $'\t\tIGNORE OUTPUT ERROR'
+ ;;
+ :1) OUTPUT=
+ OUTPUT_N=
+ print -u$stdout -r -- $'\t\tIGNORE OUTPUT'
+ ;;
+ 1:) ERROR=
+ ERROR_N=
+ print -u$stdout -r -- $'\t\tIGNORE ERROR'
+ ;;
+ esac
+ if [[ $UMASK_DONE != $UMASK ]]
+ then UMASK_DONE=$UMASK
+ print -u$stdout -r -f $'\t\tUMASK %s\n' $UMASK
+ fi
+ if (( code != CODE ))
+ then (( CODE=code ))
+ if [[ $exitcode ]]
+ then print -u$stdout -r -f $'\t\tEXIT %d\n' $CODE
+ fi
+ fi
+ ;;
+ shell) [[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "{ umask $UMASK; "
+ if [[ $op == PROG ]]
+ then print -u$stdout -r -f $'"'"$unit"$'"'
+ else print -u$stdout -r -f $'"$@"'
+ fi
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ [[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "umask $UMASK_ORIG; } "
+ if [[ ! $output ]]
+ then print -u$stdout -r -f " >/dev/null"
+ fi
+ if [[ ! $error ]]
+ then if [[ ! $output ]]
+ then print -u$stdout -r -f " 2>&1"
+ else print -u$stdout -r -f " 2>/dev/null"
+ fi
+ fi
+ IO=$(cat)
+ if [[ $IO ]]
+ then print -u$stdout -r -- "<<'!TEST-INPUT!'"
+ print -u$stdout -r -- "$IO"
+ print -u$stdout -r -- !TEST-INPUT!
+ else print -u$stdout
+ fi
+ if [[ $exitcode ]]
+ then print -u$stdout -r -- $'CODE=$?\ncase $CODE in\n0) ;;\n*) echo exit status $CODE ;;\nesac'
+ fi
+ ;;
+ esac
+}
+
+function DO
+{
+ LINE
+ print -r $'\t'DO "$@"
+}
+
+function EXEC
+{
+ RUN EXEC "$@"
+}
+
+function DATA
+{
+ typeset f p o
+ f=$1
+ shift
+ case $f in
+ -) p=$TEMP.in ;;
+ *) p=$WORK/$f ;;
+ esac
+ case $1 in
+ '') cat ;;
+ -) ;;
+ *) print -r "$@" ;;
+ esac > $p
+ DATA[$f]=1
+ if (( $# == 1 )) && [[ $1 == -?* ]]
+ then FORMAT[$f]=$1
+ else FORMAT[$f]=
+ fi
+ if [[ $f != $KEEP ]]
+ then REMOVE[$f]=1
+ fi
+ if [[ $STYLE == shell ]]
+ then {
+ print -r -f "cat > $QUOTE <<'!TEST-INPUT!'"$'\n' -- "$f"
+ cat "$p"
+ print -r -- !TEST-INPUT!
+ } >&$stdout
+ fi
+}
+
+function KEEP
+{
+ typeset p
+ for p
+ do if [[ $KEEP ]]
+ then KEEP=$KEEP'|'
+ fi
+ KEEP=$KEEP$p
+ done
+}
+
+function DIAGNOSTICS
+{
+ LINE
+ case $STYLE in
+ regress) print -u$stdout -r $'DIAGNOSTICS' ;;
+ shell) DIAGNOSTICS=1 ;;
+ esac
+}
+
+function EXPORT
+{
+ typeset x n v
+ LINE
+ case $STYLE in
+ regress) print -u$stdout -r -f $'EXPORT' ;;
+ shell) print -u$stdout -r -f $'export' ;;
+ esac
+ for x
+ do n=${x%%=*}
+ v=${x#*=}
+ export "$x"
+ print -u$stdout -r -f " %s=$QUOTE" "$n" "$v"
+ (( TEST )) && STATE.RESET["$n"]=1
+ done
+ print -u$stdout
+}
+
+function PROG
+{
+ RUN PROG "$@"
+}
+
+function WIDTH
+{
+ WIDTH=${1:-80}
+ eval QUOTE='"'$quote'"'
+}
+
+function IGNORESPACE
+{
+ IGNORESPACE=-b
+ LINE
+ print -u$stdout -r IGNORESPACE
+}
+
+function UMASK # [ mask ]
+{
+ [[ $UMASK_ORIG ]] || UMASK_ORIG=$(umask)
+ UMASK=$1
+ [[ $UMASK ]] || UMASK=$UMASK_ORIG
+}
+
+trap 'CODE=$?; rm -rf $TEMP.* $WORK; exit $CODE' 0 1 2 3 15
+
+typeset IGNORESPACE UMASK UMASK_ORIG UMASK_DONE
+UMASK_ORIG=$(umask)
+IFS=$IFS$'\n'
+
+print -u$stdout -r "# : : generated from $SCRIPT by $command : : #"
+case $STYLE in
+shell) cat <<!
+ACCEPT=0
+while :
+do case \$1 in
+ -a|--accept)
+ ACCEPT=1
+ ;;
+ --help|--man)
+ cat 1>&2 <<!!
+Usage: \\\$SHELL $PREFIX${UNIT[0]}.sh [ --accept ] [ unit ... ]
+
+${UNIT[0]} regression test script. Run this script to generate new
+results in $PREFIX${UNIT[0]}.tmp and compare with expected results in
+$PREFIX${UNIT[0]}.out. The --accept option generates $PREFIX${UNIT[0]}.tmp
+and moves it to $PREFIX${UNIT[0]}.out.
+!!
+ exit 2
+ ;;
+ -*) echo \$0: \$1: invalid option >&2
+ exit 1
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+done
+export COLUMNS=80
+{
+!
+ ;;
+esac
+
+export COLUMNS=80
+
+case $STYLE in
+shell) SINGLE='#'
+ eval QUOTE='"'$quote'"'
+ . $SCRIPT < /dev/null | sed -e $'s,\\\\n,\n,g' -e $'s,\\\\t,\t,g' -e $'s,\\$\',\',g'
+ ;;
+*) eval QUOTE='"'$quote'"'
+ : > $TEMP.INPUT > $TEMP.in
+ eval "exec $stdin<$TEMP.INPUT"
+ . $SCRIPT <&$stdin
+ ;;
+esac
+
+case $STYLE in
+shell) cat <<!
+} > $PREFIX${UNIT[0]}.tmp 2>&1 < /dev/null
+case \$ACCEPT in
+0) if grep ' $' $PREFIX${UNIT[0]}.tmp >/dev/null
+ then mv $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.junk
+ sed 's/ $//' < $PREFIX${UNIT[0]}.junk > $PREFIX${UNIT[0]}.tmp
+ rm -f $PREFIX${UNIT[0]}.junk
+ fi
+ if cmp -s $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
+ then echo ${UNIT[0]} tests PASSED
+ rm -f $PREFIX${UNIT[0]}.tmp
+ else echo ${UNIT[0]} tests FAILED
+ diff $IGNORESPACE $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
+ fi
+ ;;
+
+*) mv $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
+ ;;
+esac
+!
+ ;;
+esac
diff --git a/src/cmd/INIT/mprobe.sh b/src/cmd/INIT/mprobe.sh
new file mode 100644
index 0000000..975ebb1
--- /dev/null
+++ b/src/cmd/INIT/mprobe.sh
@@ -0,0 +1,30 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: mam probe script
+opt=
+while :
+do case $1 in
+ -d) opt=-d ;;
+ -*) ;;
+ *) break ;;
+ esac
+ shift
+done
+mamprobe $opt - "$1"
diff --git a/src/cmd/INIT/nsl.c b/src/cmd/INIT/nsl.c
new file mode 100644
index 0000000..e961e01
--- /dev/null
+++ b/src/cmd/INIT/nsl.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lnsl
+ */
+
+
+extern void* gethostbyname();
+
+int
+main()
+{
+ return gethostbyname(0) == 0;
+}
diff --git a/src/cmd/INIT/p.c b/src/cmd/INIT/p.c
new file mode 100644
index 0000000..387c4bb
--- /dev/null
+++ b/src/cmd/INIT/p.c
@@ -0,0 +1,24 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for prototyping cc
+ */
+
+int main(int argc, char** argv) { return argc || argv; }
diff --git a/src/cmd/INIT/package.mk b/src/cmd/INIT/package.mk
new file mode 100644
index 0000000..921fa2d
--- /dev/null
+++ b/src/cmd/INIT/package.mk
@@ -0,0 +1,1537 @@
+/*
+ * source and binary package support
+ *
+ * @(#)package.mk (AT&T Research) 2012-02-14
+ *
+ * usage:
+ *
+ * cd $INSTALLROOT/lib/package
+ * nmake -f name [closure] [cyg|exp|lcl|pkg|rpm|tgz] [base|delta] type
+ *
+ * where:
+ *
+ * name package description file or component
+ *
+ * type source build source archive, generates
+ * $(PACKAGEDIR)/name.version.release.suffix
+ * binary build binary archive, generates
+ * $(PACKAGEDIR)/name.version.hosttype.release.suffix
+ * runtime build binary archive, generates
+ * $(PACKAGEDIR)/name-run.version.hosttype.release.suffix
+ *
+ * NOTE: $(PACKAGEDIR) is in the lowest view and is shared among all views
+ *
+ * generated archive member files are $(PACKAGEROOT) relative
+ *
+ * main assertions:
+ *
+ * NAME [ name=value ] :PACKAGE: component ...
+ * :OMIT: component ...
+ * :LICENSE: license-class-pattern
+ * :CATEGORY: category-id ...
+ * :COVERS: package ...
+ * :REQURES: package ...
+ * :INDEX: index description line
+ * :DESCRIPTION:
+ * [ verbose description ]
+ * :DETAILS: style
+ * :README:
+ * readme lines
+ * :EXPORT:
+ * name=value
+ * target :INSTALL: [ source ]
+ *
+ * option variables, shown with default values
+ *
+ * format=tgz
+ * archive format
+ *
+ * version=YYYY-MM-DD
+ * package base version (overrides current date)
+ *
+ * release=YYYY-MM-DD
+ * package delta release (overrides current date)
+ *
+ * license=type.class
+ * :LICENSE: type.class pattern override
+ *
+ * notice=1
+ * include the conspicuous empty notice file
+ *
+ * copyright=0
+ * do not prepend source file copyright notice
+ *
+ * strip=0
+ * don't strip non-lcl binary package members
+ *
+ * variants=pattern
+ * include variants matching pattern in binary packages
+ *
+ * incremental=[source:1 binary:0]
+ * if a base archive is generated then also generate an
+ * incremental delta archive from the previous base
+ *
+ * NOTE: the Makerules.mk :PACKAGE: operator defers to :package: when
+ * a target is specified
+ */
+
+/* these are ast centric -- we'll parameterize another day */
+
+org = ast
+url = http://www.research.att.com/sw/download
+
+/* generic defaults */
+
+base =
+category = utils
+checksum = md5
+closure =
+copyright = 1
+delta =
+format = tgz
+incremental =
+index =
+init = INIT
+license =
+licenses = $(org)
+mamfile = 1
+opt =
+name =
+notice =
+release =
+strip = 0
+style = tgz
+suffix = tgz
+type =
+variants = !(cc-g)
+vendor =
+version = $("":T=R%Y-%m-%d)
+
+SUM = sum
+
+package.notice = ------------ NOTICE -- LICENSED SOFTWARE -- SEE README FOR DETAILS ------------
+
+package.readme = $(@.package.readme.)
+
+.package.readme. :
+ This is a package root directory $PACKAGEROOT. Source and binary
+ packages in this directory tree are controlled by the command
+ $()
+ bin/package
+ $()
+ Binary files may be in this directory or in the install root directory
+ $()
+ INSTALLROOT=$PACKAGEROOT/arch/`bin/package`
+ $()
+ For more information run
+ $()
+ bin/package help
+ $()
+ Many of the packaged commands self-document via the --man and --html
+ options; those that do have no separate man page.
+ $()
+ Each package is covered by one of the license files
+ $()
+ $(PACKAGELIB)/LICENSES/<license>
+ $()
+ where <license> is the license type for the package. At the top
+ of each license file is a URL; the license covers all software that
+ refers to this URL. For details run
+ $()
+ bin/package license [<package>]
+ $()
+ Any archives, distributions or packages made from source or
+ binaries covered by license(s) must contain the corresponding
+ license file(s)$(notice:?, this README file, and the empty file$$("\n")$$(package.notice)?.?)
+
+.package.licenses. : .FUNCTION
+ local I F L R T all save text
+ L := $(%)
+ while L == "--*"
+ I := $(L:O=1)
+ if I == "--all"
+ all = 1
+ elif I == "--save"
+ save = 1
+ elif I == "--text"
+ text = 1
+ end
+ L := $(L:O>1)
+ end
+ if "$(L)" == "*-*"
+ L += $(L:/[^-]*-//) $(L:/-.*//)
+ end
+ L += $(licenses)
+ for I $(L:U)
+ if I == "gpl"
+ I = gnu
+ all =
+ end
+ if F = "$(I:D=$(PACKAGESRC):B:S=.lic:T=F)"
+ R += $(F)
+ if save || text
+ T := $(.FIND. lib/package .lic $(F):P=W,query=type)
+ R += $(T:D=$(PACKAGESRC)/LICENSES:B)
+ end
+ if save
+ R += $(F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F)
+ elif ! all
+ break
+ end
+ end
+ end
+ return $(R)
+
+/*
+ * glob(3) doesn't handle / in alternation -- should it?
+ */
+
+.package.glob. : .FUNCTION
+ local A D I P S
+ for I $(%)
+ if I == "*/*"
+ D := $(I:C,/.*,,)
+ if ! "$(A:N=$(D))"
+ local S.$(D)
+ A += $(D)
+ end
+ S.$(D) += $(I:C,[^/]*/,,)
+ else
+ P := $(P)$(S)$(I)
+ end
+ S = |
+ end
+ if P == "*\|*"
+ P := ($(P))
+ end
+ for I $(A)
+ P += $(I)/$(.package.glob. $(S.$(I)))
+ end
+ return $(P)
+
+
+.MAKEINIT : .package.init
+
+.package.init : .MAKE .VIRTUAL .FORCE
+ local V
+ V := $(VROOT:T=F:P=L*)
+ if ! PACKAGEROOT
+ PACKAGEROOT := $(V:N!=*/arch/+([!/]):O=1)
+ end
+ if V == "$(PACKAGEROOT)"
+ V :=
+ end
+ V += $(INSTALLROOT) $(PACKAGEROOT)
+ PACKAGEVIEW := $(V:H=RU)
+ INSTALLOFFSET := $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
+ if license
+ license := $(license)|none.none
+ end
+
+PACKAGELIB = lib/package
+PACKAGESRC = $(PACKAGEROOT)/$(PACKAGELIB)
+PACKAGEBIN = $(INSTALLROOT)/$(PACKAGELIB)
+PACKAGEDIR = $(PACKAGESRC)/$(style)
+INSTALLOFFSET = $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
+
+package.omit = -|*/$(init)
+package.glob.all = $(INSTALLROOT)/src/*/*/($(MAKEFILES:/:/|/G))
+package.all = $(package.glob.all:P=G:W=O=$(?$(name):A=.VIRTUAL):N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
+package.glob.pkg = $(.package.glob. $(~$(name):P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%) $(~$(name):P=U:N=$(name):?$$(INSTALLROOT)/src/$$(name)/($$(MAKEFILES:/:/|/G))??)
+package.pkg = $(package.glob.pkg:P=G:D:N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
+package.closure = $(closure:?$$(package.all)?$$(package.pkg)?)
+
+package.init = $(.package.glob. $("$(init)$(name)":P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%:P=G:T=F:D::B)
+package.ini = ignore mamprobe manmake package silent
+package.src.pat = $(PACKAGESRC)/($(name).(ini|pkg))
+package.src = $(package.src.pat:P=G) $(.package.licenses. --save $(name))
+package.bin = $(PACKAGEBIN)/$(name).ini
+
+package.mam = --never --force --mam=static --corrupt=accept --clobber --compare --link='lib*.a*' CC=$(CC.DIALECT:N=C++:?CC?cc?) package.license.class=$(license:Q) $(=) 'dontcare test' install test
+
+op = current
+stamp = [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
+source = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(suffix)
+binary = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
+runtime = $(PACKAGEDIR)/$(name)-run.$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
+old.new.source = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(suffix)
+old.new.binary = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
+old.new.runtime = $(PACKAGEDIR)/$(name)-run.$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
+
+source.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(suffix)":P=G:H=R)
+binary.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H=R)
+runtime.list = $("$(PACKAGEDIR)/$(name)-run.*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H>)
+
+source.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz.c":T=F)
+binary.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz":T=F)
+
+$(init) : .VIRTUAL $(init)
+
+package.requires = 0
+
+":package:" : .MAKE .OPERATOR
+ local P I R V
+ P := $(<:O=1)
+ $(P) : $(>:V)
+ if ! package.requires
+ if ! name
+ name := $(P)
+ .PACKAGE. := $(P)
+ if name == "$(init)"
+ package.omit = -
+ package.src += $(package.ini:C,^,$(PACKAGEROOT)/bin/,) $(PACKAGESRC)/package.mk
+ else
+ $(P) : $(package.init)
+ end
+ for I $(<:O>1)
+ if I == "*=*"
+ eval
+ $(I)
+ end
+ else
+ version := $(I)
+ end
+ end
+ LICENSEFILEDEFAULT := $(.package.licenses. $(name):@/ /:/G)
+ export LICENSEFILEDEFAULT
+ end
+ if "$(>)"
+ for I $(>:V)
+ $(I) : .VIRTUAL
+ if I == "/*"
+ package.dir += $(I:V)
+ end
+ end
+ end
+ if "$(@)"
+ $(P).README := $(@)
+ else
+ $(P).README := This is the $(P) package.
+ end
+ end
+
+":AUXILIARY:" : .MAKE .OPERATOR
+ package.auxiliary.$(style) += $(>:N=/*:T=F) $(>:N!=/*:C%^%$(INSTALLROOT)/%:T=F)
+
+":CATEGORY:" : .MAKE .OPERATOR
+ if ! package.requires
+ category := $(>)
+ end
+
+.covers. : .FUNCTION
+ local I C D F K=0 L
+ for I $(%)
+ if ! "$(~covers:N=$(I:B))"
+ if F = "$(I:D:B:S=.pkg:T=F)"
+ if D = "$(F:T=I)"
+ covers : $(I:B)
+ for L $(D)
+ if L == ":COVERS:"
+ K = 1
+ elif L == ":*:"
+ if K
+ break
+ end
+ elif K
+ : $(.covers. $(L))
+ end
+ end
+ end
+ else
+ error $(--exec:?3?1?) $(I): unknown package $(I)
+ end
+ end
+ end
+
+":COVERS:" : .MAKE .OPERATOR
+ if ! package.requires
+ : $(.covers. $(>))
+ end
+
+":DESCRIPTION:" : .MAKE .OPERATOR
+ if ! package.requires
+ $(name).README := $(@:V)
+ end
+
+":DETAILS:" : .MAKE .OPERATOR
+ if ! package.requires
+ details.$(>:O=1) := $(@:V)
+ end
+
+":EXPORT:" : .MAKE .OPERATOR
+ if ! package.requires
+ export.$(style) := $(@:/$$("\n")/ /G)
+ end
+
+":INDEX:" : .MAKE .OPERATOR
+ if ! package.requires
+ index := $(>)
+ end
+
+":INSTALL:" : .MAKE .OPERATOR
+ if ! package.requires
+ local T S F X
+ S := $(>)
+ T := $(<)
+ if "$(exe.$(style))" && "$(T)" == "bin/*([!./])"
+ T := $(T).exe
+ end
+ if ! "$(S)"
+ S := $(T)
+ elif "$(exe.$(style))" && "$(S)" == "bin/*([!./])"
+ S := $(S).exe
+ end
+ install.$(style) := $(install.$(style):V)$("\n")install : $$(ROOT)/$(T)$("\n")$$(ROOT)/$(T) : $$(ARCH)/$(S)$("\n\t")cp $< $@
+ if strip && "$(T:N=*.exe)"
+ install.$(style) := $(install.$(style):V)$("\n\t")strip $@ 2>/dev/null
+ end
+ X := $(PACKAGEROOT)/arch/$(CC.HOSTTYPE)/$(S)
+ if strip && "$(X:T=Y)" == "*/?(x-)(dll|exe)"
+ F := filter $(STRIP) $(STRIPFLAGS) $(X)
+ end
+ if "$(filter.$(style):V)"
+ filter.$(style) := $(filter.$(style):V)$$("\n")
+ end
+ filter.$(style) := $(filter.$(style):V);;$(F);$(X);usr/$(T)
+ end
+
+":LICENSE:" : .MAKE .OPERATOR
+ if ! package.requires && ! license
+ license := $(>)
+ end
+
+":OMIT:" : .MAKE .OPERATOR
+ if ! package.requires
+ package.omit := $(package.omit)|$(>:C,^,*/,:/ /|/G)
+ end
+
+":POSTINSTALL:" : .MAKE .OPERATOR
+ if ! package.requires
+ postinstall.$(style) := $(@:V)
+ end
+
+":README:" : .MAKE .OPERATOR
+ if ! package.requires
+ readme.$(style) := $(@:V)
+ end
+
+.requires. : .FUNCTION
+ local I C D F K=0 L V T M=0
+ for I $(%)
+ if ! "$(~requires:N=$(I:B))"
+ if F = "$(I:D:B:S=.pkg:T=F)"
+ if I == "$(init)"
+ package.omit = -
+ else
+ requires : $(I:B)
+ end
+ if V = "$(I:D:B=gen/$(I:B):S=.ver:T=F)"
+ req : $(I:B)
+ else
+ error 1 $(I): package should be written before $(P)
+ end
+ let package.requires = package.requires + 1
+ include "$(F)"
+ let package.requires = package.requires - 1
+ else
+ error 1 $(I): package not found
+ end
+ end
+ end
+
+":REQUIRES:" : .MAKE .OPERATOR
+ : $(.requires. $(>))
+
+":TEST:" : .MAKE .OPERATOR
+ if ! package.requires
+ local T
+ T := $(>)
+ if "$(T)" == "bin/*([!./])"
+ if "$(exe.$(style))"
+ T := $(T).exe
+ end
+ T := $$(PWD)/$$(ARCH)/$(T)
+ end
+ test.$(style) := $(test.$(style):V)$("\n")test : $(T:V)$("\n\t")$(@)
+ end
+
+base delta : .MAKE .VIRTUAL .FORCE
+ op := $(<)
+
+closure : .MAKE .VIRTUAL .FORCE
+ $(<) := 1
+
+cyg exp lcl pkg rpm tgz : .MAKE .VIRTUAL .FORCE
+ style := $(<)
+
+source : .source.init .source.gen .source.$$(style)
+
+.source.init : .MAKE
+ local A B D P V I
+ type := source
+ if ! "$(incremental)"
+ incremental = 1
+ end
+ if "$(source.$(name))"
+ suffix = c
+ end
+ : $(.init.$(style))
+ : $(details.$(style):V:R) :
+ A := $(source.list)
+ B := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ deltaversion := $(B:B:/$(name).//)
+ let deltasince = $(deltaversion:/.*-//) + 1
+ deltasince := $(deltaversion:/[^-]*$/$(deltasince:F=%02d)/)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ source := $(B:D:B:S=.$(release).$(suffix))
+ version := $(source:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
+ if V == "$(stamp)" && V != "$(version)"
+ old.version := $(V)
+ old.source := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ source := $(B)
+ end
+ if B == "$(source)"
+ if "$(B:D:B:B)" == "$(D:D:B:B)" && "$(B:B::S)" != "$(D:B::S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(source:B:S:/^$(name).\(.*\).$(suffix)$/\1/)
+ end
+ PACKAGEGEN := $(PACKAGESRC)/gen
+
+.source.gen : $$(PACKAGEDIR) $$(PACKAGEGEN) $$(PACKAGEGEN)/SOURCE.html $$(PACKAGEGEN)/BINARY.html $$(PACKAGEGEN)/DETAILS.html
+
+BINPACKAGE := $(PATH:/:/ /G:X=package:T=F:O=1)
+
+$$(PACKAGEDIR) $$(PACKAGEGEN) : .IGNORE
+ [[ -d $(<) ]] || mkdir $(<)
+
+$$(PACKAGEGEN)/SOURCE.html : $(BINPACKAGE)
+ $(*) html source > $(<)
+
+$$(PACKAGEGEN)/BINARY.html : $(BINPACKAGE)
+ $(*) html binary > $(<)
+
+$$(PACKAGEGEN)/DETAILS.html : $(BINPACKAGE)
+ $(*) html intro > $(<)
+
+.source.exp .source.pkg .source.rpm : .MAKE
+ error 3 $(style): source package style not supported yet
+
+exe.cyg = .exe
+vendor.cyg = gnu
+
+.name.cyg : .FUNCTION
+ local N
+ N := $(%)
+ if N == "*-*"
+ vendor := $(N:/-.*//)
+ if vendor == "$(vendor.cyg)"
+ vendor :=
+ N := $(N:/[^-]*-//)
+ end
+ N := $(N:/-//G)
+ end
+ return $(N)
+
+.init.cyg : .FUNCTION
+ local N O
+ closure = 1
+ init = .
+ strip = 1
+ suffix = tar.bz2
+ format = tbz
+ vendor := $(licenses:N!=$(vendor.cyg):O=1)
+ package.ini := $(package.ini)
+ package.src.pat := $(package.src.pat)
+ package.src := $(package.src)
+ package.bin := $(package.bin)
+ .source.gen : .CLEAR $(*.source.gen:V:N!=*.html)
+ name.original := $(name)
+ name := $(.name.cyg $(name))
+ if name != "$(name.original)"
+ $(name) : $(~$(name.original))
+ O := $(~covers)
+ covers : .CLEAR
+ for N $(O)
+ covers : $(.name.cyg $(N))
+ end
+ end
+ stamp = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9]
+ version.original := $(version)
+ version := $(version:/-//G)-1
+ if opt
+ opt := $(opt)/$(vendor)/
+ else
+ opt := $(name)-$(version)/
+ end
+ if type == "source"
+ version := $(version)-src
+ source = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
+ else
+ binary = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
+ end
+
+.source.cyg :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ cat > $tmp/configure <<'!'
+ echo "you didn't have to do that"
+ !
+ chmod +x $tmp/configure
+ echo ";;;$tmp/configure;configure"
+ cat > $tmp/Makefile0 <<'!'
+ HOSTTYPE := $$(shell bin/package)
+ ROOT = ../..
+ ARCH = arch/$$(HOSTTYPE)
+ all :
+ PACKAGEROOT= CYGWIN="$$CYGWIN ntsec binmode" bin/package make $(export.$(style))
+ install : all
+ $(install.$(style):V)
+ $(test.$(style):V)
+ !
+ echo ";;;$tmp/Makefile0;Makefile"
+ cat > $tmp/CYGWIN-README <<'!'
+ $(readme.$(style):@?$$(readme.$$(style))$$("\n\n")??)To build binaries from source into the ./arch/`bin/package` tree run:
+ $()
+ make
+ $()
+ $(test.$(style):@?To test the binaries after building/installing run:$$("\n\n\t")make test$$("\n\n")??)To build and/or install the binaries run:
+ $()
+ make install
+ $()
+ The bin/package command provides a command line interface for all package
+ operations. The $(opt:/.$//) source and binary packages were generated by:
+ $()
+ package write cyg base source version=$(version.original) $(name.original)
+ package write cyg base binary version=$(version.original) $(name.original)
+ $()
+ using the $(org)-base package. To download and install the latest
+ $(org)-base source package in /opt/$(org) run:
+ $()
+ PATH=/opt/$(org)/bin:$PATH
+ cd /opt/$(org)
+ package authorize "NAME" password "PASSWORD" setup flat source $("\\")
+ $(url) $("\\")
+ $(org)-base
+ package make
+ $()
+ and export /opt/$(org)/bin in PATH to use. The NAME and PASSWORD signify your
+ agreement to the software license(s). All users get the same NAME and PASSWORD.
+ See $(url) for details. If multiple architectures may be built under
+ /opt/$(org) then drop "flat" and export /opt/$(org)/arch/`package`/bin in PATH
+ to use. To update previously downloaded packages from the same url simply run:
+ $()
+ cd /opt/$(org)
+ package setup
+ package make
+ $()
+ To download and install the latest $(org)-base binary package in
+ /opt/$(org) change "source" to "binary" and omit "package make".
+ !
+ echo ";;;$tmp/CYGWIN-README;CYGWIN-PATCHES/README"
+ cat > $(source:/-src.$(suffix)//).setup.hint <<'!'
+ category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
+ requires: cygwin
+ sdesc: "$(index)"
+ ldesc: "$($(name.original).README)"
+ !
+ echo ";;;$(source:/-src.$(suffix)//).setup.hint;CYGWIN-PATCHES/setup.hint"
+ echo ";;;$(BINPACKAGE);bin/package"
+ cat > $tmp/Makefile <<'!'
+ :MAKE:
+ !
+ echo ";;;$tmp/Makefile;src/Makefile"
+ echo ";;;$tmp/Makefile;src/cmd/Makefile"
+ echo ";;;$tmp/Makefile;src/lib/Makefile"
+ if [[ '$(mamfile)' == 1 ]]
+ then cat > $tmp/Mamfile1 <<'!'
+ info mam static
+ note source level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/Mamfile1;src/Mamfile"
+ cat > $tmp/Mamfile2 <<'!'
+ info mam static
+ note component level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
+ echo ";;;$tmp/Mamfile2;src/lib/Mamfile"
+ fi
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ echo ";;;$(PACKAGEGEN)/$(name.original).req"
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then if [[ '$(mamfile)' == 1 ]]
+ then (( o=m ))
+ s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
+ if [[ $s ]]
+ then for j in $s
+ do if [[ -d $j ]]
+ then cd $j
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then (( m++ ))
+ $(MAKE) $(package.mam) $(export.$(style):Q) > $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
+ fi
+ cd $(INSTALLROOT)/$i
+ fi
+ done
+ if (( o != m ))
+ then (( m++ ))
+ cat > $tmp/$m.mam <<'!'
+ info mam static
+ note subcomponent level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ else (( m++ ))
+ $(MAKE) $(package.mam) $(export.$(style):Q) > $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ fi
+ $(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q)
+ fi
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ --format=$(format) \
+ --local \
+ -wvf $(source) $(base) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%) \
+ $(vendor:?-s",^[^/],$(opt)&,"??)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ rm -rf $tmp
+ fi
+
+.source.lcl :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) $(=) .FILES.+=Mamfile recurse list.package.local
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ sort -t';' -k5,5 -u |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ -wvf $(source) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%)
+ rm -rf $tmp
+ fi
+
+.source.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ if [[ '$(init)' == '$(name)' ]]
+ then cat > $tmp/Makefile <<'!'
+ :MAKE:
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Makefile $(PACKAGEROOT)/src/Makefile && touch -r $(PACKAGEROOT)/src/Makefile $tmp/Makefile
+ echo ";;;$tmp/Makefile;src/Makefile"
+ cp $tmp/Makefile $tmp/Makefile1
+ $(CMP) $(CMPFLAGS) $tmp/Makefile1 $(PACKAGEROOT)/src/cmd/Makefile && touch -r $(PACKAGEROOT)/src/cmd/Makefile $tmp/Makefile1
+ echo ";;;$tmp/Makefile1;src/cmd/Makefile"
+ cp $tmp/Makefile $tmp/Makefile2
+ $(CMP) $(CMPFLAGS) $tmp/Makefile2 $(PACKAGEROOT)/src/lib/Makefile && touch -r $(PACKAGEROOT)/src/lib/Makefile $tmp/Makefile2
+ echo ";;;$tmp/Makefile2;src/lib/Makefile"
+ if [[ '$(mamfile)' == 1 ]]
+ then cat > $tmp/Mamfile1 <<'!'
+ info mam static
+ note source level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile1 $(PACKAGEROOT)/src/Mamfile && touch -r $(PACKAGEROOT)/src/Mamfile $tmp/Mamfile1
+ echo ";;;$tmp/Mamfile1;src/Mamfile"
+ cat > $tmp/Mamfile2 <<'!'
+ info mam static
+ note component level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile2 $(PACKAGEROOT)/src/cmd/Mamfile && touch -r $(PACKAGEROOT)/src/cmd/Mamfile $tmp/Mamfile2
+ echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
+ cp $tmp/Mamfile2 $tmp/Mamfile3
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile3 $(PACKAGEROOT)/src/lib/Mamfile && touch -r $(PACKAGEROOT)/src/lib/Mamfile $tmp/Mamfile3
+ echo ";;;$tmp/Mamfile3;src/lib/Mamfile"
+ fi
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lib pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ if [[ '$(PACKAGEDIR:B)' == '$(style)' ]]
+ then echo $(name) $(version) $(release|version) 1 > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).ver || cp $tmp/t $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).req || cp $tmp/t $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).inx || cp $tmp/t $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ } | fmt
+ package help source
+ package release $(name)
+ } > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).README || cp $tmp/t $(PACKAGEGEN)/$(name).README
+ echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
+ {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package"'
+ echo '.xx meta.keywords="software, package"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package'
+ echo '.H 1 "$(name) package"'
+ echo '$($(name).README)'
+ set -- $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F:D::B)
+ hot=
+ for i
+ do hot="$hot -e s/\\(\\<$i\\>\\)/\\\\h'0*1'\\1\\\\h'0'/"
+ done
+ set -- $(package.closure:B)
+ if (( $# ))
+ then echo 'Components in this package:'
+ echo '.P'
+ echo '.TS'
+ echo 'center expand;'
+ echo 'l l l l l l.'
+ if [[ $hot ]]
+ then hot="sed $hot"
+ else hot=cat
+ fi
+ for i
+ do echo $i
+ done |
+ pr -6 -t -s' ' |
+ $hot
+ echo '.TE'
+ fi
+ echo '.P'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ set -- $(.package.licenses. --all $(name))
+ case $# in
+ 0) ;;
+ *) case $# in
+ 1) echo 'The software is covered by this license:' ;;
+ *) echo 'The software is covered by these licenses:' ;;
+ esac
+ echo .BL
+ for j
+ do i=$( $(PROTO) -l $j -p -h -o type=usage /dev/null | sed -e 's,.*\[-license?\([^]]*\).*,\1,' )
+ echo .LI
+ echo ".xx link=\"$i\""
+ done
+ echo .LE
+ echo 'Individual components may be covered by separate licenses;'
+ echo 'refer to the component source and/or binaries for more information.'
+ echo .P
+ ;;
+ esac
+ echo 'A recent'
+ echo '.xx link="release change log"'
+ echo 'is also included.'
+ cat $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F) < /dev/null
+ echo '.H 1 "release change log"'
+ echo '.xx index'
+ echo '.nf'
+ package release $(name) |
+ sed -e 's/:::::::: \(.*\) ::::::::/.fi\$("\n").H 1 "\1 changes"\$("\n").nf/'
+ echo '.fi'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
+ $(STDED) $(STDEDFLAGS) $tmp/t <<'!'
+ /^<!--LABELS-->$/,/^<!--\/LABELS-->$/s/ changes</</
+ /^<!--LABELS-->$/,/^<!--\/LABELS-->$/m/<A name="release change log">/
+ w
+ q
+ !
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).html || cp $tmp/t $(PACKAGEGEN)/$(name).html
+ echo ";;;$(PACKAGEGEN)/$(name).html;$(PACKAGELIB)/$(name).html"
+ if [[ '$(deltasince)' ]]
+ then {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package $(version) delta $(release)"'
+ echo '.xx meta.keywords="software, package, delta"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package $(deltaversion) delta $(release)'
+ echo '.H 1 "$(name) package $(deltaversion) delta $(release) changes"'
+ echo '.nf'
+ package release $(deltasince) $(name) |
+ sed -e 's/:::::::: \(.*\) ::::::::/.H 2 \1/'
+ echo '.fi'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).$(release).html || cp $tmp/t $(PACKAGEGEN)/$(name).$(release).html
+ echo ";;;$(PACKAGEGEN)/$(name).$(release).html;$(PACKAGELIB)/$(name).$(release).html"
+ fi
+ fi
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then if [[ '$(mamfile)' == 1 ]]
+ then (( o=m ))
+ s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
+ if [[ $s ]]
+ then for j in $s
+ do if [[ -d $j ]]
+ then cd $j
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then (( m++ ))
+ $(MAKE) $(package.mam) > $tmp/$m.mam
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/$j/Mamfile && touch -r $(PACKAGEROOT)/$i/$j/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
+ fi
+ cd $(INSTALLROOT)/$i
+ fi
+ done
+ if (( o != m ))
+ then (( m++ ))
+ cat > $tmp/$m.mam <<'!'
+ info mam static
+ note subcomponent level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ else (( m++ ))
+ $(MAKE) $(package.mam) > $tmp/$m.mam
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ fi
+ $(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q) $(copyright:N=1:??LICENSE=?)
+ fi
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ $(CMP) $(CMPFLAGS) $tmp/README $(PACKAGEROOT)/README && touch -r $(PACKAGEROOT)/README $tmp/README
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ -wvf $(source) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ echo local > $(source:D:B=$(name):S=.tim)
+ if [[ '$(incremental)' == 1 && '$(old.source)' ]]
+ then $(PAX) -rf $(source) -wvf $(old.new.source) -z $(old.source)
+ $(SUM) -x $(checksum) < $(old.new.source) > $(old.new.source:D:B:S=.$(checksum))
+ fi
+ rm -rf $tmp
+ else if [[ '$(old.source)' ]] && $(CMP) $(CMPFLAGS) $(source.$(name)) $(source)
+ then : $(name) is up to date
+ else echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ : > $(PACKAGEGEN)/$(name).req
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package"'
+ echo '.xx meta.keywords="software, package"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package'
+ echo '.H 1'
+ echo '$($(name).README)'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $(PACKAGEGEN)/$(name).html
+ if [[ '$(source.$(name))' ]]
+ then {
+ echo '$($(name).README)'
+ package help source
+ } > $(PACKAGEGEN)/$(name).README
+ cp $(source.$(name)) $(source)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ fi
+ echo local > $(source:D:B=$(name):S=.tim)
+ fi
+ fi
+
+binary : .binary.init .binary.gen .binary.$$(style)
+
+.binary.init : .MAKE
+ local A B D I P V
+ type := binary
+ if ! "$(incremental)"
+ incremental = 0
+ end
+ if ! "$(~$(name))"
+ if name == "ratz"
+ suffix = exe
+ else
+ suffix = gz
+ end
+ end
+ : $(.init.$(style)) :
+ : $(details.$(style):V:R) :
+ A := $(binary.list)
+ B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ binary := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
+ version := $(binary:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
+ if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
+ old.version := $(V)
+ old.binary := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ binary := $(B)
+ end
+ if B == "$(binary)"
+ if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(binary:B:/$(name).//:/\..*//)
+ end
+ PACKAGEGEN := $(PACKAGEBIN)/gen
+
+.binary.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
+
+.binary.exp .binary.pkg .binary.rpm : .MAKE
+ error 3 $(style): binary package style not supported yet
+
+.binary.cyg :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ {
+ echo '$($(name.original).README)' | fmt
+ cat <<'!'
+ $(readme.$(style):@?$$("\n")$$(readme.$$(style))??)
+ !
+ } > $tmp/README1
+ echo ";;;$tmp/README1;usr/share/doc/Cygwin/$(opt:/.$//).README"
+ {
+ echo '$($(name.original).README)' | fmt
+ cat <<'!'
+ $()
+ The remainder of this file is the README from the source package
+ that was used to generate this binary package. It describes
+ the source build hierarchy, not the current directory.
+ $()
+ $(package.readme)
+ !
+ } > $tmp/README2
+ echo ";;;$tmp/README2;usr/share/doc/$(opt)README"
+ package release $(name.original) > $tmp/RELEASE
+ echo ";;;$tmp/RELEASE;usr/share/doc/$(opt)RELEASE"
+ cat > $(binary:/.$(suffix)//).setup.hint <<'!'
+ category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
+ requires: cygwin
+ sdesc: "$(index)"
+ ldesc: "$($(name.original).README)"
+ !
+ set -- $(.package.licenses. --text $(name.original):N!=*.lic)
+ for i
+ do echo ";;;${i};usr/share/doc/$(opt)LICENSE-${i##*/}"
+ done
+ cat <<'!'
+ $(filter.$(style))
+ !
+ if [[ '$(postinstall.$(style):V:O=1:?1??)' ]]
+ then cat >$tmp/postinstall <<'!'
+ $("#")!/bin/sh
+ $(postinstall.$(style))
+ !
+ echo ";;;$tmp/postinstall;etc/postinstall/$(name).sh"
+ fi
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ --format=$(format) \
+ --local \
+ -wvf $(binary)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ rm -rf $tmp
+ fi
+
+.binary.lcl :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ $(package.bin:U:T=F:/.*/echo ";;;&"$("\n")/)
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name).sum \
+ --install=$(PACKAGEGEN)/$(name).ins \
+ -wvf $(binary) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ rm -rf $tmp
+ fi
+
+.binary.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ if [[ '$(init)' == '$(name)' ]]
+ then for i in lib32 lib64
+ do if [[ -d $(INSTALLROOT)/$i ]]
+ then echo ";physical;;$(INSTALLROOT)/$i"
+ fi
+ done
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ $(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ $(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ if [[ '$(PACKAGEDIR:B)' == '$(style)' ]]
+ then echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lic pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ } | fmt
+ package help binary
+ package release $(name)
+ } > $(PACKAGEGEN)/$(name).README
+ echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
+ fi
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name).sum \
+ --install=$(PACKAGEGEN)/$(name).ins \
+ -wvf $(binary) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ if [[ '$(incremental)' == 1 && '$(old.binary)' ]]
+ then $(PAX) -rf $(binary) -wvf $(old.new.binary) -z $(old.binary)
+ echo $(old.new.binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(old.new.binary) > $(old.new.binary:D:B:S=.$(checksum))
+ echo $(old.new.binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+ rm -rf $tmp
+ else if [[ '$(binary.$(name))' ]]
+ then exe=$(binary.$(name))
+ else exe=$(INSTALLROOT)/bin/$(name)
+ fi
+ if [[ '$(old.binary)' ]] && $(CMP) $(CMPFLAGS) $exe $(binary)
+ then : $(name) is up to date
+ else echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ : > $(PACKAGEGEN)/$(name).req
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ echo '$($(name).README)'
+ package help binary
+ } > $(PACKAGEGEN)/$(name).README
+ case "$(binary)" in
+ *.gz) gzip < $exe > $(binary) ;;
+ *) cp $exe $(binary) ;;
+ esac
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ fi
+ echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+
+runtime : .runtime.init .runtime.gen .runtime.$$(style)
+
+.runtime.init : .MAKE
+ local A B D I P V
+ type := runtime
+ if ! "$(incremental)"
+ incremental = 0
+ end
+ if ! "$(~$(name))"
+ if name == "ratz"
+ suffix = exe
+ else
+ suffix = gz
+ end
+ end
+ : $(.init.$(style)) :
+ : $(details.$(style):V:R) :
+ A := $(runtime.list)
+ B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ runtime := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
+ version := $(runtime:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)-run\.\([^.]*\).*/\1/)
+ if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
+ old.version := $(V)
+ old.runtime := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ runtime := $(B)
+ end
+ if B == "$(runtime)"
+ if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(runtime:B:/$(name)-run.//:/\..*//)
+ end
+ PACKAGEGEN := $(PACKAGESRC)/gen
+
+.runtime.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
+
+.runtime.cyg .runtime.exp .runtime.lcl .runtime.pkg .runtime.rpm : .MAKE
+ error 3 $(style): runtime package style not supported yet
+
+.runtime.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ if [[ '$(init)' == '$(name)' ]]
+ then for i in lib32 lib64
+ do if [[ -d $(INSTALLROOT)/$i ]]
+ then echo ";physical;;$(INSTALLROOT)/$i"
+ fi
+ done
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ $(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ $(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lic pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo
+ echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo
+ echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ echo
+ echo "To install this $(type) package read the tarball into a directory"
+ echo "suitable for containing bin and lib subdirectories, and run the"
+ echo "$(PACKAGELIB)/gen/$(name)-run.ins script to fix up permissions."
+ echo
+ echo "To use the package export the bin directory in PATH. The commands and"
+ echo "libraries use \$PATH to locate dynamic libraries and related data files."
+ echo
+ } | fmt
+ } > $(PACKAGEGEN)/$(name)-run.README
+ echo ";;;$(PACKAGEGEN)/$(name)-run.README;$(PACKAGELIB)/$(name)-run.README"
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name)-run.sum \
+ --install=$(PACKAGEGEN)/$(name)-run.ins \
+ -wvf $(runtime) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ echo $(runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(runtime) > $(runtime:D:B:S=.$(checksum))
+ echo $(runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo local > $(runtime:D:B=$(name)-run:S=.$(CC.HOSTTYPE).tim)
+ if [[ '$(incremental)' == 1 && '$(old.runtime)' ]]
+ then $(PAX) -rf $(runtime) -wvf $(old.new.runtime) -z $(old.runtime)
+ echo $(old.new.runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(old.new.runtime) > $(old.new.runtime:D:B:S=.$(checksum))
+ echo $(old.new.runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+ rm -rf $tmp
+ fi
+
+list.installed list.manifest :
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ ignore $(MAKE) --noexec $(-) $(=) $(<)
+ done
diff --git a/src/cmd/INIT/package.sh b/src/cmd/INIT/package.sh
new file mode 100644
index 0000000..3f1ed1b
--- /dev/null
+++ b/src/cmd/INIT/package.sh
@@ -0,0 +1,7302 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+### this script contains archaic constructs that work with all sh variants ###
+# package - source and binary package control
+# Glenn Fowler <gsf@research.att.com>
+
+command=package
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+# ksh checks -- ksh between 2007-11-05 and 2011-11-11 conflict with new -lcmd -- wea culpa
+checksh()
+{
+ egrep 'Version.*(88|1993)' $1 >/dev/null 2>&1 ||
+ $1 -c '(( .sh.version >= 20111111 ))' >/dev/null 2>&1
+}
+
+case $_AST_BIN_PACKAGE_:$SHELL:$0 in
+1:*|*:/bin/sh:*)
+ ;;
+*:*/*:*/*)
+ _AST_BIN_PACKAGE_=1 # prevent non-interactive sh .rc referencing bin/package recursion #
+ export _AST_BIN_PACKAGE_
+ if checksh $SHELL
+ then : no -lcmd conflict :
+ else case " $* " in
+ *" debug "*|*" DEBUG "*|*" show "*)
+ echo $command: $SHELL: warning: possible -lcmd conflict -- falling back to /bin/sh >&2
+ ;;
+ esac
+ SHELL=/bin/sh
+ export SHELL
+ exec $SHELL "$0" "$@"
+ fi
+ ;;
+esac
+
+LC_ALL=C
+export LC_ALL
+
+src="cmd contrib etc lib"
+use="/usr/common /exp /usr/local /usr/add-on /usr/addon /usr/tools /usr /opt"
+usr="/home"
+lib="" # nee /usr/local/lib /usr/local/shlib
+ccs="/usr/kvm /usr/ccs/bin"
+org="gnu GNU"
+makefiles="Mamfile Nmakefile nmakefile Makefile makefile"
+env="HOSTTYPE NPROC PACKAGEROOT INSTALLROOT PATH"
+checksum=md5sum
+checksum_commands="$checksum md5"
+checksum_empty="d41d8cd98f00b204e9800998ecf8427e"
+
+package_use='=$HOSTTYPE=$PACKAGEROOT=$INSTALLROOT=$EXECROOT=$CC='
+
+PACKAGE_admin_tail_timeout=${PACKAGE_admin_tail_timeout:-"1m"}
+
+CROSS=0
+
+admin_db=admin.db
+admin_env=admin.env
+admin_ditto="ditto --checksum --delete --verbose"
+admin_ditto_update=--update
+admin_ditto_skip="OFFICIAL|core|old|*.core|*.tmp|.nfs*"
+admin_list='PACKAGE.$type.lst'
+admin_ping="ping -c 1 -w 5"
+
+default_url=default.url
+MAKESKIP=${MAKESKIP:-"*[-.]*"}
+RATZ=ratz
+SED=
+TAR=tar
+TARFLAGS=xv
+TARPROBE=B
+TR=
+
+all_types='*.*|sun4' # all but sun4 match *.*
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: package (AT&T Research) 2012-02-29 $
+]'$USAGE_LICENSE$'
+[+NAME?package - source and binary package control]
+[+DESCRIPTION?The \bpackage\b command controls source and binary
+ packages. It is a \bsh\b(1) script coded for maximal portability. All
+ package files are in the \b$PACKAGEROOT\b directory tree.
+ \b$PACKAGEROOT\b must at minumum contain a \bbin/package\b command or a
+ \blib/package\b directory. Binary package files are in the
+ \b$INSTALLROOT\b (\b$PACKAGEROOT/arch/\b\ahosttype\a) tree, where
+ \ahosttpe\a=`\bpackage\b`. All \aactions\a but \bhost\b and \buse\b
+ require the current directory to be under \b$PACKAGEROOT\b. See
+ \bDETAILS\b for more information.]
+[+?Note that no environment variables need be set by the user;
+ \bpackage\b determines the environment based on the current working
+ directory. The \buse\b action starts a \bsh\b(1) with the environment
+ initialized. \bCC\b, \bCCFLAGS\b, \bHOSTTYPE\b and \bSHELL\b may be set
+ by explicit command argument assignments to override the defaults.]
+[+?Packages are composed of components. Each component is built and
+ installed by an \bast\b \bnmake\b(1) makefile. Each package is also
+ described by an \bnmake\b makefile that lists its components and
+ provides a content description. The package makefile and component
+ makefiles provide all the information required to read, write, build
+ and install packages.]
+[+?Package recipients only need \bsh\b(1) and \bcc\b(1) to build and
+ install source packages, and \bsh\b to install binary packages.
+ \bnmake\b and \bksh93\b are required to write new packages. An
+ \b$INSTALLROOT/bin/cc\b script may be supplied for some architectures.
+ This script supplies a reasonable set of default options for compilers
+ that accept multiple dialects or generate multiple object/executable
+ formats.]
+[+?The command arguments are composed of a sequence of words: zero or
+ more \aqualifiers\a, one \aaction\a, and zero or more action-specific
+ \aarguments\a, and zero or more \aname=value\a definitions. \apackage\a
+ names a particular package. The naming scheme is a \b-\b separated
+ hierarchy; the leftmost parts describe ownership, e.g.,
+ \bgnu-fileutils\b, \bast-base\b. If no packages are specified then all
+ packages are operated on. \boptget\b(3) documentation options are also
+ supported. The default with no arguments is \bhost type\b.]
+[+?The qualifiers are:]
+ {
+ [+authorize \aname\a?Remote authorization user name or license
+ acceptance phrase.]
+ [+debug|environment?Show environment and actions but do not
+ execute.]
+ [+flat?Collapse \b$INSTALLROOT\b { bin fun include lib } onto
+ \b$PACKAGEROOT\b.]
+ [+force?Force the action to override saved state.]
+ [+never?Run make -N and show other actions.]
+ [+only?Only operate on the specified packages.]
+ [+password \apassword\a?Remote authorization or license
+ acceptance password.]
+ [+quiet?Do not list captured action output.]
+ [+show?Run make -n and show other actions.]
+ [+verbose?Provide detailed action output.]
+ [+DEBUG?Trace the package script actions in detail.]
+ }
+[+?The actions are:]
+ {
+ [+admin\b [\ball\b]] [\bdb\b \afile\a]] [\bon\b \apattern\a]][\aaction\a ...]]?Apply
+ \aaction\a ... to the hosts listed in \afile\a. If \afile\a is
+ omitted then \badmin.db\b is assumed. The caller must have
+ \brcp\b(1) and \brsh\b(1) or \bscp\b(1) and \bssh\b(1) access
+ to the hosts. Output for \aaction\a is saved per-host in the
+ file \aaction\a\b.log/\b\ahost\a. Logs can be viewed by
+ \bpackage admin\b [\bon\b \ahost\a]] \bresults\b [\aaction\a]].
+ By default only local PACKAGEROOT hosts are selected from
+ \afile\a; \ball\b selects all hosts. \bon\b \apattern\a selects
+ only hosts matching the \b|\b separated \apattern\a. \afile\a
+ contains four types of lines. Blank lines and lines beginning
+ with \b#\b are ignored. Lines starting with \aid\a=\avalue\a
+ are variable assignments. Set admin_ping to local conventions
+ if \"'$admin_ping$'\" fails. If a package list is not specified
+ on the command line the \aaction\a applies to all packages; a
+ variable assigment \bpackage\b=\"\alist\a\" applies \aaction\a
+ to the packages in \alist\a for subsequent hosts in \afile\a.
+ The remaining line type is a host description consisting of 6
+ tab separated fields. The first 3 are mandatory; the remaining
+ 3 are updated by the \badmin\b action. \afile\a is saved in
+ \afile\a\b.old\b before update. The fields are:]
+ {
+ [+hosttype?The host type as reported by
+ \"\bpackage\b\".]
+ [+[user@]]host?The host name and optionally user name
+ for \brcp\b(1) and \brsh\b(1) access.]
+ [+[remote::[[master]]::]]]]PACKAGEROOT?The absolute remote package
+ root directory and optionally the remote protocol (rsh
+ or ssh) if the directory is on a different server than
+ the master package root directory. If
+ \blib/package/admin/'$admin_env$'\b exists under this
+ directory then it is sourced by \bsh\b(1) before
+ \aaction\a is done. If this field begins with \b-\b
+ then the host is ignored. If this field contains \b:\b
+ then \bditto\b(1) is used to sync the remote \bsrc\b
+ directory hierarchy to the local one. If [\amaster\a]]:
+ is specified then the sync is deferred to the \amaster\a
+ host. If \amaster\a is omitted (two :) then the sync is
+ disabled. These directories must exist on the remote side:
+ \blib/package\b, \bsrc/cmd\b, \bsrc/lib\b.]
+ [+date?\aYYMMDD\a of the last action.]
+ [+time?Elapsed wall time for the last action.]
+ [+M T W?The \badmin\b action \bmake\b, \btest\b and
+ \bwrite\b action error counts. A non-numeric value in
+ any of these fields disables the corresponding action.]
+ }
+ [+clean | clobber?Delete the \barch/\b\aHOSTTYPE\a hierarchy; this
+ deletes all generated files and directories for \aHOSTTYPE\a.
+ The heirarchy can be rebuilt by \bpackage make\b.]
+ [+contents\b [ \apackage\a ... ]]?List description and
+ components for \apackage\a on the standard output.]
+ [+copyright\b [ \apackage\a ... ]]?List the general copyright
+ notice(s) for \apackage\a on the standard output. Note that
+ individual components in \apackage\a may contain additional or
+ replacement notices.]
+ [+export\b [ \avariable\a ...]]?List \aname\a=\avalue\a for
+ \avariable\a, one per line. If the \bonly\b attribute is
+ specified then only the variable values are listed. If no
+ variables are specified then \b'$env$'\b are assumed.]
+ [+help\b [ \aaction\a ]]?Display help text on the standard
+ error (standard output for \aaction\a).]
+ [+host\b [ \aattribute\a ... ]]?List
+ architecture/implementation dependent host information on the
+ standard output. \btype\b is listed if no attributes are
+ specified. Information is listed on a single line in
+ \aattribute\a order. The attributes are:]
+ {
+ [+canon \aname\a?An external host type name to be
+ converted to \bpackage\b syntax.]
+ [+cpu?The number of cpus; 1 if the host is not a
+ multiprocessor.]
+ [+name?The host name.]
+ [+rating?The cpu rating in pseudo mips; the value is
+ useful useful only in comparisons with rating values of
+ other hosts. Other than a vax rating (mercifully) fixed
+ at 1, ratings can vary wildly but consistently from
+ vendor mips ratings. \bcc\b(1) may be required to
+ determine the rating.]
+ [+type?The host type, usually in the form
+ \avendor\a.\aarchitecture\a, with an optional trailing
+ -\aversion\a. The main theme is that type names within
+ a family of architectures are named in a similar,
+ predictable style. OS point release information is
+ avoided as much as possible, but vendor resistance to
+ release incompatibilities has for the most part been
+ futile.]
+ }
+ [+html\b [ \aaction\a ]]?Display html help text on the standard
+ error (standard output for \aaction\a).]
+ [+install\b [ \aarchitecture\a ... ]] \adirectory\a [ \apackage\a ... ]]?Copy
+ the package binary hierarchy to \adirectory\a. If
+ \aarchitecture\a is omitted then all architectures are
+ installed. If \bflat\b is specified then exactly one
+ \aarchitecture\a must be specified; this architecture will be
+ installed in \adirectory\a without the \barch/\b\aHOSTTYPE\a
+ directory prefixes. Otherwise each architecture will be
+ installed in a separate \barch/\b\aHOSTTYPE\a subdirectory of
+ \adirectory\a. The \aarchitecture\a \b-\b names the current
+ architecture. \adirectory\a must be an existing directory. If
+ \apackage\a is omitted then all binary packages are installed.
+ This action requires \bnmake\b.]
+ [+license\b [ \apackage\a ... ]]?List the source license(s) for
+ \apackage\a on the standard output. Note that individual
+ components in \apackage\a may contain additional or replacement
+ licenses.]
+ [+list\b [ \apackage\a ... ]]?List the name, version and
+ prerequisites for \apackage\a on the standard output.]
+ [+make\b [ \apackage\a ]] [ \aoption\a ... ]] [ \atarget\a ... ]]?Build
+ and install. The default \atarget\a is \binstall\b, which makes
+ and installs \apackage\a. If the standard output is a terminal
+ then the output is also captured in
+ \b$INSTALLROOT/lib/package/gen/make.out\b. The build is done in
+ the \b$INSTALLROOT\b directory tree viewpathed on top of the
+ \b$PACKAGEROOT\b directory tree. If \bflat\b is specified then
+ the \b$INSTALLROOT\b { bin fun include lib } directories are
+ linked to the same directories in the package root. Only one
+ architecture may be \bflat\b. Leaf directory names matching the
+ \b|\b-separated shell pattern \b$MAKESKIP\b are ignored. The
+ \bview\b action is done before making. \aoption\a operands are
+ passed to the underlying make command.]
+ [+read\b [ \apackage\a ... | \aarchive\a ... ]]?Read the named
+ package or archive(s). Must be run from the package root
+ directory. Archives are searched for in \b.\b and
+ \blib/package/tgz\b. Each package archive is read only once.
+ The file \blib/package/tgz/\b\apackage\a[.\atype\a]]\b.tim\b
+ tracks the read time. See the \bwrite\b action for archive
+ naming conventions. Text file archive member are assumed to be
+ ASCII or UTF-8 encoded.]
+ [+regress?\bdiff\b(1) the current and previous \bpackage test\b
+ results.]
+ [+release\b [ [\aCC\a]]\aYY-MM-DD\a [ [\acc\a]]\ayy-mm-dd\a ]]]] [ \apackage\a ]]?Display
+ recent changes for the date range [\aCC\a]]\aYY-MM-DD\a (up to
+ [\acc\a]]\ayy-mm-dd\a.), where \b-\b means lowest (or highest.)
+ If no dates are specified then changes for the last 4 months
+ are listed. \apackage\a may be a package or component name.]
+ [+remove\b [ \apackage\a ]]?Remove files installed for
+ \apackage\a.]
+ [+results\b [ \bfailed\b ]] [ \bpath\b ]] [ \bold\b ]] [\bmake\b | \btest\b | \bwrite\b ]]?List
+ results and interesting messages captured by the most recent
+ \bmake\b (default), \btest\b or \bwrite\b action. \bold\b
+ specifies the previous results, if any (current and previous
+ results are retained.) \b$HOME/.pkgresults\b, if it exists,
+ must contain an \begrep\b(1) expression of result lines to be
+ ignored. \bfailed\b lists failures only and \bpath\b lists the
+ results file path name only.]
+ [+setup\b [ beta ]] [ binary ]] [ source ]] [ \aarchitecture\a ... ]] [ \aurl\a ]] [ \apackage\a ... ]]?This
+ action initializes the current directory as a package root, runs the
+ \bupdate\b action to download new or out of date packages, and runs the
+ \bread\b action on those packages. If \bflat\b is specified then the
+ \b$INSTALLROOT\b { bin fun include lib } directories are linked to the
+ same directories in the package root. Only one architecture may be
+ \bflat\b. See the \bupdate\b and \bread\b action descriptions for
+ argument details.]
+ [+test\b [ \apackage\a ]]?Run the regression tests for
+ \apackage\a. If the standard output is a terminal then the
+ output is also captured in
+ \b$INSTALLROOT/lib/package/gen/test.out\b. In general a package
+ must be made before it can be tested. Components tested with
+ the \bregress\b(1) command require \bksh93\b. If \bonly\b is
+ also specified then only the listed package components are
+ tested, otherwise the closure of the components is tested.]
+ [+update\b [ beta ]] [ binary ]] [ source ]] [\aarchitecture\a ... ]] [ \aurl\a ]] [ \apackage\a ... ]]?Download
+ the latest release of the selected and required packages from \aurl\a
+ (e.g., \bhttp://www.research.att.com/sw/download\b) into the directory
+ \b$PACKAGEROOT/lib/package/tgz\b. \bbeta\b acesses beta packages;
+ download these at your own risk. If \aarchitecture\a is omitted then
+ only architectures already present in the \btgz\b directory will be
+ downloaded. If \aarchitecture\a is \b-\b then all posted architectures
+ will be downloaded. If \aurl\a matches \b*.url\b then it is interpreted
+ as a file containing shell variable assignments for \burl\b,
+ \bauthorize\b and \bpassword\b. If \aurl\a is omitted then the
+ definitions for \burl\b, \bauthorize\b and \bpassword\b in
+ \b$PACKAGEROOT/lib/package/tgz/default.url\b, if it exists, are used.
+ If \b$PACKAGEROOT/lib/package/tgz/default.url\b does not exist then it
+ is initialized with the current \burl\b, \bauthorize\b and \bpassword\b
+ values and read permission for the current user only. If \apackage\a is
+ omitted then only packages already present in the tgz directory will be
+ downloaded. If \apackage\a is \b-\b then all posted packages will be
+ downloaded. If \bsource\b and \bbinary\b are omitted then both source
+ and binary packages will be downloaded. If \bonly\b is specified then
+ only the named packages are updated; otherwise the closure of required
+ packages is updated. This action requires \bwget\b(1), \blynx\b(1),
+ \bcurl\b(1) or a shell that supports io to
+ \b/dev/tcp/\b\ahost\a/\aport\a.]
+ [+use\b [ \auid\a | \apackage\a | . [ 32 | 64 ]] | 32 | 64 | - ]] [ command ...]]?Run
+ \acommand\a, or an interactive shell if \acommand\a is omitted,
+ with the environment initialized for using the package (can you
+ say \ashared\a \alibrary\a or \adll\a without cussing?) If
+ \auid\a or \apackage\a or \a.\a is specified then it is used
+ to determine a \b$PACKAGEROOT\b, possibly different from
+ the current directory. For example, to try out bozo`s package:
+ \bpackage use bozo\b. The \buse\b action may be run from any
+ directory. If the file \b$INSTALLROOT/lib/package/profile\b is
+ readable then it is sourced to initialize the environment. 32 or 64
+ implies \b$PACKAGEROOT\b of . and specifies the target architecture
+ word size (which may be silently ignored.)]
+ [+verify\b [ \apackage\a ]]?Verify installed binary files
+ against the checksum files in
+ \b$INSTALLROOT/lib/\b\apackage\a\b/gen/*.sum\b. The checksum
+ files contain mode, user and group information. If the checksum
+ matches for a given file then the mode, user and group are
+ changed as necessary to match the checksum entry. A warning is
+ printed on the standard error for each mismatch. Requires the
+ \bast\b package \bcksum\b(1) command.]
+ [+view\b?Initialize the architecture specific viewpath
+ hierarchy. If \bflat\b is specified then the \b$INSTALLROOT\b {
+ bin fun include lib } directories are linked to the same
+ directories in the package root. Only one architecture may be
+ \bflat\b. The \bmake\b action implicitly calls this action.]
+ [+write\b [\aformat\a]] \atype\a ... [ \apackage\a ...]]?Write
+ a package archive for \apackage\a. All work is done in the
+ \b$PACKAGEROOT/lib/package\b directory. \aformat\a-specific
+ files are placed in the \aformat\a subdirectory. A
+ \apackage\a[.\atype\a]]\b.tim\b file in this directory tracks
+ the write time and prevents a package from being read in the
+ same root it was written. If more than one file is generated
+ for a particular \aformat\a then those files are placed in the
+ \aformat\a/\apackage\a subdirectory. File names in the
+ \aformat\a subdirectory will contain the package name, a
+ \ayyyy-mm-dd\a date, and for binary packages, \aHOSTTYPE\a. If
+ \apackage\a is omitted then an ordered list of previously
+ written packages is generated. If \bonly\b is specified then
+ only the named packages will be written; otherwise prerequisite
+ packages are written first. Package components must be listed
+ in \apackage\a\b.pkg\b. \aformat\a may be one of:]
+ {
+ [+cyg?Generate a \bcygwin\b package.]
+ [+exp?Generate an \bexptools\b maintainer source
+ archive and \aNPD\a file, suitable for \bexpmake\b(1)]
+ [+lcl?Generate a package archive suitable for
+ restoration into the local source tree (i.e., the
+ source is not annotated for licencing.)]
+ [+pkg?Generate a \bpkgmk\b(1) package suitable for
+ \bpkgadd\b(1).]
+ [+rpm?Generate an \brpm\b(1) package.]
+ [+tgz?Generate a \bgzip\b(1) \btar\b(1) package
+ archive. This is the default.]
+ [+tst?Generate a \btgz\b format package archive in the
+ \btst\b subdirectory. Version state files are not updated.]
+ }
+ [+?\btype\b specifies the package type which must be one of
+ \bsource\b, \bbinary\b or \bruntime\b. A source package
+ contains the source needed to build the corresponding binary
+ package. A binary package includes the libraries and headers
+ needed for compiling and linking against the public interfaces.
+ A runtime package contains the commands and required dynamic
+ libraries.]
+ [+?A package may be either a \bbase\b or \bdelta\b. A base
+ package contains a complete copy of all components. A delta
+ package contains only changes from a previous base package.
+ Delta recipients must have the \bast\b \bpax\b(1) command (in
+ the \bast-base\b package.) If neither \bbase\b nor \bdelta\b is
+ specified, then the current base is overwritten if there are no
+ deltas referring to the current base. Only the \btgz\b and
+ \blcl\b formats support \bdelta\b. If \bbase\b is specified
+ then a new base and two delta archives are generated: one delta
+ to generate the new base from the old, and one delta to
+ generate the old base from the new; the old base is then
+ removed. If \bdelta\b is specified then a new delta referring
+ to the current base is written.]
+ [+?\apackage\a\b.pkg\b may reference other packages. By default
+ a pointer to those packages is written. The recipient \bpackage
+ read\b will then check that all required packages have been
+ downloaded. If \bclosure\b is specified then the components for
+ all package references are included in the generated package.
+ This may be useful for \blcl\b and versioning.]
+ [+?All formats but \blcl\b annotate each \bsource\b file (not
+ already annotated) with a license comment as it is written to
+ the package archive using \bproto\b(1).]
+ }
+[+DETAILS?The package directory hierarchy is rooted at
+ \b$PACKAGEROOT\b. All source and binaries reside under this tree. A two
+ level viewpath is used to separate source and binaries. The top view is
+ architecture specific, the bottom view is shared source. All building
+ is done in the architecture specific view; no source view files are
+ intentionally changed. This means that many different binary
+ architectures can be made from a single copy of the source.]
+[+?Independent \b$PACKAGEROOT\b hierarchies can be combined by
+ appending \b$INSTALLROOT:$PACKAGEROOT\b pairs to \bVPATH\b. The
+ \bVPATH\b viewing order is from left to right. Each \b$PACKAGEROOT\b
+ must have a \b$PACKAGEROOT/lib/package\b directory.]
+[+?Each package contains one or more components. Component source for
+ the \afoo\a command is in \b$PACKAGEROOT/src/cmd/\b\afoo\a, and source
+ for the \abar\a library is in \b$PACKAGEROOT/src/lib/lib\b\abar\a. This
+ naming is for convenience only; the underlying makefiles handle
+ inter-component build order. The \bINIT\b component, which contains
+ generic package support files, is always made first, then the
+ components named \bINIT\b*, then the component order determined by the
+ closure of component makefile dependencies.]
+[+?\b$PACKAGEROOT/lib/package\b contains package specific files. The
+ package naming convention is \agroup\a[-\apart\a]]; e.g., \bast-base\b,
+ \bgnu-fileutils\b. The *\b.pkg\b files are ast \bnmake\b(1) makefiles
+ that contain the package name, package components, references to other
+ packages, and a short package description. *\b.pkg\b files are used by
+ \bpackage write\b to generate new source and binary packages.]
+[+?\b$PACKAGEROOT/lib/package/\b\agroup\a\b.lic\b files contain license
+ information that is used by the \bast\b \bproto\b(1) and \bnmake\b(1)
+ commands to generate source and binary license strings. \agroup\a is
+ determined by the first \b:PACKAGE:\b operator name listed in the
+ component \bnmake\b makefile. \agroup\a\b.lic\b files are part of the
+ licensing documentation. Each component may have its own \bLICENSE\b file
+ that overrides the \agroup\a\b.lic\b file. The full text of the licenses
+ are in the \b$PACKAGEROOT/lib/package/LICENSES\b and
+ \b$INSTALLROOT/lib/package/LICENSES\b directories.]
+[+?A few files are generated in \b$PACKAGEROOT/lib/package/gen\b and
+ \b$INSTALLROOT/lib/package/gen\b. \apackage\a\b.ver\b contains one line
+ consisting of \apackage version release\a \b1\b for the most recent
+ instance of \apackage\a read into \b$PACKAGEROOT\b, where \apackage\a
+ is the package name, \aversion\a is the \aYYYY-MM-DD\a base version,
+ and \arelease\a is \aversion\a for the base release or \aYYYY-MM-DD\a
+ for delta releases. \apackage\a\b.req\b contains *\b.ver\b entries for
+ the packages required by \apackage\a, except that the fourth field is
+ \b0\b instead of \b1\b. All packages except \bINIT\b require the
+ \bINIT\b package. A simple sort of \apackage\a\b.pkg\b and *\b.ver\b
+ determines if the required package have been read in. Finally,
+ \apackage\a\b.README\b and \apackage\a\a.html\b contain the README text
+ for \apackage\a and all its components. Included are all changes added
+ to the component \bRELEASE\b, \bCHANGES\b or \bChangeLog\b files dated
+ since the two most recent base releases. Component \bRELEASE\b files
+ contain tag lines of the form [\aYY\a]]\aYY-MM-DD\a [ \atext\a ]] (or
+ \bdate\b(1) format dates) followed by README text, in reverse
+ chronological order (newer entries at the top of the file.) \bpackage
+ release\b lists this information, and \bpackage contents ...\b lists
+ the descriptions and components.]
+[+?\b$HOSTYPE\b names the current binary architecture and is determined
+ by the output of \bpackage\b (no arguments.) The \b$HOSTTYPE\b naming
+ scheme is used to separate incompatible executable and object formats.
+ All architecture specific binaries are placed under \b$INSTALLROOT\b
+ (\b$PACKAGEROOT/arch/$HOSTTYPE\b.) There are a few places that match
+ against \b$HOSTTYPE\b when making binaries; these are limited to
+ makefile compiler workarounds, e.g., if \b$HOSTTYPE\b matches \bhp.*\b
+ then turn off the optimizer for these objects. All other architecture
+ dependent logic is handled either by the \bast\b \biffe\b(1) command or
+ by component specific configure scripts. Explicit \b$HOSTYPE\b
+ values matching *,*cc*[,-*,...]] optionally set the default \bCC\b and
+ \bCCFLAGS\b. This is handy for build farms that support different
+ compilers on the same architecture.]
+[+?Each component contains an \bast\b \bnmake\b(1) makefile (either
+ \bNmakefile\b or \bMakefile\b) and a \bMAM\b (make abstract machine)
+ file (\bMamfile\b.) A Mamfile contains a portable makefile description
+ that is used by \bmamake\b(1) to simulate \bnmake\b. Currently there is
+ no support for old-make/gnu-make makefiles; if the binaries are just
+ being built then \bmamake\b will suffice; if source or makefile
+ modifications are anticipated then \bnmake\b (in the \bast-base\b
+ package) should be used. Mamfiles are automatically generated by
+ \bpackage write\b.]
+[+?Most component C source is prototyped. If \b$CC\b (default value
+ \bcc\b) is not a prototyping C compiler then \bpackage make\b runs
+ \bproto\b(1) on portions of the \b$PACKAGEROOT/src\b tree and places
+ the converted output files in the \b$PACKAGEROOT/proto/src\b tree.
+ Converted files are then viewpathed over the original source.
+ \bproto\b(1) converts an ANSI C subset to code that is compatible with
+ K&R, ANSI, and C++ dialects.]
+[+?All scripts and commands under \b$PACKAGEROOT\b use \b$PATH\b
+ relative pathnames (via the \bast\b \bpathpath\b(3) function); there
+ are no imbedded absolute pathnames. This means that binaries generated
+ under \b$PACKAGEROOT\b may be copied to a different root; users need
+ only change their \b$PATH\b variable to reference the new installation
+ root \bbin\b directory. \bpackage install\b installs binary packages in
+ a new \b$INSTALLROOT\b.]
+
+[ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]
+
+[+SEE ALSO?\bautoconfig\b(1), \bcksum\b(1), \bexecrate\b(1), \bexpmake\b(1),
+ \bgzip\b(1), \bmake\b(1), \bmamake\b(1), \bnmake\b(1), \bpax\b(1),
+ \bpkgadd\b(1), \bpkgmk\b(1), \bproto\b(1), \bratz\b(1), \brpm\b(1),
+ \bsh\b(1), \btar\b(1), \boptget\b(3)]
+'
+ case $* in
+ help) set -- --man ;;
+ esac
+ while getopts -a $command "$USAGE" OPT
+ do :
+ done
+ shift $OPTIND-1
+ ;;
+esac
+
+# check the args
+
+case $AR in
+'') AR=ar ;;
+esac
+case $CC in
+'') CC=cc ;;
+esac
+case $LD in
+'') LD=ld ;;
+esac
+case $NM in
+'') NM=nm ;;
+esac
+
+action=
+admin_all=1
+admin_on=
+authorize=
+bit=
+exec=
+flat=0
+force=0
+global=
+hi=
+html=0
+ifs=${IFS-'
+ '}
+lo=
+make=
+makeflags='-k -K'
+nmakeflags=
+nmakesep=
+nl="
+"
+noexec=
+only=0
+output=
+package_src=
+password=
+quiet=0
+show=:
+tab=" "
+verbose=0
+AUTHORIZE=
+DEBUG=
+HURL=
+PROTOROOT=-
+SHELLMAGIC=-
+
+unset FIGNORE BINDIR DLLDIR ETCDIR FUNDIR INCLUDEDIR LIBDIR LOCALEDIR MANDIR SHAREDIR 2>/dev/null || true
+
+while :
+do case $# in
+ 0) set host type ;;
+ esac
+ case $1 in
+ admin|clean|clobber|contents|copyright|export|host|install|license|list|make|read|regress|release|remove|results|setup|test|update|use|verify|view|write|TEST)
+ action=$1
+ shift
+ break
+ ;;
+ authorize)
+ case $# in
+ 1) echo $command: $1: authorization user name argument expected >&2; exit 1 ;;
+ esac
+ shift
+ authorize=$1
+ shift
+ continue
+ ;;
+ debug|environment)
+ exec=echo make=echo show=echo
+ ;;
+ flat) flat=1
+ ;;
+ force) force=1
+ ;;
+ never) exec=echo noexec=-N
+ ;;
+ only) only=1
+ ;;
+ password)
+ case $# in
+ 1) echo $command: $1: authorization password argument expected >&2; exit 1 ;;
+ esac
+ shift
+ password=$1
+ shift
+ continue
+ ;;
+ quiet) quiet=1
+ ;;
+ show) exec=echo noexec=-n
+ ;;
+ verbose)verbose=1
+ ;;
+ DEBUG) DEBUG=1
+ PS4='+$LINENO:$SECONDS+ '
+ set -x
+ ;;
+ help|HELP|html|man|--[?m]*)
+ case $1 in
+ help) code=0
+ case $2 in
+ '') exec 1>&2 ;;
+ esac
+ ;;
+ html) code=0 html=1
+ ;;
+ *) code=2
+ exec 1>&2
+ ;;
+ esac
+ case $html in
+ 1) bO="<HTML>
+<HEAD>
+<TITLE>$2 package installation instructions</TITLE>
+<HEAD>
+<BODY bgcolor=white link=teal vlink=dimgray>"
+ eO='</BODY>
+</HTML>'
+ bH="<CENTER><H3><FONT face=courier color=red>"
+ eH='</FONT></H3></CENTER>'
+ bP='<P>'
+ bL='<P><TABLE cellpadding=0 cellspacing=2>'
+ bL2='<P><TABLE border=0 cellpadding=0 cellspacing=2>'
+ eL='</TABLE><P>'
+ bT='<TR><TD align=right valign=top><B>'
+ bD='</B></TD><TD align=left>' eD='</TD></TR>'
+ bB='<B>' eB='</B>'
+ bI='<I>' eI='</I>'
+ bX='<PRE>' eX='</PRE>'
+ bF='<TT>' eF='</TT>'
+ Camp='&amp;'
+ Mcurl='<A href=../../man/man1/curl.html>curl</A>(1)'
+ Mdate='<A href=../../man/man1/date.html>date</A>(1)'
+ Mfile='<A href=../../man/man1/file.html>file</A>(1)'
+ Mgunzip='<A href=../../man/man1/gzip.html>gunzip</A>(1)'
+ Mhurl='<A href=../../man/man1/hurl.html>hurl</A>(1)'
+ Mlynx='<A href=../../man/man1/lynx.html>lynx</A>(1)'
+ Mnmake='<A href=../../man/man1/nmake.html>nmake</A>(1)'
+ Mpackage='<A href=../../man/man1/package.html>package</A>(1)'
+ Mproto='<A href=../../man/man1/proto.html>proto</A>(1)'
+ Mratz='<A href=../../man/man1/ratz.html>ratz</A>'
+ Mtar='<A href=../../man/man1/tar.html>tar</A>(1)'
+ Mwget='<A href=../../man/man1/wget.html>wget</A>(1)'
+ ;;
+ *) bO='' eO=''
+ bH='' eH=':'
+ bP=''
+ bL='' eL=''
+ bL2=''
+ bT=' '
+ bD=' ' eD=''
+ bB='' eB=''
+ bI='' eI=''
+ bX='' eX=''
+ bF='"' eF='"'
+ Camp='&'
+ Mcurl='curl(1)'
+ Mdate='date(1)'
+ Mfile='file(1)'
+ Mgunzip='gunzip(1)'
+ Mhurl='hurl(1)'
+ Mlynx='lynx(1)'
+ Mnmake='nmake(1)'
+ Mpackage='package(1)'
+ Mproto='proto(1)'
+ Mratz='ratz'
+ Mtar='tar(1)'
+ Mwget='wget(1)'
+ ;;
+ esac
+ case $2 in
+ binary) echo "${bO}
+${bH}Binary Package Installation Instructions${eH}
+${bL}
+${bT}(1)${bD}Do not install packages as ${bI}root/super-user${eI}. Although some components may
+ have setuid executables, few must be owned by ${bI}root${eI}. These are best
+ changed manually when the security implications are understood.${eD}
+${bT}(2)${bD}Choose a package root directory and cd to it. This will be a local work
+ area for all packages.${eD}
+${bT}(3)${bD}These instructions bypass the ${bI}click to download${eI} package links on the
+ download site. If you already clicked, or if your system does not have
+ ${Mcurl}, ${Mhurl}, ${Mlynx} or ${Mwget} then use the alternate instructions
+ for (3),(4),(5) in plan ${bB}B${eB} below. Plan ${bB}B${eB} installs the ${Mhurl}
+ script which works with ksh and modern bash. The top level URL is:${bX}
+ URL=http://www.research.att.com/sw/download${eX}${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then run:${bX}
+ test -d bin || mkdir bin
+ url=\$URL/package
+ (wget -O bin/package \$url||curl -L \$url||hurl \$url) > bin/package
+ chmod +x bin/package${eX}${eD}
+${bT}(5)${bD}Determine the list of package names you want from the download site, then
+ use the ${Mpackage} command to do the actual download:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ setup binary \$URL ${bI}PACKAGE${eI} ...${eX}
+ (Refer to the ${bB}AUTHORIZATION${eB} paragraph on the main download page for
+ ${bI}NAME${eI}/${bI}PASSWORD${eI} details.) This downloads the closure of the latest
+ binary package(s); covered and up-to-date packages are not downloaded again unless
+ ${bB}package force ...${eB} is specified. Package content is verified using ${bB}${checksum}${eB}.
+ If the package root will contain only one architecture then you can install in ${bB}bin${eB} and
+ ${bB}lib${eB} instead of ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/bin${eB} and ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/lib${eB} by running this
+ instead:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ flat setup binary \$URL ${bB}PACKAGE${eB} ...${eX}
+ To update the same packages from the same URL run:${bX}
+ bin/package setup binary${eX}${eD}
+${bT}(6)${bD}The packaged binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ ${Mfile} and ${Mnmake}, require the path of the bin directory to be
+ exported in ${bB}PATH${eb}.${eD}
+${bT}(7)${bD}You can run the binaries directly from the package root, or you can
+ install them in a public root (requires the ${bI}AT${Camp}T${eI} ${Mnmake} command):${bX}
+ bin/package flat install ${bI}DIRECTORY PACKAGE${eI}${eX}
+ This will install in ${bI}DIRECTORY${eI}${bB}/bin${eB} and ${bI}DIRECTORY${eI}${bB}/lib${eB}. If you want to
+ preserve the ${bB}arch/${eB}${bI}HOSTTYPE${eI} hierarchy under ${bI}DIRECTORY${eI} then omit the
+ ${bB}flat${eB} argument. If you don't have ${Mnmake} then the following will do a
+ flat install:${bX}
+ cd \$INSTALLROOT
+ cp -p -r bin lib include ${bI}DIRECTORY${eI}${eX}${eD}
+${bT}(8)${bD}To summarize, after the first time, the download cycle for the latest
+ binary release is:${bX}
+ bin/package setup binary${eX}${eD}${eL}
+
+${bH}Binary Package Installation Instructions -- Plan B${eH}
+${bL}
+${bT}(3)${bD}Create the subdirectory ${bB}lib/package/tgz${eB} and download all package archives
+ into that directory.${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then manually read the ${bB}INIT${eB}
+ binary package:${bX}
+ gunzip < lib/package/tgz/INIT.${bI}YYYY-MM-DD.HOSTTYPE${eI}.tgz |
+ ${TAR} ${TARFLAGS}f -${eX}
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ ${TAR} ${TARFLAGS}f -${eX} lib/package/tgz/INIT.${bI}YYYY-MM-DD.HOSTTYPE${eI}.tgz
+ If your system does not have ${Mtar} or ${Mgunzip} then download the ${Mratz}
+ binary package:${bX}
+ mkdir bin
+ cp lib/package/tgz/ratz.${bI}YYYY-MM-DD.HOSTTYPE${eI}.exe bin/ratz
+ chmod +x bin/ratz
+ bin/ratz -lm < lib/package/tgz/INIT.${bI}YYYY-MM-DD/HOSTTYPE${eI}.tgz
+${bT}(5)${bD}Read all unread package archive(s):${bX}
+ bin/package read${eX}
+ Both source and binary packages will be read by this step.${eD}${eL}${eO}"
+ ;;
+ intro) echo "${bO}
+${bH}Package Hierarchy Details${eH}
+${bP}
+The package directory hierarchy is rooted at ${bB}\$PACKAGEROOT${eB}. All source and
+binaries reside under this tree. A two level viewpath is used to separate
+source and binaries. The top view is architecture specific, the bottom view
+is shared source. All building is done in the architecture specific view;
+no source view files are intentionally changed. This means that many
+different binary architectures can be made from a single copy of the source.
+${bP}
+Each package contains one or more components. Component source for the ${bI}FOO${eI}
+command is in ${bB}\$PACKAGEROOT/src/cmd/${eB}${bI}FOO${eI}, and source for the ${bI}BAR${eI} library is
+in ${bB}\$PACKAGEROOT/src/lib/lib${eB}${bI}BAR${eI}. This naming is for convenience only; the
+underlying makefiles handle inter-component build order. The ${bB}INIT${eB} component,
+which contains generic package support files, is always made first, then the
+components named ${bB}INIT${eB}*, then the order determined by the closure of component
+makefile dependencies.
+${bP}
+${bB}\$PACKAGEROOT/lib/package${eB} contains package specific files. The package naming
+convention is ${bI}GROUP${eI}[${bI}-PART${eI}]; e.g., ${bB}ast-base${eB}, ${bB}gnu-fileutils${eB}. The *${bB}.pkg${eB} files
+are ${bB}ast${eB} ${Mnmake} makefiles that contain the package name, package components,
+references to other packages, and a short package description. *${bB}.pkg${eB} files
+are used by ${bF}package write${eF} to generate new source and binary packages.
+${bP}
+${bB}\$PACKAGEROOT/lib/package/${eB}${bI}GROUP${eI}${bB}.lic${eB} files contain license information that
+is used by the ${bB}ast${eB} ${Mproto} and ${Mnmake} commands to generate source and
+binary license strings. ${bI}GROUP${eI} is determined by the first ${bB}:PACKAGE:${eB} operator
+name listed in the component ${bB}nmake${eB} makefile. ${bI}GROUP${eI}${bB}.lic${eB} files are part of the
+licensing documentation. Each component may have its own ${bB}LICENSE${eB} file that
+overrides the ${bI}GROUP${eI}${bB}.lic${eB} file. The full text of the licenses are in the
+${bB}\$PACKAGEROOT/lib/package/LICENSES${eB} and ${bB}\$INSTALLROOT/lib/package/LICENSES${eB}
+directories.
+${bP}
+A few files are generated in ${bB}\$PACKAGEROOT/lib/package/gen${eB} and
+${bB}\$INSTALLROOT/lib/package/gen${eB}. ${bI}PACKAGE${eI}${bB}.ver${eB} contains one line consisting of${bX}
+ ${bI}PACKAGE VERSION RELEASE${eI} 1${eX}
+for the most recent instance of ${bI}PACKAGE${eI} read into ${bB}\$PACKAGEROOT${eB}, where
+${bI}PACKAGE${eI} is the package name, ${bI}VERSION${eI} is the ${bI}YYYY-MM-DD${eI} base version,
+and ${bI}RELEASE${eI} is ${bI}VERSION${eI} for the base release or ${bI}YYYY-MM-DD${eI} for delta releases.
+${bI}PACKAGE${eI}${bB}.req${eB} contains *${bB}.ver${eB} entries for the packages required by
+${bI}PACKAGE${eI}, except that the fourth field is 0 instead of 1. All packages
+except ${bB}INIT${eB} and ${Mratz} require the ${bB}INIT${eB} package. A simple sort of ${bI}PACKAGE${eI}${bB}.pkg${eB}
+and *${bB}.ver${eB} determines if the required package have been read in. Finally,
+${bI}PACKAGE${eI}${bB}.README${eB} contains the ${bB}README${eB} text for ${bI}PACKAGE${eI} and all its
+components. Included are all changes added to the component ${bB}RELEASE${eB},
+${bB}CHANGES${eB} or ${bB}ChangeLog${eB} files dated since the two most recent base
+releases. Component ${bB}RELEASE${eB} files contain tag lines of the form
+[${bI}CC${eI}]${bI}YY-MM-DD${eI} [ ${bI}TEXT${eI} ] (or ${Mdate} format dates) followed by README
+text, in reverse chronological order (newer entries at the top of the
+file.) ${bF}package release${eF} generates this information, and
+${bF}package contents ...${eF} lists the descriptions and components.
+${bP}
+${bB}\$HOSTYPE${eB} names the current binary architecture and is determined by the
+output of ${bF}package${eF} (no arguments.) The ${bB}\$HOSTTYPE${eB} naming scheme is used
+to separate incompatible executable and object formats. All architecture
+specific binaries are placed under ${bB}\$INSTALLROOT${eB} (${bB}\$PACKAGEROOT/arch/\$HOSTTYPE${eB}.)
+There are a few places that match against ${bB}\$HOSTTYPE${eB} when making binaries; these
+are limited to makefile compiler workarounds, e.g., if ${bB}\$HOSTTYPE${eB} matches
+'hp.*' then turn off the optimizer for these objects. All other architecture
+dependent logic is handled either by ${bB}\$INSTALLROOT/bin/iffe${eB} or by component
+specific configure scripts. Explicit ${bB}\$HOSTYPE${eB} values matching *,*cc*[,-*,...]
+optionally set the default ${bB}CC${eB} and ${bB}CCFLAGS${eB}. This is handy for build
+farms that support different compilers on the same architecture.
+${bP}
+Each component contains an ${bB}ast${eB} ${Mnmake} makefile (either ${bB}Nmakefile${eB} or ${bB}Makefile${eB})
+and a ${bI}MAM${eI} (make abstract machine) file (${bB}Mamfile${eB}.) A Mamfile contains a portable
+makefile description that is used by ${bB}\$INSTALLROOT/bin/mamake${eB} to simulate
+${bB}nmake${eB}. Currently there is no support for old-make/gnu-make makefiles; if
+the binaries are just being built then ${bB}mamake${eB} will suffice; if source or
+makefile modifications are anticipated then ${bB}nmake${eB} (from the ${bB}ast-open${eB} or
+${bB}ast-base${eB} package) should be used. Mamfiles are automatically generated by
+${bF}package write${eF}.
+${bP}
+Most component C source is prototyped. If ${bB}\$CC${eB} (default value ${bB}cc${eB}) is not a
+prototyping C compiler then ${bF}package make${eF} runs ${Mproto} on portions of the
+${bB}\$PACKAGEROOT/src${eB} tree and places the converted output files in the
+${bB}\$PACKAGEROOT/proto/src${eB} tree. Converted files are then viewpathed over the
+original source. The ${bB}ast${eB} ${Mproto} command converts an ANSI C subset to code
+that is compatible with K&R, ANSI, and C++ dialects.
+${bP}
+All scripts and commands under ${bB}\$PACKAGEROOT${eB} use ${bB}\$PATH${eB} relative pathnames;
+there are no imbedded absolute pathnames. This means that binaries generated
+under ${bB}\$PACKAGEROOT${eB} may be copied to a different root; users need only change
+their ${bB}\$PATH${eB} variable to reference the new instalation root bin directory.
+${bF}package install${eF} installs binary packages in a new ${bB}\$INSTALLROOT${eB}.
+${eO}"
+ ;;
+ source) echo "${bO}
+${bH}Source Package Installation Instructions${eH}
+${bL}
+${bT}(1)${bD}Do not install packages as ${bI}root/super-user${eI}. Although some components may
+ have setuid executables, few must be owned by ${bI}root${eI}. These are best
+ changed manually when the security implications are understood.${eD}
+${bT}(2)${bD}Choose a package root directory and cd to it. This will be a local work
+ area for all packages.
+${bT}(3)${bD}These instructions bypass the ${bI}click to download${eI} package links on the
+ download site. If you already clicked, or if your system does not have
+ ${Mcurl}, ${Mhurl}, ${Mlynx} or ${Mwget} then use the alternate instructions
+ for (3),(4),(5) in plan ${bB}B${eB} below. Plan ${bB}B${eB} installs the ${Mhurl}
+ script which works with ksh and modern bash. The top level URL is:${bX}
+ URL=http://www.research.att.com/sw/download${eX}${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then run:${bX}
+ test -d bin || mkdir bin
+ url=\$URL/package
+ (wget -O bin/package \$url||curl -L \$url||hurl \$url) > bin/package
+ chmod +x bin/package${eX}${eD}
+${bT}(5)${bD}Determine the list of package names you want from the download site, then
+ use the ${Mpackage} command to do the actual download:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ setup source \$URL ${bB}PACKAGE${eB} ...${eX}
+ (Refer to the ${bB}AUTHORIZATION${eB} paragraph on the main download page for
+ ${bI}NAME${eI}/${bI}PASSWORD${eI} details.) This downloads the closure of the latest
+ source package(s); covered and up-to-date packages are not downloaded again unless
+ ${bB}package force ...${eB} is specified. Package content is verified using ${bB}${checksum}${eB}.
+ If the package root will contain only one architecture then you can install in ${bB}bin${eB} and
+ ${bB}lib${eB} instead of ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/bin${eB} and ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/lib${eB} by running this
+ instead:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ flat setup source \$URL ${bB}PACKAGE${eB} ...${eX}
+ To update the same packages from the same URL run:${bX}
+ bin/package setup source${eX}${eD}
+${bT}(6)${bD}Build and install; all generated files are placed under ${bB}arch/${eB}${bI}HOSTTYPE${eI}
+ (${bB}\$INSTALLROOT${eB}), where ${bI}HOSTTYPE${eI} is the output of ${bB}bin/package${eB} (with no
+ arguments.) ${bI}name=value${eI} arguments are supported; ${bB}CC${eB} and ${bB}debug=1${eB} (compile
+ with -g instead of -O) are likely candidates. The output is written to
+ the terminal and captured in ${bB}\$INSTALLROOT/lib/package/gen/make.out${eB}:${bX}
+ bin/package make${eX}${eD}
+${bT}(7)${bD}List make results and interesting errors:${bX}
+ bin/package results${eX}
+ Run the regression tests:${bX}
+ bin/package test${eX}
+ List test results and errors:${bX}
+ bin/package results test${eX}${eD}
+${bT}(8)${bD}The generated binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ ${Mfile} and ${Mnmake}, require the path of the bin directory to be
+ exported in ${bB}PATH${eb}.${eD}
+${bT}(9)${bD}You can run the binaries directly from the package root, or you can
+ install them in a public root after you are satisfied with the make and
+ test actions (requires the ${bI}AT${Camp}T${eI} ${Mnmake} command):${bX}
+ bin/package flat install ${bI}DIRECTORY PACKAGE${eI}${eX}
+ This will install in ${bI}DIRECTORY${eI}${bB}/bin${eB} and ${bI}DIRECTORY${eI}${bB}/lib${eB}. If you want to
+ preserve the ${bB}arch/${eB}${bI}HOSTTYPE${eI} hierarchy under ${bI}DIRECTORY${eI} then omit the
+ ${bB}flat${eB} argument. If you don't have ${Mnmake} then the following will do a
+ flat install:${bX}
+ cd \$INSTALLROOT
+ cp -p -r bin lib include ${bI}DIRECTORY${eI}${eX}${eD}
+${bT}(10)${bD}To summarize, after the first time the download, build, and test cycle
+ for the latest source release is:${bX}
+ bin/package setup source
+ bin/package make
+ bin/package test${eX}${eD}${eL}
+
+${bH}Source Package Installation Instructions -- Plan B${eH}
+${bL}
+${bT}(3)${bD}Create the subdirectory ${bB}lib/package/tgz${eB} and download all package archives
+ into that directory.${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then manually read the ${bB}INIT${eB}
+ source package:${bX}
+ gunzip < lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz | ${TAR} ${TARFLAGS}f -${eX}
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ ${TAR} ${TARFLAGS}f -${eX} lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz
+ If your system does not have ${Mtar} or ${Mgunzip} then download the ${Mratz}
+ source package, compile it, and manually read the ${bB}INIT${eB}
+ source package:${bX}
+ mkdir bin
+ cp lib/package/tgz/ratz.${bI}YYYY-MM-DD${eI}.c lib/package/tgz/ratz.c
+ cc -o bin/ratz lib/package/tgz/ratz.c
+ bin/ratz -lm < lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz
+${bT}(5)${bD}Read all unread package archive(s):${bX}
+ bin/package read${eX}
+ Both source and binary packages will be read by this step.${eD}${eL}${eO}"
+ ;;
+ *) echo "Usage: $command [ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]
+
+ The $command command controls source and binary packages. It must be run
+ within the package root directory tree. See \"$command help intro\" for
+ details. In the following, PACKAGE names either a package or a component
+ within a package; if omitted, all packages are operated on. The default
+ action is \"host type\".
+
+ qualifier:
+ authorize NAME Remote authorization name or license acceptance phrase.
+ debug|environment Show environment and actions; do not execute.
+ flat Collapse \$INSTALLROOT { bin fun include lib } onto \$PACKAGEROOT.
+ force Force the action to override saved state.
+ never Run make -N; otherwise show other actions.
+ only Only operate on the specified packages.
+ password PASSWORD Remote authorization or license acceptance password.
+ quiet Do not list captured make and test action output.
+ show Run make -n; otherwise show other actions.
+ DEBUG Trace the package script actions in detail for debugging.
+ action:
+ admin [ all ] [ db FILE ] [ on PATTERN ] [ action ... ]
+ Apply ACTION ... to the hosts listed in FILE. If FILE is
+ omitted then "admin.db" is assumed. The caller must have rcp(1)
+ and rsh(1) or scp(1) and ssh(1) access to the hosts. Output
+ for the action is saved per-host in ACTION.log/HOST. Logs
+ can be viewed by \"package admin [on HOST] results [ACTION]\".
+ By default only local PACKAGEROOT hosts are selected from FILE;
+ \"all\" selects all hosts. \"on PATTERN\" selects only
+ hosts matching the | separated PATTERN. FILE contains four
+ types of lines. Blank lines and lines beginning with # are
+ ignored. Lines starting with id=value are variable assignments.
+ Set admin_ping to local conventions if \"$admin_ping\" fails.
+ If a package list is not specified on the command line the
+ action applies to all packages; a variable assigment
+ package=list applies action to the packages in list for
+ subsequent hosts in FILE. The remaining line type is a host
+ description consisting of 6 tab separated fields. The first 3
+ are mandatory; the remaining 3 are updated by the admin action:
+ hosttype
+ The host type as reported by package.
+ [user@]host
+ The host name and optionally user name for rcp(1)
+ and rsh(1) access.
+ [remote:[[master]:]]PACKAGEROOT
+ The absolute remote package root directory and
+ optionally the remote prorocol (rsh or ssh) if
+ the directory is on a different server than the
+ master package root directory. If
+ lib/package/admin/$admin_env exists under
+ this directory then it is sourced by sh(1)
+ before ACTION is done. If this field begins with -
+ then the host is ignored. If this field contains
+ : then ditto(1) is used to sync the remote src
+ directory hierarchy to the local one. If [master]:
+ is specified then the sync is deferred to the
+ master host. If master is omitted (two :) then
+ the sync is disabled. These directories must exist
+ on the remote side: lib/package, src/cmd, src/lib.
+ date YYMMDD of the last action.
+ date Elapsed wall time of the last action.
+ M T W The admin action make, test and write action error
+ counts. A non-numeric value in any of these fields
+ disables the corresponding action.
+ clean | clobber
+ Delete the arch/HOSTTYPE hierarchy; this deletes all generated
+ files and directories for HOSTTYPE. The heirarchy can be rebuilt
+ by package make.]
+ contents [ package ... ]
+ List description and components for PACKAGE on the standard
+ output.
+ copyright [ package ... ]
+ List the general copyright notice(s) for PACKAGE on the
+ standard output. Note that individual components in PACKAGE
+ may contain additional or replacement notices.
+ export [ VARIABLE ... ]
+ List NAME=VALUE for each VARIABLE, one per line. If the
+ \"only\" attribute is specified then only the variable
+ values are listed. If no variables are specified then
+ $env are assumed.
+ help [ ACTION ]
+ Display help text on the standard error [ standard output
+ for ACTION ].
+ host [ canon cpu name rating type ... ]
+ List architecture/implementation dependent host information
+ on the standard output. type is listed if no attributes are
+ specified. Information is listed on a single line in attributes
+ order. The attributes are:
+ canon The next argument is a host type name to be
+ converted to package syntax.
+ cpu The number of cpus; 1 if the host is not a
+ multiprocessor.
+ name The host name.
+ rating The cpu rating in pseudo mips; the value is useful
+ useful only in comparisons with rating values of
+ other hosts. Other than a vax rating fixed at 1,
+ ratings can vary wildly but consistently from
+ vendor mips ratings. cc(1) may be required to
+ determine the rating.
+ type The host type, usually of the form
+ vendor.architecture, with an optional trailing
+ -version. The main theme is that type names within
+ a family of architectures are named in a similar,
+ predictable style. Os point release information is
+ avoided as much as possible, but vendor resistance
+ to release incompatibilities has for the most part
+ been futile.
+ html [ ACTION ]
+ Display html help text on the standard error [ standard output
+ for ACTION ].
+ install [ ARCHITECTURE ... ] DIR [ PACKAGE ... ]
+ Copy the package binary hierarchy to DIR. If ARCHITECTURE is
+ omitted then all architectures are installed. If the \"flat\"
+ attribute is specified then exactly one ARCHITECTURE must be
+ specified; this architecture will be installed in DIR without
+ the \"arch/HOSTTYPE\" directory prefixes. Otherwise each
+ architecture will be installed in a separate \"arch/HOSTTYPE\"
+ subdirectory of DIR. The ARCHITECTURE - names the current
+ architecture. DIR must be an existing directory. If PACKAGE
+ is omitted then all binary packages are installed. This action
+ requires nmake.
+ license [ package ... ]
+ List the source license(s) for PACKAGE on the standard output.
+ Note that individual components in PACKAGE may contain
+ additional or replacement licenses.
+ list [ PACKAGE ... ]
+ List the name, version and prerequisites for PACKAGE on the
+ standard output.
+ make [ PACKAGE ] [ OPTION ... ] [ TARGET ... ]
+ Build and install. The default TARGET is install, which
+ makes and installs all packages. If the standard output
+ is a terminal then the output is also captured in
+ \$INSTALLROOT/lib/package/gen/make.out. The build is done
+ in the \$INSTALLROOT directory tree viewpathed on top of
+ the \$PACKAGEROOT directory tree. If \"flat\" is specified then
+ the \$INSTALLROOT { bin fun include lib } directories are
+ linked to the same directories in the package root. Only
+ one architecture may be flat. Leaf directory names matching
+ the |-separated shell pattern \$MAKESKIP are ignored. The
+ view action is done before making. OPTION operands are
+ passed to the underlying make command.
+ read [ package ... | archive ... ]
+ Read the named package archive(s). Must be run from the
+ package root directory. Archives are searched for in .
+ and lib/package/tgz. Each package is read only once. The
+ file lib/package/tgz/package[.type].tim tracks the read time.
+ See the write action for archive naming conventions. Text
+ file archive member are assumed to be ASCII or UTF-8 encoded.
+ regress diff(1) the current and previous package test results.
+ release [ [CC]YY-MM-DD [ [cc]yy-mm-dd ] ] [ package ]
+ Display recent changes since [CC]YY-MM-DD (up to [cc]yy-mm-dd),
+ where - means lowest (or highest.) If no dates are specified
+ then changes for the last 4 months are listed. PACKAGE may
+ be a package or component name.
+ remove PACKAGE
+ Remove files installed for PACKAGE.
+ results [ path ] [ old ] [ make | test ]
+ List results and interesting messages captured by the most
+ recent make (default), test or write action. old specifies the
+ previous results, if any (current and previous results are
+ retained.) $HOME/.pkgresults, if it exists, must contain an
+ egrep(1) expression of result lines to be ignored. failed lists
+ failures only and path lists the results file path only.
+ setup [ beta ] [ binary ] [ source ] [ ARCHITECTURE ... ] [ URL ] [ PACKAGE ... ]
+ The action initializes the current directory as a package root,
+ runs the update action to download new or out of date packages,
+ and runs the read action on those packages. If \"flat\" is
+ specified then the \$INSTALLROOT { bin fun include lib }
+ directories are linked to the same directories in the package
+ root. Only one architecture may be flat. See the update and
+ read actions for argument details.
+ test [ PACKAGE ]
+ Run the regression tests for PACKAGE. If the standard output
+ is a terminal then the output is also captured in
+ \$INSTALLROOT/lib/package/gen/test.out. In general a package
+ must be made before it can be tested. Components tested with
+ the \bregress\b(1) command require \bksh93\b. If only is
+ also specified then only the listed package components are
+ tested, otherwise the closure of the components is tested.
+ update [ beta ] [ binary ] [ source ] [ ARCHITECTURE ... ] [ URL ] [ PACKAGE ... ]
+ Download the latest release of the selected and required
+ packages from URL (e.g.,
+ http://www.research.att.com/sw/download) into the directory
+ \$PACKAGEROOT/lib/package/tgz. beta acesses beta packages;
+ download these at your own risk. If ARCHITECTURE is omitted
+ then only architectures already present in the tgz directory
+ will be downloaded. If ARCHITECTURE is - then all posted
+ architectures will be downloaded. If URL matches *.url then
+ it is interpreted as a file containing shell variable
+ assignments for url, authorize and password. If URL is
+ omitted then the definitions for url, authorize and password
+ in \$PACKAGEROOT/lib/package/tgz/$default_url, if it exists,
+ are used. If \$PACKAGEROOT/lib/package/tgz/$default_url does
+ not exist then it is initialized with the current url,
+ authorize and password values and read permission for the
+ current user only. If PACKAGE is omitted then only
+ packages already present in the tgz directory will be
+ downloaded. If PACKAGE is - then all posted packages will be
+ downloaded. If source and binary are omitted then both source
+ and binary packages will be downloaded. If \bonly\b is
+ specified then only the named packages are updated; otherwise
+ the closure of required packages is updated. This action
+ requires wget(1), lynx(1), curl(1) or a shell that supports
+ io to /dev/tcp/HOST/PORT.
+ use [ uid | PACKAGE | . [ 32 | 64 ] | 32 | 64 | - ] [ COMMAND ... ]
+ Run COMMAND or an interactive shell if COMMAND is omitted, with
+ the environment initialized for using the package (can you say
+ shared library without cussing?) If uid or PACKAGE or . is
+ specified then it is used to determine a \$PACKAGEROOT,
+ possibly different from the current directory. For example, to
+ try out bozo's package: \"package use bozo\". In this case the
+ command may be run from any directory. If the file
+ \$INSTALLROOT/lib/package/profile is readable then it is
+ sourced to initialize the environment. 32 or 64 implies
+ \$PACKAGEROOT of . and specifies the target architecture word
+ size (which may be silently ignored.)
+ verify [ PACKAGE ]
+ Verify installed binary files against the checksum files in
+ \$INSTALLROOT/lib/package/gen/*.sum. The checksum files contain
+ mode, user and group information. If the checksum matches
+ for a given file then the mode, user and group are changed
+ as necessary to match the checksum entry. A warning is printed
+ on the standard error for each mismatch. Requires the ast
+ package cksum(1) command.
+ view
+ Initialize the architecture specific viewpath hierarchy. The
+ make action implicitly calls this action. If \"flat\" is specified
+ then the \$INSTALLROOT { bin fun include lib } directories are
+ linked to the same directories in the package root. Only one
+ architecture may be flat.
+ write [closure] [cyg|exp|lcl|pkg|rpm|tgz|tst] [base|delta]
+ [binary|runtime|source] PACKAGE
+ Write a package archive for PACKAGE. All work is done in the
+ \$PACKAGEROOT/lib/package directory. FORMAT-specific files
+ are placed in the FORMAT subdirectory. A PACKAGE[.TYPE].tim
+ file in this directory tracksthe write time and prevents a
+ package from being read in the same root it was written. If
+ more than one file is generated for a particular FORMAT then
+ those files are placed in the FORMAT/PACKAGE subdirectory.
+ File names in the FORMAT subdirectory will contain the package
+ name, a YYYY-MM-DD date, and for binary packages, HOSTTYPE.
+ If PACKAGE is omitted then an ordered list of previously
+ written packages is generated. If \"only\" is specified then
+ only the named packages will be written; otherwise
+ prerequisite packages are written first. Package components
+ must be listed in PACKAGE.pkg. FORMAT may be one of:
+ cyg generate a cygwin package
+ exp generate an exptools(1) maintainer source archive
+ and NPD file in the exp subdirectory, suitable for
+ expmake(1); support files are placed in the
+ exp/PACKAGE subdirectory
+ lcl generate a package archive or delta in the lcl
+ subdirectory, suitable for restoration into the
+ primary source tree (no source licence annotation)
+ pkg generate a pkgmk(1) package, suitable for pkgadd(1)
+ rpm generate an rpm(1) package
+ tgz generate a gzip(1) tar(1) package archive; this is
+ the default
+ tst generate tgz FORMAT package archive in the tst
+ subdirectory; version state files are not updated
+ The package type must be one of source, binary or runtime.
+ A source package contains the source needed to build the
+ corresponding binary package. A binary package includes the
+ libraries and headers needed for compiling and linking
+ against the public interfaces. A runtime package contains
+ the commands and required dynamic libraries. A package may
+ be either a base or delta. A base package contains a
+ complete copy of all components. A delta package contains
+ only changes from a previous base package. Delta recipients
+ must have the ast pax(1) command (in the ast-base package.)
+ If neither base nor delta is specified, then the current
+ base is overwritten if there are no deltas referring to the
+ current base. Only the tgz and lcl formats support delta.
+ If base is specified then a new base and two delta archives
+ are generated: one delta to generate the new base from the
+ old, and one delta to generate the old base from the new;
+ the old base is then removed. If delta is specified then a
+ new delta referring to the current base is written.
+ package.pkg may reference other packages. By default a
+ pointer to those packages is written. The recipient package
+ read will then check that all required packages have been
+ downloaded. If closure is specified then the components for
+ all package references are included in the generated
+ package. This may be useful for lcl and versioning. All
+ formats but lcl annotate each source file (not already
+ annotated) with a license comment as it is written to the
+ package archive using proto(1).
+ name=value:
+ variable definition: typically CC=cc or CCFLAGS=-g."
+ ;;
+ esac
+ exit $code
+ ;;
+ *=*) set DEFAULT host type "$@"
+ ;;
+ *) echo "Usage: $command [ options ] [ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]" >&2
+ exit 2
+ ;;
+ esac
+ global="$global $1"
+ shift
+done
+
+# gather HOSTTYPE *,* options
+# ,*cc*,-*,... set CC and CCFLAGS
+
+hostopts()
+{
+ _ifs_=$IFS
+ IFS=,
+ set '' $HOSTTYPE
+ IFS=$_ifs_
+ shift
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ shift
+ case $1 in
+ *cc*) CC=$1
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ case $2 in
+ -*) case $assign_CCFLAGS in
+ ?*) assign_CCFLAGS="$assign_CCFLAGS " ;;
+ esac
+ assign_CCFLAGS="$assign_CCFLAGS$2"
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ done
+}
+
+# collect command line targets and definitions
+
+case $_PACKAGE_HOSTTYPE_ in
+?*) HOSTTYPE=$_PACKAGE_HOSTTYPE_
+ KEEP_HOSTTYPE=1
+ ;;
+*) KEEP_HOSTTYPE=0
+ ;;
+esac
+KEEP_PACKAGEROOT=0
+KEEP_SHELL=0
+USER_VPATH=
+args=
+assign=
+assign_CCFLAGS=
+for i
+do case $i in
+ *:*=*) args="$args $i"
+ continue
+ ;;
+ *=*) eval `echo ' ' "$i" | sed 's,^[ ]*\([^=]*\)=\(.*\),n=\1 v='\''\2'\'','`
+ ;;
+ esac
+ case $i in
+ AR=*|LD=*|NM=*)
+ assign="$assign $n='$v'"
+ eval $n='$'v
+ ;;
+ CC=*) eval $n='$'v
+ ;;
+ CCFLAGS=*)
+ eval $n='$'v
+ assign_CCFLAGS="CCFLAGS=\"\$CCFLAGS\""
+ ;;
+ HOSTTYPE=*)
+ eval $n='$'v
+ case $HOSTTYPE in
+ ?*) KEEP_HOSTTYPE=1 ;;
+ esac
+ ;;
+ HURL=*) eval $n='$'v
+ ;;
+ PACKAGEROOT=*)
+ eval $n='$'v
+ case $PACKAGEROOT in
+ ?*) KEEP_PACKAGEROOT=1 ;;
+ esac
+ ;;
+ SHELL=*)eval $n='$'v
+ case $SHELL in
+ ?*) KEEP_SHELL=1 ;;
+ esac
+ ;;
+ TAR=*) eval $n='$'v
+ ;;
+ TARFLAGS=*)
+ eval $n='$'v
+ ;;
+ VPATH=*)eval USER_$n='$'v
+ ;;
+ 'debug=1')
+ makeflags="$makeflags --debug-symbols"
+ ;;
+ 'strip=1')
+ makeflags="$makeflags --strip-symbols"
+ ;;
+ *=*) assign="$assign $n='$v'"
+ ;;
+ *) args="$args $i"
+ ;;
+ esac
+done
+case $HOSTTYPE in
+*,*) hostopts $HOSTTYPE ;;
+esac
+case $assign_CCFLAGS in
+?*) assign="$assign $assign_CCFLAGS"
+esac
+case $CC in
+''|cc) ;;
+*) export CC ;;
+esac
+
+# grab action specific args
+
+case $action in
+admin) while :
+ do case $# in
+ 0) set list
+ break
+ ;;
+ esac
+ case $1 in
+ all) admin_all=1
+ ;;
+ db) case $# in
+ 1) echo $command: $action: $1: db file argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ admin_db=$1
+ ;;
+ on) case $# in
+ 1) echo $command: $action: $1: host pattern argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ admin_on=$1
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ admin_action=$1
+ admin_args=$*
+ for i
+ do case $i in
+ debug|environment|force|never|only|quiet|show|DEBUG)
+ ;;
+ *) admin_action=$i
+ break
+ ;;
+ esac
+ done
+ ;;
+setup) PACKAGEROOT=${PWD:-`pwd`}
+ export PACKAGEROOT
+ KEEP_PACKAGEROOT=1
+ ;;
+use) case $1 in
+ .|32|64)case $1 in
+ 32|64) bit=$1 ;;
+ esac
+ shift
+
+ # HOSTTYPE specific setup
+
+ case $HOSTTYPE in
+ win32.*)sys=uwin
+ wow=`uname -i`
+ case $bit in
+ 32) case $HOSTTYPE in
+ *-64) HOSTTYPE=${HOSTTYPE%-64} ;;
+ esac
+ case $wow in
+ */32) ;;
+ *) vpath / /$bit ;;
+ esac
+ ;;
+ 64) case $HOSTTYPE in
+ *-64) ;;
+ *) HOSTTYPE=$HOSTTYPE-64 ;;
+ esac
+ case $wow in
+ */32) echo $command: cannot build $bit-bit on $wow $sys >&2; exit 2 ;;
+ *) vpath / /$bit ;;
+ esac
+ ;;
+ esac
+ case $bit in
+ '') PS1="($sys) " ;;
+ *) PS1="($sys-$bit) " ;;
+ esac
+
+ $exec umask 002
+ $exec unset MAKESKIP
+
+ $exec export P=$PWD
+ $exec export A=$P/arch/$HOSTTYPE
+
+ $exec export CDPATH=:..:$A/src/cmd:$A/src/lib:$A/src/uwin:$P/lib/package
+ $exec export INSTALLROOT=$A
+ $exec export PACKAGEROOT=$P
+ $exec export PATH=$A/bin:$P/bin:$PATH
+ $exec export PS1="$PS1"
+ $exec export VPATH=$A:$P
+ $exec export nativepp=/usr/lib
+
+ if test '' != "$INSTALLROOT" -a -d $INSTALLROOT/include/ast
+ then $exec export PACKAGE_ast=$INSTALLROOT
+ elif test -d ${PWD%/*}/ast/arch/$HOSTTYPE
+ then $exec export PACKAGE_ast=${PWD%/*}/ast/arch/$HOSTTYPE
+ fi
+
+ # run the command
+
+ case $# in
+ 0) case $show in
+ ':') $exec exec $SHELL ;;
+ esac
+ ;;
+ *) $exec exec $SHELL -c "$@"
+ ;;
+ esac
+ exit
+ ;;
+ esac
+ PACKAGEROOT=${PWD:-`pwd`}
+ $show export PACKAGEROOT
+ esac
+ ;;
+esac
+
+# true if arg is a valid PACKAGEROOT
+
+packageroot() # dir
+{
+ test -d $1/lib/$command -o -x $1/bin/$command
+}
+
+# true if arg is executable
+
+executable() # [!] command
+{
+ case $1 in
+ '!') test ! -x "$2" -a ! -x "$2.exe"; return ;;
+ *) test -x "$1" -o -x "$1.exe"; return ;;
+ esac
+}
+
+# initialize SHELLMAGIC
+# tangible proof of cygwin's disdain for unix (well, this and execrate)
+
+shellmagic()
+{
+ case $SHELLMAGIC in
+ '') ;;
+ -) if test -f /emx/bin/sh.exe
+ then SHELLMAGIC='#!/emx/bin/sh.exe'$nl
+ elif test -f /bin/env.exe
+ then SHELLMAGIC='#!/bin/env sh'$nl
+ else SHELLMAGIC=
+ fi
+ ;;
+ esac
+}
+
+# true if arg is executable command on $PATH
+
+onpath() # command
+{
+ _onpath_b=$1
+ case $_onpath_b in
+ /*) if executable $_onpath_b
+ then _onpath_=$_onpath_b
+ return 0
+ fi
+ return 1
+ ;;
+ esac
+ IFS=':'
+ set '' $PATH
+ IFS=$ifs
+ shift
+ for _onpath_d
+ do case $_onpath_d in
+ '') _onpath_d=. ;;
+ esac
+ if executable "$_onpath_d/$_onpath_b"
+ then _onpath_=$_onpath_d/$_onpath_b
+ return 0
+ fi
+ done
+ return 1
+}
+
+# true if no nmake or nmake not from AT&T or nmake too old
+
+nonmake() # nmake
+{
+ _nonmake_version=`( $1 -n -f - 'print $(MAKEVERSION:@/.*AT&T.* //:/-//G:@/.* .*/19960101/)' . ) </dev/null 2>/dev/null || echo 19840919`
+ if test $_nonmake_version -lt 20001031
+ then return 0
+ fi
+ return 1
+}
+
+# determine local host attributes
+
+hostinfo() # attribute ...
+{
+ case $DEBUG in
+ 1) set -x ;;
+ esac
+ map=
+ something=
+ path=$PATH
+ for i in $ccs
+ do PATH=$PATH:$i
+ done
+ for i in $use
+ do for j in $org
+ do PATH=$PATH:$i/$j/bin
+ done
+ PATH=$PATH:$i/bin
+ done
+ # LD_LIBRARY_PATH may be out of sync with PATH here
+ case $SED in
+ '') SED=sed
+ $SED 1d < /dev/null > /dev/null 2>&1 ||
+ for dir in /bin /usr/bin
+ do if test -x $dir/$SED
+ then SED=$dir/$SED
+ break
+ fi
+ done
+ TR=tr
+ $TR < /dev/null > /dev/null 2>&1 ||
+ for dir in /bin /usr/bin
+ do if test -x $dir/$TR
+ then TR=$dir/$TR
+ break
+ fi
+ done
+ ;;
+ esac
+ case $PACKAGE_PATH in
+ ?*) for i in `echo $PACKAGE_PATH | $SED 's,:, ,g'`
+ do PATH=$PATH:$i/bin
+ done
+ ;;
+ esac
+
+ # validate the args
+
+ canon=
+ cc=$CC
+ for info
+ do case $canon in
+ -) canon=$info
+ ;;
+ *) case $info in
+ */*|*[cC][cC])
+ cc=$info
+ ;;
+ canon) canon=-
+ something=1
+ ;;
+ cpu|name|rating|type)
+ something=1
+ ;;
+ *) echo "$command: $action: $info: unknown attribute" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $canon in
+ -) echo "$command: $action: canon: host type name expected" >&2
+ exit 1
+ ;;
+ esac
+ case $something in
+ "") set "$@" type ;;
+ esac
+ case $DEBUG in
+ '') exec 9>&2
+ exec 2>/dev/null
+ ;;
+ esac
+
+ # compute the info
+
+ _hostinfo_=
+ for info
+ do
+ case $info in
+ cpu) case $NPROC in
+ [123456789]*)
+ _hostinfo_="$_hostinfo_ $NPROC"
+ continue
+ ;;
+ esac
+ cpu=`grep -ic '^processor[ ][ ]*:[ ]*[0123456789]' /proc/cpuinfo`
+ case $cpu in
+ [123456789]*)
+ _hostinfo_="$_hostinfo_ $cpu"
+ continue
+ ;;
+ esac
+ cpu=1
+ # exact match
+ set \
+ hinv '^Processor [0123456789]' \
+ psrinfo 'on-line' \
+ 'cat /reg/LOCAL_MACHINE/Hardware/Description/System/CentralProcessor' '.' \
+ 'cat /proc/registry/HKEY_LOCAL_MACHINE/Hardware/Description/System/CentralProcessor' '.' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | grep -c "$2"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift
+ done
+ case $cpu in
+ 0|1) set \
+ /bin/mpstat
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ if executable $1
+ then case `$1 | grep -ic '^cpu '` in
+ 1) cpu=`$1 | grep -ic '^ *[0123456789][0123456789]* '`
+ break
+ ;;
+ esac
+ fi
+ shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) # token match
+ set \
+ /usr/kvm/mpstat 'cpu[0123456789]' \
+ /usr/etc/cpustatus 'enable' \
+ /usr/alliant/showsched 'CE' \
+ 'ls /config/hw/system/cpu' 'cpu' \
+ prtconf 'cpu-unit' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | $TR ' ' '
+
+' | grep -c "^$2"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) # special match
+ set \
+ \
+ hinv \
+ '/^[0123456789][0123456789]* .* Processors*$/' \
+ '/[ ].*//' \
+ \
+ /usr/bin/hostinfo \
+ '/^[0123456789][0123456789]* .* physically available\.*$/' \
+ '/[ ].*//' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | $SED -e "${2}!d" -e "s${3}"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift;shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) cpu=`(
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.c <<!
+#include <stdio.h>
+#include <pthread.h>
+int main()
+{
+ printf("%d\n", pthread_num_processors_np());
+ return 0;
+}
+!
+ for o in -lpthread ''
+ do if $CC $o -O -o $tmp.exe $tmp.c $o >/dev/null 2>&1 ||
+ gcc $o -O -o $tmp.exe $tmp.c $o >/dev/null 2>&1
+ then ./$tmp.exe
+ break
+ fi
+ done
+ )`
+ case $cpu in
+ [0123456789]*) ;;
+ *) cpu=1 ;;
+ esac
+ ;;
+ esac
+ _hostinfo_="$_hostinfo_ $cpu"
+ ;;
+ name) _name_=`hostname || uname -n || cat /etc/whoami || echo local`
+ _hostinfo_="$_hostinfo_ $_name_"
+ ;;
+ rating) for rating in `grep -i ^bogomips /proc/cpuinfo 2>/dev/null | $SED -e 's,.*:[ ]*,,' -e 's,\(...*\)\..*,\1,' -e 's,\(\..\).*,\1,'`
+ do case $rating in
+ [0123456789]*) break ;;
+ esac
+ done
+ case $rating in
+ [0123456789]*) ;;
+ *) cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.c <<!
+#include <stdio.h>
+#include <sys/types.h>
+#if TD || TZ
+#include <sys/time.h>
+#else
+extern time_t time();
+#endif
+int main()
+{
+ register unsigned long i;
+ register unsigned long j;
+ register unsigned long k;
+ unsigned long l;
+ unsigned long m;
+ unsigned long t;
+ int x;
+#if TD || TZ
+ struct timeval b;
+ struct timeval e;
+#if TZ
+ struct timezone z;
+#endif
+#endif
+ l = 500;
+ m = 890;
+ x = 0;
+ for (;;)
+ {
+#if TD || TZ
+#if TZ
+ gettimeofday(&b, &z);
+#else
+ gettimeofday(&b);
+#endif
+#else
+ t = (unsigned long)time((time_t*)0);
+#endif
+ k = 0;
+ for (i = 0; i < l; i++)
+ for (j = 0; j < 50000; j++)
+ k += j;
+#if TD || TZ
+#if TZ
+ gettimeofday(&e, &z);
+#else
+ gettimeofday(&e);
+#endif
+ t = (e.tv_sec - b.tv_sec) * 1000 + (e.tv_usec - b.tv_usec) / 1000;
+ if (!x++ && t < 1000)
+ {
+ t = 10000 / t;
+ l = (l * t) / 10;
+ continue;
+ }
+#else
+ t = ((unsigned long)time((time_t*)0) - t) * 1000;
+ if (!x++ && t < 20000)
+ {
+ t = 200000l / t;
+ l = (l * t) / 10;
+ continue;
+ }
+#endif
+#if PR
+ printf("[ k=%lu l=%lu m=%lu t=%lu ] ", k, l, m, t);
+#endif
+ if (t == 0)
+ t = 1;
+ break;
+ }
+ printf("%lu\n", ((l * m) / 10) / t);
+ return k == 0;
+}
+!
+ rating=
+ for o in -DTZ -DTD ''
+ do if $CC $o -O -o $tmp.exe $tmp.c >/dev/null 2>&1 ||
+ gcc $o -O -o $tmp.exe $tmp.c >/dev/null 2>&1
+ then rating=`./$tmp.exe`
+ break
+ fi
+ done
+ case $rating in
+ [0123456789]*) ;;
+ *) rating=1 ;;
+ esac
+ ;;
+ esac
+ _hostinfo_="$_hostinfo_ $rating"
+ ;;
+ type|canon)
+ case $CROSS:$canon in
+ 0:) case $cc in
+ cc) case $KEEP_HOSTTYPE:$HOSTTYPE in
+ 0:?*) if test -d ${PACKAGEROOT:-.}/arch/$HOSTTYPE
+ then KEEP_HOSTTYPE=1
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ case $KEEP_HOSTTYPE in
+ 1) _hostinfo_="$_hostinfo_ $HOSTTYPE"
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ case $cc in
+ /*) a=`$cc -dumpmachine $CCFLAGS 2>/dev/null`
+ case $a in
+ '') case $CCFLAGS in
+ ?*) a=`$cc -dumpmachine 2>/dev/null` ;;
+ esac
+ ;;
+ esac
+ case $a in
+ ''|*' '*|*/*:*)
+ ;;
+ *.*-*) _hostinfo_="$_hostinfo_ $a"
+ continue
+ ;;
+ *-*-*) case $canon in
+ '') canon=$a ;;
+ esac
+ ;;
+ *) _hostinfo_="$_hostinfo_ $a"
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ f=../lib/hostinfo/typemap
+ for i
+ do case $i in
+ "") i=. ;;
+ esac
+ case $canon in
+ '') case $cc in
+ /*|cc) ;;
+ *) if executable $i/$cc
+ then a=`$i/$cc -dumpmachine $CCFLAGS 2>/dev/null`
+ case $a in
+ '') case $CCFLAGS in
+ ?*) a=`$cc -dumpmachine 2>/dev/null` ;;
+ esac
+ ;;
+ esac
+ case $a in
+ ''|*' '*|*/*:*)
+ ;;
+ *-*) canon=$a
+ ;;
+ *) _hostinfo_="$_hostinfo_ $a"
+ continue 2
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ if test -f "$i/$f"
+ then map="`grep -v '^#' $i/$f` $map"
+ fi
+ done
+
+ # inconsistent -dumpmachine filtered here
+
+ case -${canon}- in
+ --|*-powerpc-*)
+ h=`hostname || uname -n || cat /etc/whoami`
+ case $h in
+ '') h=local ;;
+ esac
+ a=`arch || uname -m || att uname -m || uname -s || att uname -s`
+ case $a in
+ *[\ \ ]*) a=`echo $a | $SED "s/[ ]/-/g"` ;;
+ esac
+ case $a in
+ '') a=unknown ;;
+ esac
+ m=`mach || machine || uname -p || att uname -p`
+ case $m in
+ *[\ \ ]*) m=`echo $m | $SED "s/[ ]/-/g"` ;;
+ esac
+ case $m in
+ '') m=unknown ;;
+ esac
+ x=`uname -a || att uname -a`
+ case $x in
+ '') x="unknown $host unknown unknown unknown unknown unknown" ;;
+ esac
+ set "" $h $a $m $x
+ expected=$1 host=$2 arch=$3 mach=$4 os=$5 sys=$6 rel=$7 ver=$8
+ ;;
+ *) case $canon in
+ *-*) IFS=-
+ set "" $canon
+ shift
+ IFS=$ifs
+ case $# in
+ 2) host= mach= arch=$1 os=$2 sys= rel= ;;
+ *) host= mach=$2 arch=$1 os=$3 sys= rel= ;;
+ esac
+ case $os in
+ [abcdefghijklmnopqrstuvwxyz]*[0123456789])
+ eval `echo $os | $SED -e 's/^\([^0123456789.]*\)\.*\(.*\)/os=\1 rel=\2/'`
+ ;;
+ esac
+ ;;
+ *) arch=$canon mach= os= sys= rel=
+ ;;
+ esac
+ ;;
+ esac
+ type=unknown
+ case $host in
+ *.*) host=`echo $host | $SED -e 's/\..*//'` ;;
+ esac
+ case $mach in
+ unknown)
+ mach=
+ ;;
+ [Rr][0123][0123456789][0123456789][0123456789])
+ mach=mips1
+ ;;
+ [Rr][4][0123456789][0123456789][0123456789])
+ mach=mips2
+ ;;
+ [Rr][56789][0123456789][0123456789][0123456789]|[Rr][123456789][0123456789][0123456789][0123456789][0123456789])
+ mach=mips4
+ ;;
+ pc) arch=i386
+ mach=
+ ;;
+ [Pp][Oo][Ww][Ee][Rr][Pp][Cc])
+ arch=ppc
+ mach=
+ ;;
+ *) case $arch in
+ 34[0123456789][0123456789])
+ os=ncr
+ arch=i386
+ ;;
+ esac
+ ;;
+ esac
+ case $canon in
+ '') set \
+ \
+ /NextDeveloper -d next - \
+ /config/hw/system/cpu -d tandem mach \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ if test $2 $1
+ then os=$3
+ case $4 in
+ arch) mach=$arch ;;
+ mach) arch=$mach ;;
+ esac
+ break
+ fi
+ shift;shift;shift;shift
+ done
+ ;;
+ esac
+ case $os in
+ AIX*|aix*)
+ type=ibm.risc
+ ;;
+ HP-UX) case $arch in
+ 9000/[78]*)
+ type=hp.pa
+ ;;
+ */*) type=hp.`echo $arch | $SED 's,/,_,g'`
+ ;;
+ *) type=hp.$arch
+ ;;
+ esac
+ ;;
+ [Ii][Rr][Ii][Xx]*)
+ set xx `hinv | $SED -e '/^CPU:/!d' -e 's/CPU:[ ]*\([^ ]*\)[ ]*\([^ ]*\).*/\1 \2/' -e q | $TR ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ shift
+ type=$1
+ n=
+ case $2 in
+ r[0123][0123456789][0123456789][0123456789])
+ n=1
+ ;;
+ r[4][0123][0123456789][0123456789])
+ n=2
+ ;;
+ r[4][456789][0123456789][0123456789]|r[5][0123456789][0123456789][0123456789])
+ n=3
+ ;;
+ r[6789][0123456789][0123456789][0123456789]|r[123456789][0123456789][0123456789][0123456789][0123456789])
+ n=4
+ ;;
+ esac
+ case $rel in
+ [01234].*|5.[012]|5.[012].*)
+ case $n in
+ 1) ;;
+ *) n=2 ;;
+ esac
+ ;;
+ 5.*) case $n in
+ 2) n=3 ;;
+ esac
+ ;;
+ esac
+ if executable $cc
+ then a=$cc
+ else IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ for i
+ do a=$i/$cc
+ if executable $a
+ then break
+ fi
+ done
+ fi
+ split='
+'
+ a=`strings $a < /dev/null | $SED -e 's/[^abcdefghijklmnopqrstuvwxyz0123456789]/ /g' -e 's/[ ][ ]*/\'"$split"'/g' | $SED -e "/^${type}[0123456789]$/!d" -e "s/^${type}//" -e q`
+ case $a in
+ [0123456789]) n=$a ;;
+ esac
+ case $n in
+ 4) a=`$cc -${type}3 2>&1`
+ case $a in
+ *unknown*|*install*|*conflict*)
+ ;;
+ *) n=3
+ ;;
+ esac
+ ;;
+ esac
+ a=`$cc -show F0oB@r.c 2>&1`
+ case $n:$a in
+ [!2]:*mips2*) n=2 ;;
+ [!23]:*mips3*) n=3 ;;
+ [!234]:*mips4*) n=4 ;;
+ esac
+ case $n:$a in
+ [!2]:*[Oo]32*) abi=-o32 ;;
+ [!3]:*[Nn]32*) abi=-n32 ;;
+ esac
+ mach=${type}$n
+ type=sgi.$mach
+ ;;
+ OSx*|SMP*|pyramid)
+ type=pyr
+ ;;
+ OS/390) type=mvs.390
+ ;;
+ [Ss][Cc][Oo]*)
+ type=sco
+ ;;
+ [Ss]ol*)
+ v=`echo $rel | $SED -e 's/^[25]\.//' -e 's/\.[^.]*$//'`
+ case $v in
+ [6789]|[1-9][0-9])
+ ;;
+ *) v=
+ ;;
+ esac
+ case $arch in
+ '') case $mach in
+ '') arch=sun4 ;;
+ *) arch=$mach ;;
+ esac
+ ;;
+ esac
+ case $arch in
+ sparc) arch=sun4 ;;
+ esac
+ type=sol$v.$arch
+ ;;
+ [Ss]un*)type=`echo $arch | $SED -e 's/\(sun.\).*/\1/'`
+ case $type in
+ sparc) type=sun4 ;;
+ esac
+ case $rel in
+ [01234]*)
+ ;;
+ '') case $os in
+ *[Oo][Ss])
+ ;;
+ *) type=sol.$type
+ ;;
+ esac
+ ;;
+ *) case $type in
+ '') case $mach in
+ sparc*) type=sun4 ;;
+ *) type=$mach ;;
+ esac
+ ;;
+ esac
+ v=`echo $rel | $SED -e 's/^[25]\.//' -e 's/\.[^.]*$//'`
+ case $v in
+ [6789]|[1-9][0-9])
+ ;;
+ *) v=
+ ;;
+ esac
+ type=sol$v.$type
+ ;;
+ esac
+ case $type in
+ sun*|*.*)
+ ;;
+ *) type=sun.$type
+ ;;
+ esac
+ ;;
+ [Uu][Nn][Ii][Xx]_[Ss][Vv])
+ type=unixware
+ ;;
+ UTS*|uts*)
+ if test -x /bin/u370 -o -x /bin/u390
+ then type=uts.390
+ else case $arch in
+ '') arch=$mach ;;
+ esac
+ type=uts.$arch
+ fi
+ ;;
+ $host) type=$arch
+ case $type in
+ *.*|*[0123456789]*86|*68*)
+ ;;
+ *) case $mach in
+ *[0123456789]*86|*68*|mips)
+ type=$type.$mach
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ unknown)
+ case $arch in
+ ?*) case $arch in
+ sun*) mach= ;;
+ esac
+ type=$arch
+ case $mach in
+ ?*) type=$type.$mach ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $ver in
+ FTX*|ftx*)
+ case $mach in
+ *[0123456789][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*)
+ mach=`echo $mach | $SED -e 's/[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*$//'`
+ ;;
+ esac
+ type=stratus.$mach
+ ;;
+ *) case $arch in
+ [Oo][Ss][-/.]2)
+ type=os2
+ arch=$rel
+ ;;
+ *) type=`echo $os | $SED -e 's/[0123456789].*//' -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789.].*//'`
+ ;;
+ esac
+ case $type in
+ [Cc][Yy][Gg][Ww][Ii][Nn]_*)
+ type=cygwin
+ ;;
+ [Uu][Ww][Ii][Nn]*|[Ww]indows_[0123456789][0123456789]|[Ww]indows_[Nn][Tt])
+ type=win32
+ arch=`echo $arch | $SED -e 's/_[^_]*$//'`
+ ;;
+ esac
+ case $arch in
+ '') case $mach in
+ ?*) type=$type.$mach ;;
+ esac
+ ;;
+ *) type=$type.$arch ;;
+ esac
+ ;;
+ esac
+ esac
+ case $type in
+ [0123456789]*)
+ case $mach in
+ ?*) type=$mach ;;
+ esac
+ case $type in
+ */MC) type=ncr.$type ;;
+ esac
+ ;;
+ *.*) ;;
+ *[0123456789]*86|*68*)
+ case $rel in
+ [34].[0123456789]*)
+ type=att.$type
+ ;;
+ esac
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*[0123456789])
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*) case $mach in
+ $type) case $ver in
+ Fault*|fault*|FAULT*)
+ type=ft.$type
+ ;;
+ esac
+ ;;
+ ?*) case $arch in
+ '') type=$type.$mach ;;
+ *) type=$type.$arch ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $type in
+ *[-_]32|*[-_]64|*[-_]128)
+ bits=`echo $type | $SED 's,.*[-_],,'`
+ type=`echo $type | $SED 's,[-_][0-9]*$,,'`
+ ;;
+ *) bits=
+ ;;
+ esac
+ type=`echo $type | $SED -e 's%[-+/].*%%' | $TR ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ case $type in
+ *.*) lhs=`echo $type | $SED -e 's/\..*//'`
+ rhs=`echo $type | $SED -e 's/.*\.//'`
+ case $rhs in
+ [x0123456789]*86) rhs=i$rhs ;;
+ 68*) rhs=m$rhs ;;
+ esac
+ case $rhs in
+ i[x23456789]86|i?[x23456789]86|*86pc)
+ rhs=i386 ;;
+ powerpc) rhs=ppc ;;
+ s[0123456789]*[0123456789]x)
+ rhs=`echo $rhs | $SED -e 's/x$/-64/'` ;;
+ esac
+ case $rhs in
+ arm[abcdefghijklmnopqrstuvwxyz_][0123456789]*)
+ rhs=arm ;;
+ hppa) rhs=pa ;;
+ esac
+ case $lhs in
+ ?*coff|?*dwarf|?*elf)
+ case $lhs in
+ ?*coff) x=coff ;;
+ ?*dwarf)x=coff ;;
+ ?*elf) x=elf ;;
+ esac
+ lhs=`echo ${lhs}XXX | $SED -e "s/${x}XXX//"`
+ ;;
+ esac
+ case $lhs in
+ bsdi) lhs=bsd ;;
+ darwin) case $rel in
+ [01234567].*) lhs=${lhs}7 ;;
+ esac
+ ;;
+ freebsd) case $rel in
+ [01234].*) lhs=${lhs}4 ;;
+ [123456789]*.*) lhs=${lhs}`echo $rel | $SED -e 's/\..*//'` ;;
+ esac
+ ;;
+ hpux) lhs=hp ;;
+ mvs) rhs=390 ;;
+ esac
+ case $lhs in
+ '') type=$rhs ;;
+ $rhs) type=$lhs ;;
+ *) type=$lhs.$rhs ;;
+ esac
+ ;;
+ esac
+ case $type in
+ sgi.mips*)
+ case $mach in
+ mips2) type=sgi.$mach
+ abi=-o32
+ ;;
+ mips3) type=sgi.$mach
+ abi=-n32
+ ;;
+ mips[456789])
+ type=sgi.$mach
+ case $abi in
+ *-n32) ;;
+ *) abi=-64 ;;
+ esac
+ ;;
+ *) pwd=`pwd`
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.a.c <<!
+extern int b();
+int main() { return b(); }
+!
+ cat > $tmp.b.c <<!
+int b() { return 0; }
+!
+ abi=
+ if $cc -c $tmp.a.c
+ then for i in -n32 -o32 -64
+ do if $cc $i -c $tmp.b.c &&
+ $cc -o $tmp.exe $tmp.a.o $tmp.b.o
+ then abi=$i
+ for i in 2 3 4 5 6 7 8 9
+ do case $i:$abi in
+ 2:-n32|2:-64|3:-64)
+ continue
+ ;;
+ esac
+ if $cc $abi -mips$i -c $tmp.b.c &&
+ $cc -o $tmp.exe $tmp.a.o $tmp.b.o
+ then type=`echo $type | $SED -e 's/.$//'`$i
+ break
+ fi
+ done
+ break
+ fi
+ done
+ fi </dev/null >/dev/null 2>&1
+ rm -f $tmp.*
+ trap - 0 1 2
+ cd $pwd
+ ;;
+ esac
+ case $type$abi in
+ sgi.mips2-o32)
+ ;;
+ sgi.mips3)
+ type=$type-o32
+ ;;
+ sgi.mips3-n32)
+ ;;
+ sgi.mips4)
+ type=$type-o32
+ ;;
+ sgi.mips[456789]-64)
+ ;;
+ *) type=$type$abi
+ ;;
+ esac
+ ;;
+ *) case $bits in
+ '') case `file /bin/sh 2>/dev/null` in
+ *universal*64*)
+ pwd=`pwd`
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.a.c <<!
+int main() { return 0; }
+!
+ if $cc -o $tmp.a.exe $tmp.a.c
+ then case `file $tmp.a.exe` in
+ *64*) bits=64 ;;
+ esac
+ fi </dev/null >/dev/null 2>&1
+ rm -f $tmp.*
+ trap - 0 1 2
+ cd $pwd
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $bits in
+ 32) case $type in
+ *.i386) bits= ;;
+ esac
+ ;;
+ esac
+ case $bits in
+ ?*) type=$type-$bits ;;
+ esac
+
+ # last chance mapping
+
+ set "" "" $map
+ while :
+ do case $# in
+ [012]) break ;;
+ esac
+ shift;shift
+ eval " case \$type in
+ $1) type=\$2; break ;;
+ esac"
+ done
+ _hostinfo_="$_hostinfo_ $type"
+ ;;
+ esac
+ done
+ set '' $_hostinfo_
+ shift
+ _hostinfo_=$*
+
+ # restore the global state
+
+ PATH=$path
+ case $DEBUG in
+ '') exec 2>&9
+ exec 9>&-
+ ;;
+ esac
+}
+
+# info message
+
+note() # message ...
+{
+ echo $command: "$@" >&2
+}
+
+# cc checks
+#
+# CC: compiler base name name
+# cc: full path, empty if not found
+
+checkcc()
+{
+ cc=
+ if onpath $CC
+ then cc=$_onpath_
+ else case $CC in
+ cc) if onpath gcc
+ then CC=gcc
+ cc=$_onpath_
+ fi
+ ;;
+ esac
+ fi
+ case $cc in
+ '') case $action in
+ make|test) note "$CC: not found"; exit 1 ;;
+ *) note "warning: $CC: not found" ;;
+ esac
+ ;;
+ esac
+}
+
+# some actions have their own PACKAGEROOT or kick out early
+
+case $action in
+host) eval u=$package_use
+ case $u in
+ $PACKAGE_USE)
+ ;;
+ *) if onpath $0
+ then case $_onpath_ in
+ */arch/$HOSTTYPE/bin/package)
+ KEEP_HOSTTYPE=1
+ ;;
+ *) KEEP_HOSTTYPE=0
+ ;;
+ esac
+ else KEEP_HOSTTYPE=0
+ fi
+ ;;
+ esac
+ hostinfo $args
+ echo $_hostinfo_
+ exit 0
+ ;;
+export|setup|use)
+ x=
+ ;;
+*) x=
+ eval u=$package_use
+ case $u in
+ $PACKAGE_USE)
+ case :$PATH: in
+ *:$INSTALLROOT/bin:*)
+ case $LIBPATH: in
+ $INSTALLROOT/bin:$INSTALLROOT/lib:*)
+ case $SHLIB_PATH: in
+ $INSTALLROOT/lib:*)
+ x=1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+run=-
+case $x in
+1) : accept the current package use environment
+
+ OK=ok
+ KSH=$EXECROOT/bin/ksh
+ MAKE=nmake
+ NMAKE=$EXECROOT/bin/$MAKE
+ SUM=$EXECROOT/bin/sum
+ TEE=$EXECROOT/bin/tee
+ INITROOT=$PACKAGEROOT/src/cmd/INIT
+ checkcc
+ ;;
+*) hosttype=
+ case $KEEP_PACKAGEROOT in
+ 0) case $action in
+ use) PACKAGEROOT=
+ case $show in
+ echo) exec=echo make=echo show=echo ;;
+ esac
+ set '' $args
+ shift
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -|.) ;;
+ /*) PACKAGEROOT=$1
+ ;;
+ *) i=`echo ~$1`
+ if packageroot $i
+ then PACKAGEROOT=$i
+ else for i in `echo $HOME | sed -e 's,/[^/]*$,,'` $usr $use
+ do if packageroot $i/$1
+ then PACKAGEROOT=$i/$1
+ break
+ fi
+ done
+ case $PACKAGEROOT in
+ '') hosttype=$1 ;;
+ esac
+ fi
+ ;;
+ esac
+ shift
+ ;;
+ esac
+ run="$@"
+ ;;
+ esac
+ case $PACKAGEROOT in
+ '') PACKAGEROOT=${PWD:-`pwd`} ;;
+ esac
+
+ # . must be within the PACKAGEROOT tree
+
+ i=X$PACKAGEROOT
+ IFS=/
+ set $i
+ IFS=$ifs
+ while :
+ do i=$1
+ shift
+ case $i in
+ X) break ;;
+ esac
+ done
+ case $PACKAGEROOT in
+ //*) d=/ ;;
+ *) d= ;;
+ esac
+ case $1 in
+ home) k=1 ;;
+ *) k=0 ;;
+ esac
+ for i
+ do case $i in
+ '') continue ;;
+ esac
+ d=$d/$i
+ case $k in
+ 2) k=1
+ ;;
+ 1) k=0
+ ;;
+ 0) case $i in
+ arch) k=2
+ ;;
+ *) if packageroot $d
+ then PACKAGEROOT=$d
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ done
+ ;;
+ esac
+ INITROOT=$PACKAGEROOT/src/cmd/INIT
+ $show PACKAGEROOT=$PACKAGEROOT
+ $show export PACKAGEROOT
+ export PACKAGEROOT
+
+ # initialize the architecture environment
+
+ case $KEEP_HOSTTYPE in
+ 0) hostinfo type
+ HOSTTYPE=$_hostinfo_
+ ;;
+ 1) _PACKAGE_HOSTTYPE_=$HOSTTYPE
+ export _PACKAGE_HOSTTYPE_
+ ;;
+ esac
+ $show HOSTTYPE=$HOSTTYPE
+ $show export HOSTTYPE
+ export HOSTTYPE
+ INSTALLROOT=$PACKAGEROOT/arch/$HOSTTYPE
+ case $action in
+ admin|install|make|read|remove|test|verify|view|write)
+ ;;
+ *) if test ! -d $INSTALLROOT
+ then INSTALLROOT=$PACKAGEROOT
+ fi
+ ;;
+ esac
+ $show INSTALLROOT=$INSTALLROOT
+ $show export INSTALLROOT
+ export INSTALLROOT
+
+ # HOSTTYPE specific package profile
+
+ if test -r $INSTALLROOT/lib/package/profile
+ then . $INSTALLROOT/lib/package/profile
+ fi
+
+ # check the basic package hierarchy
+
+ case $action in
+ export|use)
+ packageroot $PACKAGEROOT || {
+ echo "$command: $PACKAGEROOT: invalid package root directory" >&2
+ exit 1
+ }
+ case $KEEP_HOSTTYPE:$hosttype in
+ 0:?*) if test -d ${PACKAGEROOT:-.}/arch/$hosttype
+ then KEEP_HOSTTYPE=1
+ HOSTTYPE=$hosttype
+ else echo "$command: $hosttype: package root not found" >&2
+ exit 1
+ fi
+ ;;
+ esac
+ ;;
+ *) packageroot $PACKAGEROOT || {
+ case $KEEP_PACKAGEROOT in
+ 1) ;;
+ *) echo "$command: $PACKAGEROOT: must be in the package root directory tree" >&2
+ exit 1
+ ;;
+ esac
+ }
+
+ case $action in
+ admin) ;;
+ *) for i in arch arch/$HOSTTYPE
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ for i in lib
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ ;;
+ esac
+
+ # no $INITROOT means INIT already installed elsewhere
+
+ if test -d $INITROOT
+ then
+ # update the basic package commands
+
+ for i in execrate ignore mamprobe silent
+ do test -h $PACKAGEROOT/bin/$i 2>/dev/null ||
+ case `ls -t $INITROOT/$i.sh $PACKAGEROOT/bin/$i 2>/dev/null` in
+ "$INITROOT/$i.sh"*)
+ note update $PACKAGEROOT/bin/$i
+ shellmagic
+ case $SHELLMAGIC in
+ '') $exec cp $INITROOT/$i.sh $PACKAGEROOT/bin/$i || exit
+ ;;
+ *) case $exec in
+ '') {
+ echo "$SHELLMAGIC"
+ cat $INITROOT/$i.sh
+ } > $PACKAGEROOT/bin/$i || exit
+ ;;
+ *) echo "{
+echo \"$SHELLMAGIC\"
+cat $INITROOT/$i.sh
+} > $PACKAGEROOT/bin/$i"
+ ;;
+ esac
+ ;;
+ esac
+ $exec chmod +x $PACKAGEROOT/bin/$i || exit
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ path=$PATH
+ PATH=$INSTALLROOT/bin:$PACKAGEROOT/bin:$PATH
+ checkcc
+ PATH=$path
+ case $cc in
+ ?*) if test -f $INITROOT/hello.c
+ then
+ # check if $CC (full path $cc) is a cross compiler
+
+ (
+ cd /tmp || exit 3
+ cp $INITROOT/hello.c pkg$$.c || exit 3
+ $cc -o pkg$$.exe pkg$$.c > pkg$$.e 2>&1 || {
+ if $cc -Dnew=old -o pkg$$.exe pkg$$.c > /dev/null 2>&1
+ then echo "$command: ${warn}$CC: must be a C compiler (not C++)" >&2
+ else cat pkg$$.e
+ echo "$command: ${warn}$CC: failed to compile and link $INITROOT/hello.c -- is it a C compiler?" >&2
+ fi
+ exit 2
+ }
+ if ./pkg$$.exe >/dev/null 2>&1
+ then code=0
+ else code=1
+ fi
+ rm -f pkg$$.*
+ exit $code
+ )
+ code=$?
+ case $code in
+ 1) CROSS=1 ;;
+ esac
+ fi
+ ;;
+ esac
+ EXECTYPE=$HOSTTYPE
+ EXECROOT=$INSTALLROOT
+ case $CROSS in
+ 0) # dll hackery -- why is this so complicated?
+
+ abi=
+ case $HOSTTYPE in
+ sgi.mips[0123456789]*)
+ x=rld
+ if executable /lib32/$x || executable /lib64/$x
+ then case $INSTALLROOT in
+ */sgi.mips[0123456789]*)
+ u=`echo $INSTALLROOT | sed -e 's,-[^-/]*$,,' -e 's,.$,,'`
+ ;;
+ *) u=
+ ;;
+ esac
+ for a in "n=2 v= l=" "n=3 v=N32 l=lib32" "n=4-n32 v=N32 l=lib32" "n=4 v=64 l=lib64"
+ do eval $a
+ case $v in
+ N32) case $n:$HOSTTYPE in
+ *-n32:*-n32) ;;
+ *-n32:*) continue ;;
+ *:*-n32) continue ;;
+ esac
+ ;;
+ esac
+ case $l in
+ ?*) if executable ! /$l/$x
+ then continue
+ fi
+ ;;
+ esac
+ case $u in
+ '') case $HOSTTYPE in
+ sgi.mips$n|sgi.mips$n-*)
+ abi="$abi 'd=$INSTALLROOT v=$v'"
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ *) if test -d $u$n
+ then abi="$abi 'd=$u$n v=$v'"
+ fi
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ case $abi in
+ '') abi="'d=$INSTALLROOT v='" ;;
+ esac
+ p=0
+ eval "
+ for a in $abi
+ do eval \$a
+ eval \"
+ case \\\$LD_LIBRARY\${v}_PATH: in
+ \\\$d/lib:*)
+ ;;
+ *) x=\\\$LD_LIBRARY\${v}_PATH
+ case \\\$x in
+ ''|:*) ;;
+ *) x=:\\\$x ;;
+ esac
+ LD_LIBRARY\${v}_PATH=\$d/lib\\\$x
+ export LD_LIBRARY\${v}_PATH
+ p=1
+ ;;
+ esac
+ \"
+ done
+ "
+ case $LD_LIBRARY_PATH in
+ '') ;;
+ *) for d in $lib
+ do case $HOSTTYPE in
+ *64) if test -d ${d}64
+ then d=${d}64
+ fi
+ ;;
+ esac
+ case :$LD_LIBRARY_PATH: in
+ *:$d:*) ;;
+ *) if test -d $d
+ then LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$d
+ p=1
+ fi
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $p in
+ 1) $show LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+ $show export LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH
+ ;;
+ esac
+ case $LIBPATH: in
+ $INSTALLROOT/bin:$INSTALLROOT/lib:*)
+ ;;
+ *) case $LIBPATH in
+ '') LIBPATH=/usr/lib:/lib ;;
+ esac
+ LIBPATH=$INSTALLROOT/bin:$INSTALLROOT/lib:$LIBPATH
+ $show LIBPATH=$LIBPATH
+ $show export LIBPATH
+ export LIBPATH
+ ;;
+ esac
+ case $SHLIB_PATH: in
+ $INSTALLROOT/lib:*)
+ ;;
+ *) SHLIB_PATH=$INSTALLROOT/lib${SHLIB_PATH:+:$SHLIB_PATH}
+ $show SHLIB_PATH=$SHLIB_PATH
+ $show export SHLIB_PATH
+ export SHLIB_PATH
+ ;;
+ esac
+ case $DYLD_LIBRARY_PATH: in
+ $INSTALLROOT/lib:*)
+ ;;
+ *) DYLD_LIBRARY_PATH=$INSTALLROOT/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}
+ $show DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH
+ $show export DYLD_LIBRARY_PATH
+ export DYLD_LIBRARY_PATH
+ ;;
+ esac
+ case $_RLD_ROOT in
+ $INSTALLROOT/arch*) ;;
+ ':') _RLD_ROOT=$INSTALLROOT/arch:/ ;;
+ /|*:/) _RLD_ROOT=$INSTALLROOT/arch:$_RLD_ROOT ;;
+ *) _RLD_ROOT=$INSTALLROOT/arch:$_RLD_ROOT:/ ;;
+ esac
+ $show _RLD_ROOT=$_RLD_ROOT
+ $show export _RLD_ROOT
+ export _RLD_ROOT
+
+ # now set up PATH
+ #
+ # NOTE: PACKAGEROOT==INSTALLROOT is possible for binary installations
+
+ case $PATH: in
+ $PACKAGEROOT/bin:*)
+ ;;
+ *) PATH=$PACKAGEROOT/bin:$PATH
+ ;;
+ esac
+ case $PATH: in
+ $INSTALLROOT/bin:*)
+ ;;
+ *) PATH=$INSTALLROOT/bin:$PATH
+ ;;
+ esac
+ $show PATH=$PATH
+ $show export PATH
+ export PATH
+ ;;
+ *) for i in package proto nmake
+ do if onpath $i
+ then EXECROOT=`echo $_onpath_ | sed -e 's,//*[^/]*//*[^/]*$,,'`
+ EXECTYPE=`echo $EXECROOT | sed -e 's,.*/,,'`
+ break
+ fi
+ done
+ case $HOSTTYPE in
+ $EXECTYPE)
+ OCC=$CC
+ CC=cc
+ hostinfo type
+ EXECTYPE=$_hostinfo_
+ case $HOSTTYPE in
+ $EXECTYPE)
+ echo "$command: $CC: seems to be a cross-compiler" >&2
+ echo "$command: set HOSTTYPE to something other than the native $EXECTYPE" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ $show EXECTYPE=$EXECTYPE
+ $show export EXECTYPE
+ export EXECTYPE
+ ;;
+ esac
+ $show EXECROOT=$EXECROOT
+ $show export EXECROOT
+ export EXECROOT
+
+ # use these if possible
+
+ OK=ok
+ KSH=$EXECROOT/bin/ksh
+ MAKE=nmake
+ NMAKE=$EXECROOT/bin/$MAKE
+ SUM=$EXECROOT/bin/sum
+ TEE=$EXECROOT/bin/tee
+
+ # grab a decent default shell
+
+ case $KEEP_SHELL in
+ 0) executable "$SHELL" || SHELL=
+ case $SHELL in
+ ?*) checksh $SHELL || SHELL= ;;
+ esac
+ case $SHELL in
+ ''|/bin/*|/usr/bin/*)
+ case $SHELL in
+ '') SHELL=/bin/sh ;;
+ esac
+ for i in ksh sh bash
+ do if onpath $i && checksh $_onpath_
+ then SHELL=$_onpath_
+ break
+ fi
+ done
+ ;;
+ */*ksh) if executable $KSH
+ then SHELL=$KSH
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ # $SHELL must be /bin/sh compatible
+
+ case $SHELL in
+ /bin/sh);;
+ '') SHELL=/bin/sh
+ ;;
+ *) $SHELL -c 'trap "exit 0" 0; exit 1' 2>/dev/null
+ case $? in
+ 1) SHELL=/bin/sh
+ ;;
+ *) # catch (our own) pipe/socket configuration mismatches
+ $SHELL -c "date | $SHELL -c 'read x'"
+ case $? in
+ 0) ;;
+ *) SHELL=/bin/sh ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ export SHELL
+ $show SHELL=$SHELL
+ $show export SHELL
+ COSHELL=$SHELL
+ export COSHELL
+ $show COSHELL=$COSHELL
+ $show export COSHELL
+
+ # tame the environment
+
+ case $action in
+ use) ;;
+ *) ENV=
+ ERROR_OPTIONS=
+ export ENV ERROR_OPTIONS
+ ;;
+ esac
+
+ # finalize the views
+
+ case $USER_VPATH in
+ '') case $VPATH in
+ ?*) IFS=':'
+ set '' $VPATH
+ shift
+ IFS=$ifs
+ USER_VPATH=
+ for i
+ do case $i in
+ */arch/$HOSTTYPE) ;;
+ */arch/*/*) ;;
+ */arch/*) continue ;;
+ esac
+ if packageroot $i
+ then case $USER_VPATH in
+ '') USER_VPATH=$i ;;
+ ?*) USER_VPATH=$USER_VPATH:$i ;;
+ esac
+ fi
+ done
+ esac
+ ;;
+ esac
+ case $USER_VPATH in
+ ?*) IFS=':'
+ set '' $USER_VPATH
+ shift
+ IFS=$ifs
+ USER_VPATH=
+ USER_VPATH_CHAIN=
+ p=$PACKAGEROOT
+ for i
+ do case $i in
+ ''|$PACKAGEROOT|$INSTALLROOT)
+ ;;
+ ?*) USER_VPATH=$USER_VPATH:$i
+ USER_VPATH_CHAIN="$USER_VPATH_CHAIN $p $i"
+ p=$i
+ case $PROTOROOT in
+ -) executable $i/bin/mamake && PROTOROOT= ;;
+ esac
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+esac
+PACKAGESRC=$PACKAGEROOT/lib/package
+PACKAGEBIN=$INSTALLROOT/lib/package
+case $action:$run in
+use:-) set '' $args
+ shift
+ case $# in
+ 0) ;;
+ *) shift ;;
+ esac
+ run="$@"
+ ;;
+esac
+
+# more cygwin hassles
+
+case $HOSTTYPE in
+cygwin.*)
+ lose=
+ case $CYGWIN in
+ *nontsec*)
+ lose=ntsec
+ ;;
+ *ntsec*);;
+ *) exe=/tmp/pkg$$.exe
+ rm -f $exe
+ : > $exe
+ if test -x $exe
+ then lose=ntsec
+ fi
+ ;;
+ esac
+ case $CYGWIN in
+ *nobinmode*)
+ case $lose in
+ '') lose=binmode ;;
+ *) lose="$lose binmode" ;;
+ esac
+ ;;
+ esac
+ case $lose in
+ ?*) echo "$command: $HOSTTYPE: export '$lose' in CYGWIN or languish in windows" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+# set up the view state
+
+VIEW_bin=$INSTALLROOT VIEW_src=$PACKAGEROOT VIEW_all="$INSTALLROOT $PACKAGEROOT"
+if (vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+then $show vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+else VPATH=$INSTALLROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ $show export VPATH
+ export VPATH
+ IFS=':'
+ set '' $VPATH
+ shift
+ IFS=$ifs
+ for i
+ do case $i in
+ */arch/*/*)
+ VIEW_src="$VIEW_src $i"
+ ;;
+ */arch/*)
+ VIEW_bin="$VIEW_bin $i"
+ ;;
+ *)
+ VIEW_src="$VIEW_src $i"
+ ;;
+ esac
+ VIEW_all="$VIEW_all $i"
+ done
+fi
+
+# return 0 if arg in src|bin|all view
+
+view() # [test] [-|type] [src|bin|all] file
+{
+ case $1 in
+ -[dfsx])_view_T_=$1; shift ;;
+ *) _view_T_=-f ;;
+ esac
+ case $1 in
+ -) _view_t_= ;;
+ *) _view_t_=$1 ;;
+ esac
+ shift
+ case $1 in
+ all) shift; _view_v_=$VIEW_all ;;
+ bin) shift; _view_v_=$VIEW_bin ;;
+ src) shift; _view_v_=$VIEW_src ;;
+ *) _view_v_=$VIEW_all ;;
+ esac
+ case $1 in
+ /*) if test $_view_T_ $1
+ then _view_=$1
+ return 0
+ fi
+ ;;
+ *) for _view_d_ in $_view_v_
+ do if test $_view_T_ $_view_d_/$1
+ then _view_=$_view_d_/$1
+ return 0
+ fi
+ done
+ ;;
+ esac
+ _view_=
+ case $_view_t_ in
+ ?*) echo $command: $1: $_view_t_ not found >&2 ;;
+ esac
+ return 1
+}
+
+# determine the package and targets
+
+case $action in
+admin) case $admin_action in
+ results)action=$admin_action
+ set '' $admin_args
+ shift;shift
+ admin_args="admin $*"
+ case $admin_on in
+ '') target=$admin_args ;;
+ *) target="on $admin_on $admin_args" ;;
+ esac
+ ;;
+ esac
+ ;;
+release)set '' $args
+ target=
+ while :
+ do shift
+ case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ target="$target $1"
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ package=$*
+ ;;
+setup) # { update read } with optional (bin|fun|include|lib) symlinks
+ # flat option sets up { bin fun include lib } symlinks from
+ # $INSTALLROOT to $PACKAGEROOT
+
+ # . is the package root
+
+ set '' $args
+ shift
+ types=
+ url=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ flat) flat=1 # backwards compatibility -- documentation dropped
+ ;;
+ *://*|*.url)
+ url=$1
+ shift
+ break
+ ;;
+ *) types="$types $1"
+ ;;
+ esac
+ shift
+ done
+ if test ! -d $PACKAGEROOT/lib/package/tgz
+ then $exec mkdir -p $PACKAGEROOT/lib/package/tgz || exit
+ fi
+ case " $types " in
+ *" source "*)
+ case " $* " in
+ ' ') ;;
+ *" INIT "*)
+ ;;
+ *) view - all src/cmd/INIT ||
+ set INIT "$@"
+ ;;
+ esac
+ ;;
+ esac
+ packages=`$0 $global authorize "$authorize" password "$password" update setup $types $url "$@" PACKAGEROOT=$PACKAGEROOT`
+ case $packages in
+ ?*) $0 $global read $packages PACKAGEROOT=$PACKAGEROOT
+ esac
+ exit
+ ;;
+*) package=
+ target=
+ set '' $args
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ ''|-) target="$target $package"
+ package=
+ ;;
+ *) if view - src "lib/package/$1.pkg"
+ then package="$package $1"
+ else target="$target $package $1"
+ package=
+ fi
+ ;;
+ esac
+ done
+ ;;
+esac
+
+# flatten -- assumes symlink support
+
+case $flat in
+1) case $action in
+ make|read|setup|update|use|view)
+ if test ! -d $INSTALLROOT
+ then $exec mkdir -p $INSTALLROOT || exit
+ fi
+ for i in bin include lib fun man share
+ do if test ! -d $INSTALLROOT/../../$i
+ then $exec mkdir $INSTALLROOT/../../$i
+ fi
+ if test ! -d $INSTALLROOT/$i
+ then if test ! -h $INSTALLROOT/$i
+ then $exec ln -s ../../$i $INSTALLROOT/$i
+ fi
+ elif test ! -h $INSTALLROOT/$i
+ then for x in $INSTALLROOT/$i/.[a-z]* $INSTALLROOT/$i/*
+ do if test -f $x -o -d $x
+ then if test ! -d $INSTALLROOT/$i/$x || test ! -d $INSTALLROOT/../../$i/$x
+ then $exec mv $x $INSTALLROOT/../../$i
+ fi
+ fi
+ done
+ $exec rm -rf $INSTALLROOT/$i
+ $exec ln -s ../../$i $INSTALLROOT/$i
+ fi
+ done
+ ;;
+ esac
+ ;;
+esac
+
+# check that cmd args are up to date a.out's
+
+checkaout() # cmd ...
+{
+ case $PROTOROOT in
+ -) PROTOROOT=
+ case $* in
+ ratz) if test -f $INITROOT/ratz.c -a -w $PACKAGEROOT
+ then test -f $INITROOT/hello.c || {
+ cat > $INITROOT/hello.c <<'!'
+#ifndef printf
+#include <stdio.h>
+#endif
+int main() { int new = 0; printf("hello world\n"); return new;}
+!
+ }
+ test -f $INITROOT/p.c || {
+ cat > $INITROOT/p.c <<'!'
+/*
+ * small test for prototyping cc
+ */
+
+int main(int argc, char** argv) { return argc || argv; }
+!
+ }
+ fi
+ ;;
+ esac
+ test -f $INITROOT/hello.c -a -f $INITROOT/p.c -a -w $PACKAGEROOT || {
+ for i
+ do onpath $i || {
+ echo "$command: $i: command not found" >&2
+ return 1
+ }
+ done
+ return 0
+ }
+ case $cc in
+ '') _PACKAGE_cc=0
+ ;;
+ *) _PACKAGE_cc=1
+ test -f $INITROOT/hello.c -a -f $INITROOT/p.c || {
+ echo "$command: $INITROOT: INIT package source not found" >&2
+ return 1
+ }
+ executable $INSTALLROOT/bin/nmake || {
+ # check for prototyping cc
+ # NOTE: proto.c must be K&R compatible
+
+ $CC -c $INITROOT/p.c >/dev/null 2>&1
+ c=$?
+ rm -f p.*
+ test 0 != "$c" && {
+ checkaout proto || return
+ PROTOROOT=$PACKAGEROOT/proto
+ $show PROTOROOT=$PACKAGEROOT/proto
+ export PROTOROOT
+ INITPROTO=$PROTOROOT/src/cmd/INIT
+ note proto convert $PACKAGEROOT/src into $PROTOROOT/src
+ if test -d $PACKAGEROOT/src/cmd/nmake
+ then dirs="src/cmd/INIT src/lib/libast src/lib/libardir src/lib/libcoshell src/lib/libpp src/cmd/probe src/cmd/cpp src/cmd/nmake"
+ else dirs="src"
+ fi
+ (
+ if test -f $PROTOROOT/UPDATE
+ then newer="-newer $PROTOROOT/UPDATE"
+ else newer=""
+ fi
+ case $exec in
+ '') cd $PACKAGEROOT
+ find $dirs -name '*.[CcHh]' $newer -print | proto -v -L - -C proto
+ ;;
+ *) $exec cd $PACKAGEROOT
+ $exec "find $dirs -name '*.[CcHh]' $newer -print | proto -L - -C proto"
+ ;;
+ esac
+ $exec touch $PROTOROOT/UPDATE
+ )
+ if (vpath $INSTALLROOT - $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT - $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT
+ then $show vpath $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT $USER_VPATH_CHAIN
+ else VPATH=$INSTALLROOT:$PROTOROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ export VPATH
+ fi
+ }
+ }
+ for i in arch arch/$HOSTTYPE arch/$HOSTTYPE/bin
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || return
+ done
+ ;;
+ esac
+ ;;
+ esac
+ case $_PACKAGE_cc in
+ '') case $cc in
+ '') _PACKAGE_cc=0 ;;
+ *) _PACKAGE_cc=1 ;;
+ esac
+ ;;
+ esac
+ for i
+ do eval j=\$_PACKAGE_AOUT_$i
+ case $j in
+ '') eval _PACKAGE_AOUT_$i=1 ;;
+ *) continue ;;
+ esac
+ k=$_PACKAGE_cc
+ if test -f $INITROOT/$i.c
+ then k=${k}1
+ else k=${k}0
+ fi
+ if executable $EXECROOT/bin/$i
+ then k=${k}1
+ else k=${k}0
+ fi
+ : $k : compiler : source : binary :
+ case $k in
+ *00) view - bin/$i && continue ;;
+ esac
+ case $k in
+ 000) echo "$command: $i: not found: download the INIT package $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 010) echo "$command: $i: not found: set CC=C-compiler or download the INIT package $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 100) echo "$command: $i: not found: download the INIT package source or $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 110) case $CROSS in
+ 1) echo "$command: $i: not found: make the local $EXECTYPE binary package before $HOSTTYPE" >&2
+ return 1
+ ;;
+ esac
+ ;;
+ ?01) : accept binary
+ continue
+ ;;
+ 011) : accept binary
+ continue
+ ;;
+ ??1) case $CROSS in
+ 1) continue ;;
+ esac
+ ;;
+ esac
+ case `ls -t $INITROOT/$i.c $INSTALLROOT/bin/$i 2>/dev/null` in
+ "$INITROOT/$i.c"*)
+ note update $INSTALLROOT/bin/$i
+ if test proto != "$i" && executable $INSTALLROOT/bin/proto
+ then case $exec in
+ '') $INSTALLROOT/bin/proto -p $INITROOT/$i.c > $i.c || return ;;
+ *) $exec "$INSTALLROOT/bin/proto -p $INITROOT/$i.c > $i.c" ;;
+ esac
+ $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $i.c || return
+ $exec rm -f $i.c
+ else if test ! -d $INSTALLROOT/bin
+ then for j in arch arch/$HOSTTYPE arch/$HOSTTYPE/bin
+ do test -d $PACKAGEROOT/$j || $exec mkdir $PACKAGEROOT/$j || return
+ done
+ fi
+ if test '' != "$PROTOROOT" -a -f $INITPROTO/$i.c
+ then $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $INITPROTO/$i.c || return
+ else $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $INITROOT/$i.c || return
+ fi
+ case $i:$exec in
+ proto:) test -d $INSTALLROOT/include || mkdir $INSTALLROOT/include
+ $INSTALLROOT/bin/proto -f /dev/null > $i.c
+ cmp -s $i.c $INSTALLROOT/include/prototyped.h 2>/dev/null || cp $i.c $INSTALLROOT/include/prototyped.h
+ rm $i.c
+ ;;
+ esac
+ fi
+ test -f $i.o && $exec rm -f $i.o
+ i=$PATH
+ PATH=/bin
+ PATH=$i
+ ;;
+ esac
+ done
+ return 0
+}
+
+# check package requirements against received packages
+
+requirements() # source|binary [ package ]
+{
+ case $1 in
+ binary) r=$VIEW_BIN ;;
+ source) r=$VIEW_SRC ;;
+ *) r=$VIEW_ALL ;;
+ esac
+ shift
+ case $1 in
+ '') x= ;;
+ *) x=$* ;;
+ esac
+ set ''
+ for d in $r
+ do set "$@" $d/gen/*.ver
+ case $x in
+ '') set "$@" $d/gen/*.req
+ ;;
+ *) for p in $x
+ do set "$@" $d/gen/$p.req
+ done
+ ;;
+ esac
+ done
+ shift
+ e=0
+ x=$*
+ y=
+ n=
+ set ''
+ for i in $x
+ do p=`echo $i | sed -e 's,.*/,,' -e 's,\....$,,'`
+ if test -f $i
+ then set "$@" $i
+ y="$y $p"
+ else case $p in
+ '*') ;;
+ *) n="$n $p" ;;
+ esac
+ fi
+ done
+ for i in $n
+ do case " $y " in
+ *" $i "*)
+ ;;
+ *) echo "$command: $i: must read or write package" >&2
+ e=1
+ ;;
+ esac
+ done
+ case $e in
+ 1) exit 1 ;;
+ esac
+ shift
+ test 0 != "$#" && release=`sort -r "$@" | {
+ q=
+ e=0
+ o=
+ while read p v r s
+ do q="$q
+$v $r"
+ case $p in
+ $o) continue ;;
+ esac
+ case $s in
+ 0) e=1
+ case $r in
+ base) echo "$command: base package $p.$v or newer required" >&2 ;;
+ *) echo "$command: delta package $p.$v.$r or newer required" >&2 ;;
+ esac
+ ;;
+ esac
+ o=$p
+ done
+ case $e in
+ 0) echo "$q" | sort | { read v r; read v r; echo $v; } ;;
+ 1) echo ERROR ;;
+ esac
+ }`
+ case $release in
+ ERROR) case $force in
+ 0) exit 1 ;;
+ esac
+ ;;
+ ?*) eval `echo $release | sed -e 's,\(.*\)-\(.*\)-\(.*\),yy=\1 mm=\2 dd=\3,'`
+ # slide back 4 months
+ case $mm in
+ 01) mm=09 dd=1 ;;
+ 02) mm=10 dd=1 ;;
+ 03) mm=11 dd=1 ;;
+ 04) mm=12 dd=1 ;;
+ 05) mm=01 dd=0 ;;
+ 06) mm=02 dd=0 ;;
+ 07) mm=03 dd=0 ;;
+ 08) mm=04 dd=0 ;;
+ 09) mm=05 dd=0 ;;
+ 10) mm=06 dd=0 ;;
+ 11) mm=07 dd=0 ;;
+ 12) mm=08 dd=0 ;;
+ esac
+ case $dd in
+ 1) yy=`expr $yy - 1` ;;
+ esac
+ release=$yy-$mm-01
+ count=1
+ lo=$release
+ release="-f $release -r $count"
+ ;;
+ esac
+}
+
+# write ordered package prerequisite list to the standard output
+
+order() # [ package ]
+{
+ _order_t_=lib/package/tgz
+ case $action in
+ binary) _order_a_=.$HOSTTYPE ;;
+ *) _order_a_= ;;
+ esac
+ _order_n_=$#
+ case $_order_n_ in
+ 0) _order_p_=
+ for _order_v_ in $VIEW_all
+ do for _order_f_ in $_order_v_/lib/package/*.pkg
+ do if test -f $_order_f_
+ then _order_p_="$_order_p_ $_order_f_"
+ fi
+ done
+ done
+ set '' $_order_p_
+ shift
+ esac
+ {
+ if test ratz != "$*"
+ then for _order_f_ in ratz INIT
+ do if view -s - src $_order_t_/$_order_f_$_order_a_.tim
+ then echo $_order_f_ $_order_f_
+ fi
+ done
+ fi
+ for _order_f_
+ do while :
+ do view - src $_order_f_ && break
+ case $_order_f_ in
+ *.pkg) ;;
+ *) _order_f_=$_order_f_.pkg; view - src $_order_f_ && break ;;
+ esac
+ case $_order_f_ in
+ */*) ;;
+ *) _order_f_=lib/package/$_order_f_; view - src $_order_f_ && break ;;
+ esac
+ echo "$command: $_order_f_: not a package" >&2
+ continue 2
+ done
+ _order_f_=$_view_
+ _order_p_=`echo $_order_f_ | sed -e 's,.*/,,' -e 's,\.pkg$,,'`
+ case $_order_n_ in
+ 0) view -s - src $_order_t_/$_order_p_$_order_a_.tim || continue ;;
+ esac
+ echo $_order_p_ $_order_p_
+ case $_order_p_ in
+ INIT|ratz)
+ ;;
+ *) echo INIT $_order_p_
+ ;;
+ esac
+ {
+ req= req_sep=
+ op=::
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :REQUIRES:)
+ req="$req$req_sep$1"
+ req_sep=" "
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ for _order_i_ in $req
+ do if view - src lib/package/$_order_i_.pkg
+ then case $_order_u_ in
+ 0) view -s - src $_order_t_/$_order_i_$_order_a_.tim || continue ;;
+ esac
+ echo $_order_i_ $_order_i_; echo INIT $_order_i_; echo $_order_i_ $_order_p_
+ fi
+ done
+ } < $_order_f_
+ done
+ } | tsort
+}
+
+# generate the package component list in _components_
+
+components() # [ package ]
+{
+ _components_=
+ for p
+ do case $p in
+ '') ;;
+ INIT) case " $_components_ " in
+ *" $p "*) ;;
+ *) _components_="$_components_ $p" ;;
+ esac
+ ;;
+ *) if view - src lib/package/$p.pkg
+ then p=$_view_
+ op=::
+ exec < $p
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :PACKAGE:)
+ case " $_components_ " in
+ *" $1 "*) ;;
+ *) _components_="$_components_ $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ exec < /dev/null
+ elif test -d $PACKAGEROOT/src/cmd/$p -o -d $PACKAGEROOT/src/lib/$p
+ then _components_="$_components_ $p"
+ else echo "$command: $p: package or component not found" >&2
+ exit 1
+ fi
+ ;;
+ esac
+ done
+}
+
+# list main environment values
+
+showenv()
+{
+ case $1 in
+ ''|make)for __i__ in CC SHELL $env
+ do eval echo $__i__='$'$__i__
+ done
+ ;;
+ esac
+}
+
+# capture command output
+
+capture() # file command ...
+{
+ case $make:$noexec in
+ :) case $action in
+ install|make|view)
+ o=$action
+ ;;
+ *) case $package in
+ ''|*' '*)
+ o=$action
+ ;;
+ *) o=$package
+ ;;
+ esac
+ ;;
+ esac
+ case $action in
+ write) d=$PACKAGESRC/gen ;;
+ *) d=$PACKAGEBIN/gen ;;
+ esac
+ test -d $d || $exec mkdir $d
+ o=$d/$o
+ case $o in
+ $output)o=$o.out
+ s=
+ ;;
+ *) output=$o
+ if test -f $o.old
+ then mv $o.old $o.out.1
+ if test -f $o.out
+ then mv $o.out $o.out.2
+ fi
+ elif test -f $o.out
+ then for i in `ls -t $o.out.? 2>/dev/null`
+ do break
+ done
+ case $i in
+ *.1) i=2 ;;
+ *.2) i=3 ;;
+ *.3) i=4 ;;
+ *.4) i=5 ;;
+ *.5) i=6 ;;
+ *.6) i=7 ;;
+ *.7) i=8 ;;
+ *.8) i=9 ;;
+ *) i=1 ;;
+ esac
+ mv $o.out $o.out.$i
+ fi
+ o=$o.out
+ : > $o
+ note $action output captured in $o
+ s="$command: $action start at `date` in $INSTALLROOT"
+ case $quiet in
+ 0) trap "echo \"$command: $action done at \`date\`\" in $INSTALLROOT 2>&1 | \$TEE -a $o" 0 1 2 ;;
+ *) trap "echo \"$command: $action done at \`date\`\" in $INSTALLROOT >> $o" 0 1 2 ;;
+ esac
+ ;;
+ esac
+ case $quiet in
+ 0) if executable ! $TEE
+ then TEE=tee
+ fi
+ {
+ case $s in
+ ?*) echo "$s" ;;
+ esac
+ showenv $action
+ "$@"
+ } < /dev/null 2>&1 | $TEE -a $o
+ ;;
+ *) {
+ case $s in
+ ?*) echo "$s" ;;
+ esac
+ showenv $action
+ "$@"
+ } < /dev/null > $o 2>&1
+ ;;
+ esac
+ ;;
+ *) $make "$@"
+ ;;
+ esac
+}
+
+package_install() # dest sum
+{
+ dest=$1 sum=$2
+ ot=
+ code=0
+ sed -e '/ /!d' -e 's,[^ ]* ,,' -e 's, \(arch/[^/]*\)/, \1 ,' -e '/ arch\//!s,^[^ ]* [^ ]* [^ ]*,& .,' -e 's,/\([^ /]*\)$, \1,' $sum |
+ while read mode user group arch dir file
+ do case $flat:$arch in
+ 1:*|?:.)t=$dest/$dir ;;
+ *) t=$dest/$arch/$dir ;;
+ esac
+ case $t in
+ $ot) ;;
+ *) if test ! -d "$t"
+ then $exec mkdir -p "$t" || exit
+ fi
+ ot=$t
+ ;;
+ esac
+ case $file in
+ ?*) case $arch in
+ .) f=$dir/$file ;;
+ *) f=$arch/$dir/$file ;;
+ esac
+ if test -f "$f"
+ then t=$t/$file
+ case $quiet in
+ 0) echo "$t" ;;
+ esac
+ $exec cp -f "$f" "$t" || code=1
+ $exec chmod $mode "$t" || code=1
+ fi
+ ;;
+ esac
+ done
+ return $code
+}
+
+package_verify() # sum
+{
+ $exec $SUM -cp $1
+}
+
+make_recurse() # dir
+{
+ for _make_recurse_j in $makefiles
+ do if view - $1/$_make_recurse_j
+ then return
+ fi
+ done
+ if test -d $1
+ then case $exec in
+ '') echo :MAKE: > $1/Makefile || exit ;;
+ *) $exec "echo :MAKE: > $1/Makefile" ;;
+ esac
+ fi
+}
+
+get() # host path [ file size ]
+{
+ case $HURL in
+ '') HURL=.
+ for i in wget lynx curl
+ do if onpath $i
+ then HURL=$i
+ break;
+ fi
+ done
+ AUTHORIZE="User-Agent: package AT&T Research\\r\\n"
+ case $HURL:$authorize in
+ .:?*) AUTHORIZE="${AUTHORIZE}Authorization: Basic `print -n -r -- $authorize:$password | uuencode -h -x base64`\\r\\n" ;;
+ esac
+ ;;
+ esac
+ getfd=8
+ case $3 in
+ '') case $HURL in
+ .) host=$1
+ path=$2
+ while :
+ do eval "exec $getfd<> /dev/tcp/$host/80" || exit
+ case $path in
+ /*) ;;
+ *) path=/$path ;;
+ esac
+ print "GET $path HTTP/1.0\\r\\nHost: $host\\r\\n$AUTHORIZE\\r" >&$getfd
+ cat <&8 > get.tmp
+ got=`sed -e 1q get.tmp`
+ case $got in
+ *" "200" "*)
+ got=`sed -e '1,/^.$/d' -e '/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]/!d' get.tmp`
+ : > get.err
+ code=0
+ break
+ ;;
+ *" "30[123]" "*)
+ got=`sed -e '/^Location: /!d' -e 's,^Location: \(.*\)://\([^/]*\)\(/.*\),prot='\''\1'\'' host='\''\2'\'' path='\''\3'\'',' get.tmp`
+ case $got in
+ '') rm get.tmp
+ echo "$command: $action: $url: redirect error" >&2
+ exit 1
+ ;;
+ esac
+ eval $got
+ ;;
+ *) rm get.tmp
+ echo "$command: $action: $url: $got" >&2
+ echo '' "$got" > get.err
+ code=1
+ break
+ ;;
+ esac
+ done
+ ;;
+ curl) case $authorize in
+ '') curl -s -L -o get.tmp http://$1/$2 2> get.err; code=$? ;;
+ *) curl -s -L -o get.tmp -u "$authorize":"$password" http://$1/$2 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp 2>/dev/null`
+ case $code in
+ 0) if grep '^<H1>Authorization Required</H1>' get.tmp > get.err
+ then code=1
+ fi
+ ;;
+ esac
+ ;;
+ hurl) case $authorize in
+ '') hurl http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ *) hurl -a "$authorize":"$password" http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp`
+ ;;
+ lynx) case $authorize in
+ '') lynx -source http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ *) lynx -source -auth "$authorize":"$password" http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp`
+ ;;
+ wget) wget -nv -O get.tmp ${authorize:+--http-user="$authorize"} ${password:+--http-passwd="$password"} http://$1/$2 2> get.err
+ code=$?
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp 2>/dev/null`
+ ;;
+ *) echo $command: $action: $HURL: url get command not found >&2
+ exit 1
+ ;;
+ esac
+ if test 0 != "$code"
+ then case `cat get.err get.tmp 2>/dev/null` in
+ *[Aa][Uu][Tt][Hh][Oo][Rr][Ii][SsZz]*|*[Dd][Ee][Nn][Ii][Ee][Dd]*)
+ echo $command: $action: authorization required -- see $url for license acceptance authorization name and password >&2
+ ;;
+ *) cat get.err
+ ;;
+ esac
+ rm -f get.tmp get.err
+ echo $command: $action: $2: download failed >&2
+ exit 1
+ fi
+ rm -f get.tmp get.err
+ ;;
+ *) case $exec in
+ '') echo "$3 ($4 bytes):" >&2
+ case $HURL in
+ .) eval "exec $getfd<> /dev/tcp/$1/80" || exit
+ path=$2/$3
+ case $path in
+ /*) ;;
+ *) path=/$path ;;
+ esac
+ print "GET $path HTTP/1.0\\r\\nHost: $host\\r\\n$AUTHORIZE\\r" >&$getfd
+ read got <&$getfd
+ case $got in
+ *" 200 "*)
+ code=0
+ : > get.err
+ ;;
+ *) echo '' "$got" > get.err
+ code=1
+ ;;
+ esac
+ while read got <&$getfd
+ do case $got in
+ ''|?) break ;;
+ esac
+ done
+ cat <&$getfd > get.tmp
+ ;;
+ curl) case $authorize in
+ '') curl -s -L -o get.tmp http://$1/$2/$3 2> get.err; code=$? ;;
+ *) curl -s -L -o get.tmp -u "$authorize":"$password" http://$1/$2/$3 2> get.err; code=$?
+ esac
+ case $code in
+ 0) if grep '^<H1>Authorization Required</H1>' get.tmp > get.err
+ then code=1
+ fi
+ ;;
+ esac
+ ;;
+ hurl) case $authorize in
+ '') ksh -x hurl http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ *) ksh -x hurl -a "$authorize":"$password" http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ esac
+ ;;
+ lynx) case $authorize in
+ '') lynx -source http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ *) lynx -source -auth "$authorize":"$password" http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ esac
+ ;;
+ wget) wget -nv -O get.tmp ${authorize:+--http-user="$authorize"} ${password:+--http-passwd="$password"} http://$1/$2/$3 2> get.err
+ code=$?
+ ;;
+ *) echo $command: $action: $HURL: url get command not found >&2
+ exit 1
+ ;;
+ esac
+ if test 0 != "$code"
+ then case `cat get.err get.tmp` in
+ *[Aa][Uu][Tt][Hh][Oo][Rr][Ii][SsZz]*|*[Dd][Ee][Nn][Ii][Ee][Dd]*)
+ echo $command: $action: authorization required -- see $url for license acceptance authorization name and password >&2
+ ;;
+ *) cat get.err
+ ;;
+ esac
+ rm get.tmp get.err
+ echo $command: $action: $3: download failed >&2
+ exit 1
+ fi
+ rm get.err
+ case $checksum:$5 in
+ :*|*:-) z=`wc -c < get.tmp`
+ case " $z " in
+ *" $4 "*)
+ ;;
+ *) rm -f get.tmp
+ echo $command: $3: download error: expected $4 bytes, got $z >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *) z=`$checksum < get.tmp | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'`
+ case " $z " in
+ *" $5 "*)
+ ;;
+ *) rm -f get.tmp
+ echo $command: $3: download $checksum error: expected $5, got $z >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ mv get.tmp $3 || exit
+ ;;
+ *) echo "$3 ($4 bytes)" >&2
+ ;;
+ esac
+ esac
+}
+
+# generate copyright notice
+
+copyright()
+{
+ if test -f $1.lic
+ then echo $1 package general copyright notice
+ echo
+ proto -c'#' -p -s -l $1.lic -o type=verbose,author='*' /dev/null
+ return 0
+ fi
+ case $1 in
+ *-*) eval `echo '' $1 | sed 's/\([^-]*\)-\(.*\)/__j__="\1" __i__="\2"/'`
+ if copyright $__i__ || copyright $__j__
+ then return 0
+ fi
+ ;;
+ esac
+ return 1
+}
+
+# run remote make on host
+
+remote() # host no-exec-background
+{
+ host=$1
+ background=$2
+ eval name=\$${host}_name user=\$${host}_user snarf=\$${host}_snarf type=\$${host}_type rsh=\$${host}_rsh root=\$${host}_root keep=\$${host}_keep log=\$${host}_log
+ case $keep in
+ 1*) ;;
+ *) return ;;
+ esac
+ case $host in
+ $main) ;;
+ *) case $exec in
+ '') exec > $admin_log/$log 2>&1 ;;
+ *) echo "exec > $admin_log/$log 2>&1" ;;
+ esac
+ ;;
+ esac
+ if $admin_ping $name >/dev/null 2>&1 || $admin_ping $name >/dev/null 2>&1
+ then cmd=". ./.profile"
+ case $root in
+ .) root=
+ ;;
+ *) cmd="$cmd && cd $root"
+ root=$root/
+ ;;
+ esac
+ cmd="$cmd && { test -f lib/package/admin/$admin_env && . ./lib/package/admin/$admin_env || true ;} && PATH=\${PWD:-\`pwd\`}/bin:\$PATH \${SHELL:-/bin/sh} -c 'package $admin_args PACKAGEROOT=\${PWD:-\`pwd\`} HOSTTYPE=$type VPATH='"
+ case $admin_binary in
+ '') snarf= ;;
+ esac
+ case $snarf in
+ '') $exec $rsh $user$name "$cmd" $background
+ ;;
+ *?) rcp=`echo $rsh | sed 's/\(.\).*/\1/'`cp
+ case $background in
+ ?*) $exec "{" ;;
+ esac
+ $exec $rsh $user$name "$cmd"
+ eval lst=$admin_list
+ case $admin_pkgs in
+ '') filter=cat ;;
+ *) filter="egrep lib/package/tgz/($admin_pkgs)\\." ;;
+ esac
+ if $exec $rcp $user$name:${root}lib/package/tgz/$lst $PACKAGESRC/tgz
+ then $exec $rcp `$filter $PACKAGESRC/tgz/$lst | sed "s,^,$user$name:,"` $PACKAGESRC/tgz
+ else echo "$command: $user$name:${root}lib/package/tgz/$lst: not found" >&2
+ fi
+ case $background in
+ ?*) $exec "} $background" ;;
+ esac
+ ;;
+ esac
+ else echo "$command: $name: down" >&2
+ fi
+}
+
+# update package_src
+
+checksrc()
+{
+ case $package_src in
+ '') package_src=$src
+ for _i_ in `cd $PACKAGESRC; ls *.def *.lic *.pkg 2>/dev/null | sed 's/[-.].*//'`
+ do case " $package_src " in
+ *" $_i_ "*)
+ ;;
+ *) package_src="$package_src $_i_"
+ ;;
+ esac
+ done
+ ;;
+ esac
+}
+
+# check for native ascii 0:yes 1:no
+
+__isascii__=
+
+isascii()
+{
+ case $__isascii__ in
+ '') case `echo A | od -o | sed -e 's/[ ]*$//' -e '/[ ]/!d' -e 's/.*[ ]//'` in
+ 005101|040412) __isascii__=0 ;;
+ *) __isascii__=1 ;;
+ esac
+ esac
+ return $__isascii__
+}
+
+case $action in
+
+admin) while test ! -f $admin_db
+ do case $admin_db in
+ /*) echo $command: $action: $admin_db: data file not found >&2
+ exit 1
+ ;;
+ esac
+ view file src lib/package/admin/$admin_db || exit 1
+ admin_db=$_view_
+ done
+ admin_components=
+ case $admin_action in
+ list) cat $admin_db
+ exit
+ ;;
+ test) set $admin_args
+ while :
+ do case $# in
+ 1) break ;;
+ esac
+ shift
+ case $1 in
+ *=*) ;;
+ *) admin_components=-$1
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ : all work done in $PACKAGESRC/admin
+ cd $PACKAGESRC/admin || exit
+ checksrc
+ packages=
+ admin_log=${admin_action}${admin_components}.log
+ exec < $admin_db || exit
+ test -d $admin_log || $exec mkdir $admin_log || exit
+ case $admin_on in
+ '') admin_on="*" ;;
+ esac
+ hostname=
+ hosts=
+ logs=
+ local_hosts=
+ local_types=
+ pids=
+ remote_hosts=
+ sync_hosts=
+ admin_host=_admin_host_
+ admin_out=
+ case " $admin_args " in
+ *" write binary "*|*" write "*" binary "*)
+ admin_binary=1
+ ;;
+ *) admin_binary=
+ ;;
+ esac
+ case $only in
+ 1) admin_args="only $admin_args" ;;
+ esac
+ trap 'kill $pids >/dev/null 2>&1' 1 2 3 15
+ index=0
+ while read type host root date time make test write comment
+ do case $type in
+ ''|'#'*);;
+ *=*) eval "$type $host $root $date $time $make $test $write $comment"
+ ;;
+ *) case $admin_action in
+ make|test|write)
+ eval f='$'$admin_action
+ case $f in
+ *[!0123456789]*) continue ;;
+ esac
+ ;;
+ esac
+ rsh=rsh
+ case $host in
+ *@*) IFS=@
+ set '' $host
+ IFS=$ifs
+ user=${2}@
+ host=$3
+ ;;
+ *) user=
+ ;;
+ esac
+ : type=$type host=$host root=$root date=$date time=$time make=$make test=$test write=$write :
+ name=$host
+ host=`echo $name | sed 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789],__,g'`
+ eval x='$'${host}_index
+ eval ${host}_index=1
+ case $x in
+ 1) i=0
+ while :
+ do case $i in
+ $index) h=''
+ break
+ ;;
+ esac
+ i=`expr $i + 1`
+ eval h='$'${admin_host}${i}_name
+ case $h in
+ $host) host=${admin_host}${i}
+ eval user='$'${host}_user root='$'${host}_rsh:$host:'$'${host}_root
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $root in
+ *:$name:*)root=`echo '' $root | sed 's,:.*,:,'` ;;
+ esac
+ case $root in
+ *:*:*) index=`expr $index + 1`
+ host=${admin_host}$index
+ ;;
+ *:*) case " $sync_hosts " in
+ *" $name ${admin_host}"*)
+ set '' '' $sync_hosts
+ while :
+ do shift
+ shift
+ case $1 in
+ $name) host=$2
+ break
+ ;;
+ esac
+ done
+ ;;
+ *) index=`expr $index + 1`
+ host=${admin_host}$index
+ sync_hosts="$sync_hosts $name $host"
+ ;;
+ esac
+ ;;
+ *) index=`expr $index + 1`
+ host=${admin_host}$index
+ ;;
+ esac
+ case $root in
+ -*) continue
+ ;;
+ *:*) case $admin_all in
+ 0) continue ;;
+ esac
+ case $root in
+ *:) root=${root}. ;;
+ esac
+ IFS=:
+ set '' $root
+ IFS=$ifs
+ sync=$host
+ case $hostname in
+ '') hostinfo name
+ hostname=$_hostinfo_
+ ;;
+ esac
+ shift
+ case $# in
+ 0) ;;
+ 1) root=$1
+ ;;
+ 2) rsh=$1 root=$2
+ ;;
+ *) rsh=$1 sync=$2 root=$3
+ case $sync in
+ ${admin_host}*)
+ ;;
+ ?*) case " $sync_hosts " in
+ *" $sync ${admin_host}"*)
+ set '' '' $sync_hosts
+ while :
+ do shift
+ shift
+ case $1 in
+ $sync) sync=$2
+ break
+ ;;
+ esac
+ done
+ ;;
+ *) index=`expr $index + 1`
+ x=${admin_host}$index
+ sync_hosts="$sync_hosts $sync $x"
+ sync=$x
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) sync=
+ ;;
+ esac
+ case $name in
+ $admin_on)
+ keep=1
+ ;;
+ *) case " $admin_on " in
+ *" $name "*) keep=1 ;;
+ *) keep=0 ;;
+ esac
+ ;;
+ esac
+ case " $admin_out " in
+ *" $name "*)
+ log=$name.$type
+ ;;
+ *) admin_out="$admin_out $name"
+ log=$name
+ ;;
+ esac
+ case $sync in
+ '') local_types="$local_types $type" ;;
+ esac
+ case $sync in
+ $host) remote_hosts="$remote_hosts $host"
+ ;;
+ ?*) eval ${sync}_share=\"\$${sync}_share $host\"
+ ;;
+ '') local_hosts="$local_hosts $host"
+ ;;
+ esac
+ eval ${host}_name='$'name ${host}_type='$'type ${host}_user='$'user ${host}_sync='$'sync ${host}_snarf='$'sync ${host}_rsh='$'rsh ${host}_root='$'root ${host}_keep='$'keep ${host}_log='$'log
+ ;;
+ esac
+ done
+ p=
+ for i in $admin_args
+ do p="$i $p"
+ done
+ admin_pkgs=
+ for i in $p
+ do if view - src "lib/package/$i.pkg"
+ then case $admin_pkgs in
+ '') admin_pkgs="$i" ;;
+ *) admin_pkgs="$admin_pkgs|$i" ;;
+ esac
+ fi
+ done
+ : "admin_binary :" $admin_binary
+ : "admin_args :" $admin_args
+ : "admin_pkgs :" $admin_pkgs
+ : "admin_on :" "$admin_on"
+ : "local_hosts :" $local_hosts
+ : "local_types :" $local_types
+ : "remote_hosts :" $remote_hosts
+ : "sync_hosts :" $sync_hosts
+ : "sync_share :" $sync_share
+ case $admin_binary in
+ 1) admin_bin_types=
+ admin_bin_main=
+ for main in $local_hosts $remote_hosts
+ do eval share=\$${main}_share keep=\$${main}_keep
+ case $keep in
+ 0*) continue ;;
+ esac
+ for host in $main $share
+ do case " $admin_bin_hosts " in
+ *" $host "*)
+ continue
+ ;;
+ esac
+ eval type=\$${host}_type
+ case " $admin_bin_types " in
+ *" $type "*)
+ continue
+ ;;
+ esac
+ case " $types " in
+ " ") ;;
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ admin_bin_hosts="$admin_bin_hosts $host"
+ admin_bin_types="$admin_bin_types $type"
+ case " $admin_bin_hosts " in
+ *" $main "*)
+ ;;
+ *) case " $admin_bin_main " in
+ *" $main "*)
+ ;;
+ *) admin_bin_main="$admin_bin_main $main"
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ local=
+ remote=
+ for host in $admin_bin_main $admin_bin_hosts
+ do case " $local_hosts " in
+ *" $host "*)
+ local="$local $host"
+ ;;
+ *) case " $remote_hosts " in
+ *" $host "*)
+ remote="$remote $host"
+ ;;
+ esac
+ ;;
+ esac
+ done
+ local_hosts=$local
+ remote_hosts=$remote
+ ;;
+ esac
+ for host in $remote_hosts $local_hosts
+ do eval share=\$${host}_share
+ case $share in
+ ?*) while :
+ do oshare=$share
+ for s in $share
+ do eval r='$'${s}_share
+ case $r in
+ ?*) case " $share " in
+ *" $r "*) ;;
+ *) share="$share $r" ;;
+ esac
+ ;;
+ esac
+ done
+ case $share in
+ $oshare) eval ${host}_share="'$share'"
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ done
+ for host in $remote_hosts
+ do eval type=\$${host}_type
+ case " $local_types " in
+ *" $type "*)
+ eval ${host}_snarf=
+ ;;
+ esac
+ eval name=\$${host}_name keep=\$${host}_keep share=\$${host}_share
+ for share in $share
+ do eval type=\$${share}_type keep=\$keep\$${share}_keep
+ case " $local_types " in
+ *" $type "*)
+ eval ${share}_snarf=
+ ;;
+ esac
+ done
+ case $keep in
+ 0*1*) keep=2$keep ;;
+ *1*) ;;
+ *) keep=0 ;;
+ esac
+ eval ${host}_keep=$keep
+ done
+ for host in $remote_hosts $local_hosts
+ do eval name=\$${host}_name user=\$${host}_user type=\$${host}_type sync=\$${host}_sync snarf=\$${host}_snarf share=\$${host}_share rsh=\$${host}_rsh root=\$${host}_root keep=\$${host}_keep
+ case $keep in
+ 0*) continue ;;
+ esac
+ case $sync in
+ '') case $admin_action in
+ ditto) continue ;;
+ esac
+ case $admin_binary in
+ 1) case $keep in
+ 1*|?*1*);;
+ *) continue ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ eval main_log='$'${host}_log
+ main=
+ share_keep=
+ for i in $host $share
+ do eval n='$'${i}_name t='$'${i}_type q='$'${i}_sync s='$'${i}_snarf l='$'${i}_log k='$'${i}_keep
+ case $main:$k in
+ :*) ;;
+ *:0) continue ;;
+ esac
+ case $admin_binary in
+ 1) case $s:$q in
+ :?*) continue ;;
+ esac
+ case " $admin_bin_hosts " in
+ *" $i "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ esac
+ case $main in
+ '') main=$i ;;
+ *) share_keep="$share_keep $i" ;;
+ esac
+ echo package "$admin_args" "[ $n $t ]"
+ case $exec in
+ '') : > $admin_log/$l ;;
+ *) $exec ": > $admin_log/$l" ;;
+ esac
+ done
+ host=$main
+ share=$share_keep
+ case $force in
+ 0) admin_ditto_update=--update ;;
+ *) admin_ditto_update= ;;
+ esac
+ case $exec in
+ '') {
+ case $admin_binary:$sync in
+ :?*) eval syncname='$'${sync}_name
+ test -x $PACKAGEROOT/bin/package && $admin_ditto $admin_ditto_update --remote=$rsh --expr="name=='package'" $PACKAGEROOT/bin $user$syncname:$root/bin
+ test -d $PACKAGESRC && $admin_ditto $admin_ditto_update --remote=$rsh --expr="if(level>1&&path!='LICENSES/*')status=SKIP;path=='LICENSES*|*.(pkg|lic|def)'" $PACKAGESRC $user$syncname:$root/lib/package
+ for dir in $package_src
+ do case $MAKESKIP in
+ '') expr="--expr=if(name=='$admin_ditto_skip')status=SKIP" ;;
+ *) expr="--expr=if(name=='$admin_ditto_skip'||level==1&&name=='$MAKESKIP')status=SKIP" ;;
+ esac
+ test -d $PACKAGEROOT/src/$dir && $admin_ditto $admin_ditto_update --remote=$rsh "$expr" $PACKAGEROOT/src/$dir $user$syncname:$root/src/$dir
+ done
+ ;;
+ esac
+ case $admin_action in
+ ditto) ;;
+ ?*) pids=
+ set '' $host $share
+ while :
+ do shift
+ case $# in
+ 0) break
+ ;;
+ 1) remote $1
+ ;;
+ *) remote $1 &
+ pids="$pids $!"
+ ;;
+ esac
+ done
+ case $pids in
+ ?*) wait $pids ;;
+ esac
+ ;;
+ esac
+ } < /dev/null > $admin_log/$main_log 2>&1 &
+ pids="$pids $!"
+ ;;
+ *) echo "{"
+ case $admin_binary:$sync in
+ :?*) eval syncname='$'${sync}_name
+ test -d $PACKAGESRC && echo $admin_ditto $admin_ditto_update --remote=$rsh --expr="if(level>1)status=SKIP;name=='*.(pkg|lic|def)'" $PACKAGESRC $user$syncname:$root/lib/package
+ for dir in $package_src
+ do case $MAKESKIP in
+ '') expr="--expr=if(name=='$admin_ditto_skip')status=SKIP" ;;
+ *) expr="--expr=if(name=='$admin_ditto_skip'||level==1&&name=='$MAKESKIP')status=SKIP" ;;
+ esac
+ test -d $PACKAGEROOT/src/$dir && echo $admin_ditto $admin_ditto_update --remote=$rsh "$expr" $PACKAGEROOT/src/$dir $user$syncname:$root/src/$dir
+ done
+ ;;
+ esac
+ case $admin_action in
+ ditto) ;;
+ ?*) pids=
+ set '' $host $share
+ while :
+ do shift
+ case $# in
+ 0) break
+ ;;
+ 1) remote $1
+ ;;
+ *) remote $1 "&"
+ pids=1
+ ;;
+ esac
+ done
+ case $pids in
+ 1) echo wait ;;
+ esac
+ ;;
+ esac
+ echo "} < /dev/null > $admin_log/$main_log 2>&1 &"
+ ;;
+ esac
+ eval name='$'${main}_name
+ hosts="$hosts $name"
+ logs="$logs $main_log"
+ for share in $share
+ do eval keep=\$${share}_keep
+ case $keep in
+ 1) eval name='$'${share}_name log='$'${share}_log
+ hosts="$hosts $name"
+ logs="$logs $log"
+ ;;
+ esac
+ done
+ done
+ case $exec in
+ '') # track the progress
+ case $quiet in
+ 0) cd $admin_log
+ tail -t $PACKAGE_admin_tail_timeout -f $logs
+ cd ..
+ ;;
+ esac
+ # wait for the remote actions to complete
+ wait
+ trap - 1 2 3 15
+ # update the db
+ exec < $admin_db || exit
+ exec 9>&1
+ D=`date +%y%m%d`
+ while read line
+ do set -- $line
+ case $1 in
+ ''|'#'*|*=*)
+ ;;
+ *) case " $hosts " in
+ *" $2 "*)
+ : ast date command assumed :
+ E=`eval date -E \`egrep '[ ](start|done)[ ][ ]*at[ ]' $admin_log/$2 | sed -e 's/.*[ ][ ]*at[ ][ ]*//' -e 's/[ ][ ]*in[ ].*$//' -e 's/.*/"&"/'\``
+ M=$6 T=$7 W=$8
+ case $admin_action in
+ make|view)
+ M=`egrep -c ']:.* (\*\*\*.* code|don'\''t know) | \*\*\* termination code ' $admin_log/$2` ;;
+ test) T=`grep -ci 'fail[es]' $admin_log/$2` ;;
+ *) W=`grep '^[abcdefghijklmnopqrstuvwxyz][abcdefghijklmnopqrstuvwxyz]*:.' $admin_log/$2 | egrep -cv 'start at|done at|output captured|warning:|: package not found|whence: command not found'` ;;
+ esac
+ case $1 in
+ ?|??|???|????|?????|??????|???????)
+ t1=' '
+ ;;
+ ????????|?????????|??????????|???????????|????????????|?????????????|??????????????|???????????????)
+ t1=' '
+ ;;
+ *) t1=''
+ ;;
+ esac
+ case $2 in
+ ?|??|???|????|?????|??????|???????)
+ t2=' '
+ ;;
+ *) t2=''
+ ;;
+ esac
+ case $3 in
+ ?|??|???|????|?????|??????|???????)
+ t3=' '
+ ;;
+ *) t3=''
+ ;;
+ esac
+ case $E in
+ ?????) E=" $E" ;;
+ ????) E=" $E" ;;
+ ???) E=" $E" ;;
+ ??) E=" $E" ;;
+ ?) E=" $E" ;;
+ esac
+ case $M in
+ ???) M="$M" ;;
+ ??) M=" $M" ;;
+ ?) M=" $M" ;;
+ '') M=" 0" ;;
+ esac
+ case $T in
+ ???) T="$T" ;;
+ ??) T=" $T" ;;
+ ?) T=" $T" ;;
+ '') T=" 0" ;;
+ esac
+ case $W in
+ ???) W="$W" ;;
+ ??) W=" $W" ;;
+ ?) W=" $W" ;;
+ '') W=" 0" ;;
+ esac
+ A=$1$t1
+ H=$2$t2
+ R=$3$t3
+ case $# in
+ [0-8]) C=
+ ;;
+ *) shift 8
+ C=" $*"
+ ;;
+ esac
+ echo "$A $H $R $D $E $M $T $W$C"
+ echo "$A $H $R $D $E $M $T $W$C" >&9
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ echo "$line"
+ done > $admin_db.new
+ mv $admin_db $admin_db.old
+ mv $admin_db.new $admin_db
+ ;;
+ esac
+ ;;
+
+clean|clobber)
+ cd $PACKAGEROOT
+ $exec rm -rf $INSTALLROOT
+ exit
+ ;;
+
+contents|list)
+ # all work in $PACKAGESRC
+
+ cd $PACKAGESRC
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' *.pkg
+ case $2 in
+ '*.pkg')
+ echo $command: $action: no packages >&2
+ exit 1
+ ;;
+ esac
+ set '' `echo $* | sed 's,\.pkg,,g'`
+ shift
+ ;;
+ esac
+ sep="$nl "
+ echo packages in $PACKAGEROOT
+ case $action in
+ list) echo
+ echo "NAME${nl}VERSION${nl}RELEASE${nl}TYPE${nl}STATUS${nl}REQUIRES${nl}----${nl}-------${nl}-------${nl}----${nl}------${nl}--------" | pr -6 -a -o4 -t
+ ;;
+ esac
+ {
+ omit=:
+ for pkg
+ do if test ! -f $pkg.pkg
+ then echo $command: $action: $pkg: not a package >&2
+ else if test -f gen/$pkg.ver
+ then set '' `cat gen/$pkg.ver`
+ case $3 in
+ $2) ver=base ;;
+ *) ver=$3 ;;
+ esac
+ if test -s tgz/$pkg.tim
+ then sts=local
+ else sts=
+ fi
+ else ver=
+ sts=unwritten
+ fi
+ typ=
+ txt=
+ cmp= cmp_sep=
+ req= req_sep=
+ op=::
+ exec < $pkg.pkg
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :DESCRIPTION:)
+ txt="$txt$sep$line"
+ break
+ ;;
+ :PACKAGE:)
+ cmp="$cmp$cmp_sep$1"
+ cmp_sep=$nl
+ ;;
+ :REQUIRES:)
+ req="$req$req_sep$1"
+ req_sep=" "
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ exec < /dev/null
+ case $txt in
+ ?*) txt="$nl$txt" ;;
+ esac
+ case :$ver: in
+ *::*) ;;
+ *) case $action in
+ list) case $sts in
+ '') case `ls -t "tgz/$pkg.$ver.base" "tgz/$pkg.tim" 2>/dev/null` in
+ "tgz/$pkg.tim"*)
+ sts=read
+ ;;
+ *) sts=unread
+ ;;
+ esac
+ ;;
+ esac
+ echo "$pkg${nl}$ver${nl}base${nl}$typ${nl}$sts${nl}$req"
+ case $typ in
+ '') omit=$omit$pkg.$ver.base: ;;
+ esac
+ ;;
+ *) case $req in
+ ?*) req=": $req" ;;
+ esac
+ echo
+ echo $pkg $ver $req "$txt"
+ case $cmp in
+ ?*) echo "${sep}Components in this package:$nl"
+ echo "$cmp" | pr -4 -o4 -t ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ case $argc:$action in
+ 0:list) if test -d tgz
+ then cd tgz
+ # f:file p:package v:version r:release t:type u:update
+ for f in `find . -name '*?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]*' -print | sed 's,^\./,,' | sort -r`
+ do eval `echo "$f" | sed -e 's,\.c$,,' -e 's,\.gz$,,' -e 's,\.exe$,,' -e 's,\.tgz$,,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]\([0123456789][0123456789][0123456789][0123456789][^_.]*\)[_.]*\(.*\),p=\1 v=\2 r=\3 t=\4,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]*\(.*\),p=\1 v=\2 r=base t=\3,'`
+ case $t in
+ '') case $omit in
+ *:$p.$v.$r:*) continue ;;
+ esac
+ u=$p.tim
+ ;;
+ *) u=$p.$t.tim
+ ;;
+ esac
+ if test -s "$u"
+ then s=local
+ elif test -f "$u"
+ then case `ls -t "$f" "$u" 2>/dev/null` in
+ "$u"*) s=read ;;
+ *) s=unread ;;
+ esac
+ else s=unread
+ fi
+ echo "$p$nl$v$nl$r$nl$t$nl$s$nl"
+ done
+ fi
+ ;;
+ esac
+ } |
+ case $action in
+ list) pr -6 -a -o4 -t | sort -u ;;
+ *) cat ;;
+ esac
+ case $argc in
+ 0) if test -d $PACKAGEROOT/arch
+ then echo
+ echo architectures in $PACKAGEROOT
+ echo
+ for i in `ls $PACKAGEROOT/arch`
+ do if test -f $PACKAGEROOT/arch/$i/lib/package/gen/host
+ then h=`cat $PACKAGEROOT/arch/$i/lib/package/gen/host`
+ else h=
+ fi
+ echo $i
+ echo $h
+ echo
+ echo
+ done | pr -4 -a -o4 -t
+ fi
+ ;;
+ esac
+ ;;
+
+copyright)
+ # all work in $PACKAGESRC
+
+ cd $PACKAGESRC
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' `echo *.lic | sed 's,\.lic,,g'`
+ shift
+ case $1 in
+ '*') echo $command: $action: no packages >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ checkaout proto || exit
+ for i
+ do copyright $i
+ done
+ ;;
+
+export) case $INSTALLROOT in
+ $PACKAGEROOT)
+ INSTALLROOT=$INSTALLROOT/arch/$HOSTTYPE
+ ;;
+ esac
+ case $only in
+ 0) v='$i=' ;;
+ *) v= ;;
+ esac
+ set '' $target $package
+ case $# in
+ 1) set '' $env ;;
+ esac
+ while :
+ do case $# in
+ 1) break ;;
+ esac
+ shift
+ i=$1
+ eval echo ${v}'$'${i}
+ done
+ ;;
+
+install)cd $PACKAGEROOT
+ set '' $package
+ shift
+ case $only in
+ 0) set '' `order "$@"`
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: at least one package name expected" >&2
+ exit 1
+ ;;
+ esac
+ package=$*
+ requirements - $package
+ set '' $target
+ shift
+ case $1 in
+ flat) flat=1 # backwards compatibility -- documentation dropped
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: $action: target directory argument expected" >&2
+ exit 1
+ ;;
+ esac
+ target=
+ while :
+ do case $# in
+ 1) directory=$1
+ break
+ ;;
+ esac
+ target="$target $1"
+ shift
+ done
+ if test ! -d $directory
+ then echo "$command: $action: $directory: target directory not found" >&2
+ exit 1
+ fi
+ case $target in
+ '') cd arch
+ set '' *
+ shift
+ target=$*
+ cd ..
+ ;;
+ esac
+ code=0
+ makecheck=1
+ for a in $target
+ do case $a in
+ -) a=$HOSTTYPE ;;
+ esac
+ case $flat:$a in
+ 1:*|?:.)dest=$directory
+ ;;
+ *) dest=$directory/arch/$a
+ if test "" = "$exec" -a ! -d $dest
+ then mkdir -p $dest || {
+ echo "$command: $dest: destination directory must exist" >&2
+ exit 1
+ }
+ fi
+ ;;
+ esac
+ for i in $package
+ do if test "ratz" = "$i"
+ then : skip
+ elif test -f arch/$a/lib/package/gen/$i.sum
+ then package_install $directory arch/$a/lib/package/gen/$i.sum || code=1
+ elif test ! -d arch/$a/bin
+ then echo "$command: $a: invalid architecture" >&2
+ elif test ! -d $dest
+ then echo "$command: $dest: destination directory must exist" >&2
+ else if test "" != "$makecheck"
+ then if onpath $MAKE
+ then MAKE=$_onpath_
+ else echo "$command: $MAKE: not found" >&2
+ exit 1
+ fi
+ makecheck=
+ fi
+ if test "" != "$exec"
+ then (
+ trap - 0 1 2 15
+ echo "=== $i installation manifest ==="
+ cd arch/$a
+ (
+ cd lib/package
+ INSTALLROOT=$PACKAGEROOT/arch/$a
+ VPATH=$INSTALLROOT:$PACKAGEROOT:$VPATH
+ export INSTALLROOT VPATH
+ $MAKE -s $makeflags -f $i.pkg $qualifier list.installed $assign
+ ) | sort -u
+ )
+ else (
+ set -
+ cd arch/$a
+ (
+ cd lib/package
+ INSTALLROOT=$PACKAGEROOT/arch/$a
+ VPATH=$INSTALLROOT:$PACKAGEROOT:$VPATH
+ export INSTALLROOT VPATH
+ echo lib/$command
+ $MAKE -s $makeflags -f $i.pkg $qualifier list.installed $assign
+ ) | sort -u | pax -drw -ps $dest
+ )
+ fi
+ fi
+ done
+ done
+ exit $code
+ ;;
+
+license)# all work in $PACKAGESRC/LICENSES
+
+ cd $PACKAGESRC/LICENSES || exit
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' *
+ shift
+ case $1 in
+ '*') echo $command: $action: no licenses >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *) checkaout proto || exit
+ a=
+ for i
+ do while :
+ do if test -f ../$i.lic
+ then j=`proto -df -l ../$i.lic -o query=type /dev/null 2>/dev/null`
+ case $j in
+ ?*) if test -f $j
+ then case " $a " in
+ *" $j "*) ;;
+ *) a="$a $j" ;;
+ esac
+ fi
+ break
+ ;;
+ esac
+ fi
+ case $i in
+ *-*) i=`echo $i | sed 's/-[^-]*$//'`
+ ;;
+ *) echo "$command: $i: package license not found" >&2
+ break
+ ;;
+ esac
+ done
+ done
+ set '' $a
+ shift
+ ;;
+ esac
+ for i
+ do case $exec in
+ '') echo
+ echo " --- $i source license ---"
+ echo
+ cat $i
+ ;;
+ *) echo $PACKAGESRC/LICENSES/$i
+ ;;
+ esac
+ done
+ ;;
+
+make|view)
+ cd $PACKAGEROOT
+ case $package in
+ '') lic="lib/package/*.lic"
+ ;;
+ *) for i in $package
+ do lic="$lic lib/package/$i.lic"
+ case $i in
+ *-*) lic="$lic lib/package/"`echo $i | sed 's,-.*,,'`".lic" ;;
+ esac
+ done
+ ;;
+ esac
+ checksrc
+ requirements source $package
+ components $package
+ package=$_components_
+
+ # check for some required commands
+
+ must="$AR"
+ warn="$NM yacc bison"
+ test="$must $warn"
+ have=
+ IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ for t in $test
+ do if executable $t
+ then have="$have $t"
+ fi
+ done
+ for d
+ do for t in $test
+ do case " $have " in
+ *" $t "*)
+ ;;
+ *) if executable $d/$t
+ then have="$have $t"
+ fi
+ ;;
+ esac
+ done
+ done
+ case " $have " in
+ *" bison "*) ;;
+ *" yacc "*) have="$have bison" ;;
+ esac
+ case " $have " in
+ *" yacc "*) ;;
+ *" bison "*) have="$have yacc" ;;
+ esac
+ for t in $test
+ do case " $have " in
+ *" $t "*)
+ ;;
+ *) case " $must " in
+ *" $t "*)
+ echo "$command: $t: not found -- must be on PATH to $action" >&2
+ exit 1
+ ;;
+ *) echo "$command: warning: $t: not found -- some $action actions may fail" >&2
+ ;;
+ esac
+ ;;
+ esac
+ done
+
+ # verify the top view
+
+ if test ! -d $PACKAGEROOT/src
+ then note no source packages to make
+ exit 0
+ elif test ! -d $INSTALLROOT/src
+ then note initialize the $INSTALLROOT view
+ fi
+ for i in arch arch/$HOSTTYPE
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ for i in bin bin/$OK bin/$OK/lib fun include lib lib/package lib/package/gen src man man/man1 man/man3 man/man8
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ make_recurse src
+ o= k=
+ for i in $makefiles
+ do case $o in
+ ?*) o="$o -o" k="$k|" ;;
+ esac
+ o="$o -name $i"
+ k="$k$i"
+ done
+ o="( $o ) -print"
+ for d in $package_src
+ do i=src/$d
+ if test -d $i
+ then test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ make_recurse $i
+ for j in `cd $i; find . $o 2>/dev/null | sed -e 's,^\./,,' -e '/\//!d' -e 's,/[^/]*$,,' | sort -u`
+ do case $j in
+ $k|$MAKESKIP) continue ;;
+ esac
+ test -d $INSTALLROOT/$i/$j ||
+ $exec mkdir -p $INSTALLROOT/$i/$j || exit
+ done
+ fi
+ done
+ def=
+ for i in $lic
+ do test -f $i || continue
+ cmp -s $i $INSTALLROOT/$i 2>/dev/null ||
+ $exec cp $PACKAGEROOT/$i $INSTALLROOT/$i
+ for j in `grep '^. .*\.def$' $i`
+ do case $j in
+ .) ;;
+ *) case " $def " in
+ *" $i "*) ;;
+ *) def="$def $i" ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ for i in $def
+ do i=lib/package/$i
+ test -f $i || continue
+ cmp -s $i $INSTALLROOT/$i 2>/dev/null ||
+ $exec cp $PACKAGEROOT/$i $INSTALLROOT/$i
+ done
+
+ # check $CC and { ar cc ld ldd } intercepts
+
+ h="${HOSTTYPE} ${HOSTTYPE}.*"
+ case $HOSTTYPE in
+ *.*) t=`echo $HOSTTYPE | sed 's/[.][^.]*//'`
+ h="$h $t"
+ ;;
+ *) t=$HOSTTYPE
+ ;;
+ esac
+ case $t in
+ *[0123456789])
+ t=`echo $t | sed 's/[0123456789]*$//'`
+ h="$h $t"
+ ;;
+ esac
+ case $CC in
+ cc) c=cc
+ b=$INSTALLROOT/bin/$c
+ t=$INSTALLROOT/lib/package/gen/$c.tim
+ intercept=0
+ for k in $h
+ do for s in $INITROOT/$c.$k
+ do test -x "$s" || continue
+ if cmp -s "$s" "$b" >/dev/null 2>&1
+ then intercept=1
+ break 2
+ fi
+ case `ls -t "$t" "$b" "$s" 2>/dev/null` in
+ $t*) ;;
+ $b*) cc=$b
+ ;;
+ $s*) cd $INSTALLROOT/lib/package/gen
+ tmp=pkg$$
+ eval '$'exec echo "'int main(){return 0;}' > $tmp.c"
+ if $exec $s -o $tmp.exe $tmp.c >/dev/null 2>&1 &&
+ test -x $tmp.exe
+ then case $HOSTTYPE in
+ *.mips*)$s -version >/dev/null 2>&1 || s= ;;
+ esac
+ case $s in
+ ?*) $exec sed "s/^HOSTTYPE=.*/HOSTTYPE=$HOSTTYPE/" < "$s" > "$b" || exit
+ $exec chmod +x "$b" || exit
+ cc=$b
+ intercept=1
+ note update $b
+ ;;
+ esac
+ fi
+ $exec rm -f $tmp.*
+ $exec touch "$t"
+ cd $PACKAGEROOT
+ ;;
+ esac
+ break 2
+ done
+ done
+ case $intercept in
+ 1) c=ld
+ b=$INSTALLROOT/bin/$c
+ for k in $h
+ do for s in $INITROOT/$c.$k
+ do test -x "$s" || continue
+ case `ls -t "$b" "$s" 2>/dev/null` in
+ $b*) ;;
+ $s*) $exec cp "$s" "$b"
+ note update $b
+ ;;
+ esac
+ done
+ done
+ ;;
+ esac
+ ;;
+ esac
+ c=ldd
+ b=$INSTALLROOT/bin/$c
+ for t in $h
+ do s=$INITROOT/$c.$t
+ test -x "$s" || continue
+ onpath $c ||
+ case `ls -t "$b" "$s" 2>/dev/null` in
+ $b*) ;;
+ $s*) $exec cp "$s" "$b"
+ note update $b
+ ;;
+ esac
+ done
+# following code stubbed out just in case ar.ibm.risc is needed
+# c=ar
+# b=$INSTALLROOT/bin/$c
+# for t in $h
+# do s=$INITROOT/$c.$t
+# test -x "$s" || continue
+# onpath $c ||
+# case `ls -t "$b" "$s" 2>/dev/null` in
+# $b*) ;;
+# $s*) x=`$s -tv /foo/bar.a 2>&1 | egrep -i 'option|usage'`
+# case $x in
+# '') $exec cp "$s" "$b"
+# note update $b
+# ;;
+# esac
+# ;;
+# esac
+# done
+ case $cc in
+ /*) ;;
+ *) echo "$command: $CC: not found -- set CC=C-compiler" >&2
+ exit 1
+ ;;
+ esac
+ case $exec in
+ '') cd $INSTALLROOT/lib/package/gen
+ tmp=pkg$$
+ echo 'int main(){return 0;}' > $tmp.c
+ if $CC -o $tmp.exe $tmp.c > /dev/null 2> $tmp.err &&
+ test -x $tmp.exe
+ then : ok
+ else echo "$command: $CC: failed to compile this program:" >&2
+ cat $tmp.c >&2
+ if test -s $tmp.err
+ then cat $tmp.err >&2
+ else echo "$command: $CC: not a C compiler" >&2
+ fi
+ rm -f $tmp.*
+ exit 1
+ fi
+ rm -f $tmp.*
+ cd $PACKAGEROOT
+ ;;
+ esac
+
+ # remember the default $CC
+
+ case $CC in
+ cc) ;;
+ *) if test -x $INSTALLROOT/bin/cc
+ then case `sed 1q $INSTALLROOT/bin/cc` in
+ ": $CC :")
+ CC=cc
+ export CC
+ ;;
+ *) assign="$assign CC=\"\$CC\""
+ ;;
+ esac
+ else case $CROSS in
+ 1) assign="$assign CC=\"\$CC\""
+ ;;
+ *) case $exec in
+ '') {
+ echo ": $CC :"
+ echo "$CC \"\$@\""
+ } > $INSTALLROOT/bin/cc
+ chmod +x $INSTALLROOT/bin/cc
+ ;;
+ *) note generate a $INSTALLROOT/bin/cc wrapper for $CC
+ ;;
+ esac
+ CC=cc
+ export CC
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ # no $INITROOT means INIT already installed elsewhere
+
+ if test -d $INITROOT
+ then
+ # update probe scripts
+
+ for i in lib/probe lib/probe/C lib/probe/C/make
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ i=$INSTALLROOT/lib/probe/C/make/probe
+ j=$INITROOT/C+probe
+ k=$INITROOT/make.probe
+ case `ls -t $i $j $k 2>/dev/null` in
+ $i*) ;;
+ *) if test -f $j -a -f $k
+ then note update $i
+ shellmagic
+ case $exec in
+ '') {
+ case $SHELLMAGIC in
+ ?*) echo "$SHELLMAGIC" ;;
+ esac
+ cat $j $k
+ } > $i || exit
+ ;;
+ *) echo "{
+echo $SHELLMAGIC
+cat $j $k
+} > $i"
+ ;;
+ esac
+ $exec chmod +x $i || exit
+ fi
+ ;;
+ esac
+ fi
+
+ # initialize a few mamake related commands
+
+ checkaout mamake proto ratz release || exit
+
+ # execrate if necessary
+
+ if (execrate) >/dev/null 2>&1
+ then execrate=execrate
+ $make cd $INSTALLROOT/bin
+ for i in chmod chgrp cmp cp ln mv rm
+ do if test ! -x $OK/$i -a -x /bin/$i.exe
+ then shellmagic
+ case $exec in
+ '') echo "$SHELLMAGIC"'execrate /bin/'$i' "$@"' > $OK/$i
+ chmod +x $OK/$i
+ ;;
+ *) $exec echo \'"$SHELLMAGIC"'execrate /bin/'$i' "$@"'\'' >' $OK/$i
+ $exec chmod +x $OK/$i
+ ;;
+ esac
+ fi
+ done
+ PATH=$INSTALLROOT/bin/$OK:$PATH
+ export PATH
+ else execrate=
+ fi
+ case $action in
+ view) exit 0 ;;
+ esac
+
+ # all work under $INSTALLROOT/src
+
+ $make cd $INSTALLROOT/src
+
+ # record the build host name
+
+ case $noexec in
+ '') hostinfo name
+ echo "$_hostinfo_" | sed 's,\..*,,' > $PACKAGEBIN/gen/host
+ ;;
+ esac
+
+ # make in parallel if possible
+
+ case $NPROC in
+ '') hostinfo cpu
+ case $_hostinfo_ in
+ 0|1) ;;
+ *) NPROC=$_hostinfo_
+ $show NPROC=$NPROC
+ $show export NPROC
+ export NPROC
+ ;;
+ esac
+ ;;
+ esac
+
+ # separate flags from target list
+
+ case $target in
+ *-*) a=
+ for t in $target
+ do case $t in
+ -[eiknFKNV]*|--*-symbols)
+ makeflags="$makeflags $t"
+ ;;
+ -*) nmakeflags="$nmakeflags $t"
+ ;;
+ *) a="$a $t"
+ ;;
+ esac
+ done
+ target=$a
+ ;;
+ esac
+
+ # generate nmake first if possible
+
+ if executable ! $NMAKE && test -d $PACKAGEROOT/src/cmd/nmake
+ then if nonmake $MAKE
+ then note make $NMAKE with mamake
+ c=$CC
+ a=$assign
+ case $HOSTTYPE in
+ win32*|cygwin*)
+ CC="$CC -D_BLD_STATIC"
+ accept="libast"
+ case $assign in
+ *' CC='*) ;;
+ *) assign="$assign CC=\"\$CC\"" ;;
+ esac
+ ;;
+ *) accept=nmake
+ ;;
+ esac
+ eval capture mamake \$makeflags \$nmakeflags \$noexec install nmake $assign
+ assign=$a
+ CC=$c
+ case $make$noexec in
+ '') if executable ! $NMAKE
+ then echo "$command: $action: errors making $NMAKE" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ if test '' != "$PROTOROOT"
+ then if (vpath $INSTALLROOT - $PROTOROOT - $INSTALLROOT $PACKAGEROOT) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT - $PROTOROOT - $INSTALLROOT $PACKAGEROOT
+ then $show vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+ else VPATH=$INSTALLROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ export VPATH
+ fi
+ fi
+ note believe generated files for $accept
+ eval capture \$NMAKE \$makeflags \$nmakeflags \$noexec recurse believe \$nmakesep $accept $assign
+ $exec touch $INSTALLROOT/bin/.paths
+ note make the remaining targets with $NMAKE
+ else eval capture $MAKE \$makeflags \$nmakeflags \$noexec install nmake $assign
+ case $make$noexec in
+ '') if executable ! $NMAKE
+ then echo "$command: $action: errors making $NMAKE" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ fi
+ fi
+
+ # generate ksh next if possible
+
+ if nonmake $MAKE
+ then : no need to generate ksh next -- it could be the only package
+ elif test "$KEEP_SHELL" != 1 -a -d $PACKAGEROOT/src/cmd/ksh93 && executable ! $KSH
+ then eval capture nmake $nmakeflags \$makeflags \$noexec install ksh93 $assign
+ case $make$noexec in
+ '') if executable ! $KSH
+ then echo "$command: $action: errors making $KSH" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ fi
+
+ # mamprobe data should have been generated by this point
+
+ case $exec in
+ '') if test ! -f $INSTALLROOT/bin/.paths -o -w $INSTALLROOT/bin/.paths
+ then nl="
+"
+ o=`cat $INSTALLROOT/bin/.paths 2>/dev/null`
+ v=
+ n=
+ case $nl$o in
+ *${nl}FPATH=*|*#FPATH=*|*[Nn][Oo]FPATH=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ n="${n}FPATH=../fun"
+ v="${v}FPATH"
+ ;;
+ esac
+ case $nl$o in
+ *${nl}BUILTIN_LIB=*|*#BUILTIN_LIB=*|*[Nn][Oo]BUILTIN_LIB=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ if grep '^setv mam_cc_DIALECT .* EXPORT=[AD]LL' $INSTALLROOT/lib/probe/C/mam/* >/dev/null 2>&1
+ then x=
+ else x='no'
+ fi
+ n="${n}${x}BUILTIN_LIB=cmd"
+ v="${v}BUILTIN_LIB"
+ ;;
+ esac
+ case $n in
+ ?*) case $o in
+ ?*) o=`egrep -v "($v)=" $INSTALLROOT/bin/.paths`$nl ;;
+ esac
+ echo "# use { # no NO } prefix instead of XX to permanently disable #$nl$o$n" > $INSTALLROOT/bin/.paths
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ # run from separate copies since nmake and ksh may be rebuilt
+
+ case $EXECROOT in
+ $INSTALLROOT)
+ $make cd $INSTALLROOT/bin
+ if executable /bin/cp
+ then cp=/bin/cp
+ else cp=cp
+ fi
+ if executable /bin/mv
+ then mv=/bin/mv
+ else mv=mv
+ fi
+ if executable /bin/rm
+ then rm=/bin/rm
+ else rm=rm
+ fi
+ for i in \
+ ksh nmake tee cp ln mv rm \
+ *ast*.dll *cmd*.dll *dll*.dll *shell*.dll
+ do executable $i && {
+ cmp -s $i $OK/$i 2>/dev/null || {
+ test -f $OK/$i &&
+ $exec $execrate $rm $OK/$i </dev/null
+ test -f $OK/$i &&
+ $exec $execrate $mv $OK/$i $OK/$i.old </dev/null
+ test -f $OK/$i &&
+ case $exec:$i in
+ :nmake|:ksh)
+ echo "$command: $OK/$i: cannot update [may be in use by a running process] remove manually and try again" >&2
+ exit 1
+ ;;
+ esac
+ $exec $execrate $cp $i $OK/$i
+ }
+ }
+ done
+ if test -f ../lib/make/makerules.mo
+ then cmp -s ../lib/make/makerules.mo $OK/lib/makerules.mo ||
+ $exec $execrate $cp -p ../lib/make/makerules.mo $OK/lib/makerules.mo ||
+ $exec $execrate $cp ../lib/make/makerules.mo $OK/lib/makerules.mo
+ fi
+ if executable $OK/nmake
+ then MAKE="$INSTALLROOT/bin/$OK/nmake LOCALRULESPATH=$INSTALLROOT/bin/$OK/lib"
+ fi
+ if executable $OK/tee
+ then TEE=$INSTALLROOT/bin/$OK/tee
+ fi
+ if test "$KEEP_SHELL" != 1 && executable $OK/ksh
+ then SHELL=$INSTALLROOT/bin/$OK/ksh
+ export SHELL
+ COSHELL=$SHELL
+ export COSHELL
+ fi
+ case :$PATH: in
+ *:$INSTALLROOT/bin/$OK:*)
+ ;;
+ *) PATH=$INSTALLROOT/bin/$OK:$PATH
+ export PATH
+ ;;
+ esac
+ $make cd $INSTALLROOT/src
+ ;;
+ esac
+
+ # fall back to mamake if nmake not found or too old
+
+ if nonmake $MAKE
+ then note make with mamake
+ case $target in
+ '') target="install" ;;
+ esac
+ eval capture mamake \$makeflags \$noexec \$target $assign
+ else case $target in
+ '') target="install cc-" ;;
+ esac
+ eval capture \$MAKE \$makeflags \$nmakeflags \$noexec recurse \$target \$nmakesep \$package $assign
+ fi
+ ;;
+
+read) case ${PWD:-`pwd`} in
+ $PACKAGEROOT)
+ ;;
+ *) echo "$command: must be in package root directory" >&2
+ exit 1
+ ;;
+ esac
+ PAX=
+ if onpath pax
+ then case `$_onpath_ -rw --?meter 2>&1` in
+ *--meter*) PAX=pax ;;
+ esac
+ fi
+ code=0
+ i=
+ x=
+ remove=
+ touch=
+ set '' $target
+ case $2 in
+ lcl|tgz)tgz=$2
+ shift 2
+ target=$*
+ ;;
+ *) tgz=tgz
+ ;;
+ esac
+ set '' $package $target
+ case $# in
+ 1) verbose=:
+ set '' `ls lib/package/$tgz/*?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ ;;
+ *) verbose=
+ ;;
+ esac
+ shift
+ files=
+ for f
+ do if test -f "$f"
+ then : ok
+ elif test -f "lib/package/$tgz/$f"
+ then f=lib/package/$tgz/$f
+ else set '' `ls -r ${f}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ if test '' != "$2" -a -f "$2"
+ then f=$2
+ else set '' `ls -r lib/package/$tgz/${f}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ if test '' != "$2" -a -f "$2"
+ then f=$2
+ else echo "$command: $f: package archive not found" >&2
+ continue
+ fi
+ fi
+ fi
+ files="$files $f"
+ done
+ case $files in
+ '') echo "$command: lib/package/$tgz: no package archives" >&2
+ exit 1
+ ;;
+ esac
+ set '' `ls -r $files 2>/dev/null`
+ shift
+ f1= f2= f3= f4=
+ for f
+ do case $f in
+ ratz.*|*/ratz.*)
+ f1="$f1 $f"
+ ;;
+ INIT.*|*/INIT.*)
+ f2="$f2 $f"
+ ;;
+ INIT*|*/INIT*)
+ f3="$f3 $f"
+ ;;
+ *) f4="$f4 $f"
+ ;;
+ esac
+ done
+ gen=
+ set '' $f1 $f2 $f3 $f4
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ f=$1
+ case $f in
+ *.gz) : standalone packages unbundled manually
+ continue
+ ;;
+ *.md5) : tarball checksum
+ continue
+ ;;
+ *?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]*)
+ ;;
+ *) echo "$command: $f: not a package archive" >&2
+ code=1
+ continue
+ ;;
+ esac
+ case $f in
+ */*) eval `echo "$f" | sed -e 's,\(.*/\)\(.*\),d=\1 a=\2,'` ;;
+ *) d= a=$f ;;
+ esac
+ # f:file d:dir a:base p:package v:version r:release t:type
+ eval `echo "$a" | sed -e 's,\.c$,,' -e 's,\.gz$,,' -e 's,\.exe$,,' -e 's,\.tgz$,,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]\([0123456789][0123456789][0123456789][0123456789][^_.]*\)[_.]*\(.*\),p=\1 v=\2 r=\3 t=\4,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]*\(.*\),p=\1 v=\2 r=base t=\3,'`
+ case $r in
+ base) y=$p.base ;;
+ *) y=$p.delta ;;
+ esac
+ case " $x " in
+ *" $y "*)
+ continue
+ ;;
+ esac
+ case $t in
+ '') w=$PACKAGESRC
+ q=
+ Q=
+ m=
+ ;;
+ *) w=$PACKAGEROOT/arch/$t/lib/package
+ q=".$t"
+ Q="_$t"
+ m="[_.]$t"
+ ;;
+ esac
+ u=$d$p$q.tim
+ if test -s "$u"
+ then continue
+ else case $force in
+ 0) case `ls -t "$f" "$u" 2>/dev/null` in
+ "$u"*) case $verbose in
+ 1) note $p already read ;;
+ esac
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $p in
+ INIT) if test -f $PACKAGEROOT/bin/package
+ then $exec mv $PACKAGEROOT/bin/package $PACKAGEROOT/bin/package.old
+ fi
+ ;;
+ esac
+ z=
+ case $r in
+ base) # base archive
+ if test ratz = "$p"
+ then # ratz packages are not archives
+ case $t in
+ '') for i in src src/cmd src/cmd/INIT
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ $exec cp $f $PACKAGEROOT/src/cmd/INIT/$p.c
+ ;;
+ *) for i in arch arch/$t arch/$t/bin
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ $exec cp $f $PACKAGEROOT/arch/$t/bin/$p &&
+ $exec chmod +x $PACKAGEROOT/arch/$t/bin/$p
+ ;;
+ esac
+ elif test "" != "$PAX"
+ then $exec pax -L --from=ascii --local -m -ps -rvf "$f" || {
+ code=1
+ continue
+ }
+ else if onpath gunzip && onpath $TAR && isascii
+ then case $TARPROBE in
+ ?*) for i in $TARPROBE
+ do if $TAR ${i}f - /dev/null > /dev/null 2>&1
+ then TARFLAGS=$TARFLAGS$i
+ fi
+ done
+ TARPROBE=
+ ;;
+ esac
+ if gunzip -l < "$f" > /dev/null 2>&1
+ then case $exec in
+ '') $exec gunzip < "$f" | $TAR ${TARFLAGS}f - ;;
+ *) $exec "gunzip < $f | $TAR ${TARFLAGS}f -" ;;
+ esac || {
+ code=1
+ continue
+ }
+ else $exec $TAR ${TARFLAGS}f "$f" || {
+ code=1
+ continue
+ }
+ fi
+ else checkaout ratz && onpath ratz || {
+ code=1
+ continue
+ }
+ RATZ=$_onpath_
+ case $exec in
+ '') echo $f:
+ $exec $RATZ -lm < "$f"
+ ;;
+ *) $exec "$RATZ -lm < $f"
+ ;;
+ esac || {
+ code=1
+ continue
+ }
+ fi
+ if test -f $PACKAGEBIN/gen/$p.sum
+ then while read md5 mode usr grp file
+ do case $file in
+ -*) file=./$file ;;
+ esac
+ case $mode in
+ [01234567][01234567][01234567][01234567])
+ case $grp in
+ -) ;;
+ *) $exec chgrp $grp "$file" ;;
+ esac
+ case $usr in
+ -) ;;
+ *) $exec chown $usr "$file" ;;
+ esac
+ $exec chmod $mode "$file"
+ ;;
+ esac
+ done < $PACKAGEBIN/gen/$p.sum
+ fi
+ fi
+ ;;
+ *) # delta archive
+ test "" != "$PAX" || {
+ echo "$command: $f: pax required to read delta archive" >&2
+ code=1
+ continue
+ }
+ case `echo "$v:
+$r:" | sort` in
+ $r:*) y=$p.base
+ b=${d}${p}_${r}${Q}.tgz
+ test -f "$b" || b=${d}${p}.${r}${q}.tgz
+ test -f "$b" || {
+ case " $gen " in
+ *" $b "*)
+ ;;
+ *) case $# in
+ 1) echo "$command: $f: base archive $b required to read delta" >&2
+ code=1
+ ;;
+ *) shift
+ y=$1
+ shift
+ set '' $y $f "$@"
+ esac
+ continue
+ ;;
+ esac
+ }
+ # -m with delta bug fixed 2005-02-08
+ $exec pax -L --from=ascii --local -ps -rvf "$f" -z "$b" || {
+ code=1
+ continue
+ }
+ note $f: generate new base $d$p.$v$q.tgz
+ $exec pax -rf "$f" -z "$b" -wf $d$p.$v$q.tgz -x tgz || {
+ code=1
+ continue
+ }
+ case $exec in
+ '') echo $p $v $v 1 > $w/gen/$p.ver
+ ;;
+ *) z=$d${p}[_.]$v$q.tgz
+ $exec "echo $p $v $v 1 > $w/gen/$p.ver"
+ gen="$gen $d$p.$v$q.tgz"
+ ;;
+ esac
+ case " $remove " in
+ *" $f "*) ;;
+ *) remove="$remove $f" ;;
+ esac
+ ;;
+ *) b=${d}${p}_${v}${Q}.tgz
+ test -f "$b" || b=${d}${p}.${v}${q}.tgz
+ test -f "$b" || {
+ case " $gen " in
+ *" $b "*)
+ ;;
+ *) case $# in
+ 1) echo "$command: $f: base archive $b required to read delta" >&2
+ code=1
+ ;;
+ *) shift
+ y=$1
+ shift
+ set '' $y $f "$@"
+ esac
+ continue
+ ;;
+ esac
+ }
+ # -m with delta bug fixed 2005-02-08
+ $exec pax -L --from=ascii --local -ps -rvf "$f" -z "$b" || {
+ code=1
+ continue
+ }
+ ;;
+ esac
+ ;;
+ *) echo "$command: $f: unknown archive type" >&2
+ code=1
+ continue
+ ;;
+ esac
+
+ # check for ini files
+
+ if executable $w/$p.ini
+ then $exec $w/$p.ini read || {
+ code=1
+ continue
+ }
+ fi
+
+ # add to the obsolete list
+
+ k=
+ for i in `ls $d$p[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]????$m* $z 2>/dev/null`
+ do case $i in
+ *.md5) continue
+ ;;
+ $d${p}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]$m*)
+ ;;
+ $d${p}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]$m*)
+ continue
+ ;;
+ esac
+ case $k in
+ ?*) case " $remove " in
+ *" $k "*) ;;
+ *) remove="$remove $k" ;;
+ esac
+ ;;
+ esac
+ k=$i
+ done
+ x="$x $y"
+ case " $touch " in
+ *" $u "*) ;;
+ *) touch="$touch $u" ;;
+ esac
+ done
+ if test ! -f $PACKAGEROOT/bin/package -a -f $PACKAGEROOT/bin/package.old
+ then $exec cp $PACKAGEROOT/bin/package.old $PACKAGEROOT/bin/package
+ fi
+
+ # drop obsolete archives
+
+ case $remove in
+ ?*) $exec rm -f $remove ;;
+ esac
+
+ # mark the updated archives
+
+ case $touch in
+ ?*) sleep 1; $exec touch $touch ;;
+ esac
+
+ # check the requirements
+
+ case $code$exec in
+ 0) requirements - $x ;;
+ esac
+ exit $code
+ ;;
+
+regress)if test ! -d $PACKAGEBIN/gen
+ then echo "$command: 'package make' and 'package test' required for regression" >&2
+ exit 1
+ fi
+ dir=$PACKAGEBIN/gen
+ cd $dir
+ for s in out old
+ do case `ls -t regress.$s test.$s 2>/dev/null` in
+ regress*)
+ ;;
+ test*) if test -f regress.$s
+ then $exec mv regress.$s regress.old
+ fi
+ case $exec in
+ '') egrep -i '\*\*\*|FAIL|^TEST.* [123456789][0123456789]* error|core.*dump' test.$s |
+ sed -e '/\*\*\* [0123456789]/d' \
+ -e '/^TEST.\//s,/[^ ]*/,,' \
+ -e 's,[ ][ ]*$,,' \
+ -e 's/[0123456789][0123456789]*:* \([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*[Cc][Oo][Rr][Ee][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*)\)/\1/' \
+ -e 's/\.sh failed at .* with /.sh failed /' \
+ > regress.$s
+ ;;
+ *) $exec filter test failures from $dir/test.$s to $dir/regress.$s
+ ;;
+ esac
+ ;;
+ esac
+ done
+ if test -f regress.out -a -f regress.old
+ then $exec diff -b regress.out regress.old
+ else echo "$command: at least 2 test runs required for regression" >&2
+ exit 1
+ fi
+ ;;
+
+release)count= lo= hi=
+ checksrc
+ checkaout release || exit
+ requirements source $package
+ components $package
+ package=$_components_
+ set '' $target
+ shift
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ case $1 in
+ -) lo= release= ;;
+ *) lo=$1 release="-f $1" ;;
+ esac
+ shift
+ case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ case $1 in
+ -) hi= ;;
+ *) hi=$1 release="$release -t $1" ;;
+ esac
+ shift
+ ;;
+ esac
+ ;;
+ [0123456789]|[0123456789][0123456789]|[0123456789][0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789][0123456789]*)
+ count=$1
+ release="-r $count"
+ shift
+ ;;
+ esac
+ ;;
+ esac
+ case $# in
+ 0) case $package in
+ '') package=* ;;
+ esac
+ ;;
+ *) case $package in
+ '') package=$*
+ ;;
+ *) echo $command: $*: lo-date hi-date arguments expected >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ echo
+ case $count:$lo:$hi in
+ ::) echo "All recorded changes follow." ;;
+ 1::) echo "Changes since the last release follow." ;;
+ ?*::) echo "Changes since the last $count releases follow." ;;
+ 1:?*:) echo "Changes since $lo or the last release follow." ;;
+ *:?*:*) echo "Changes since $lo follow." ;;
+ *::?*) echo "Changes before $hi follow." ;;
+ *) echo "Changes between $lo and $hi follow." ;;
+ esac
+ x=
+ for r in $INSTALLROOT $PACKAGEROOT
+ do for s in $package_src
+ do d=$r/src/$s
+ if test -d $d
+ then cd $d
+ for i in $package
+ do if test -h $i 2>/dev/null
+ then continue
+ fi
+ case " $x " in
+ *" $i "*) continue ;;
+ esac
+ for f in RELEASE CHANGES ChangeLog
+ do if test -f $i/$f
+ then $exec release $release $i/$f
+ x="$x $i"
+ for f in $i/*/$f
+ do if test -f $f
+ then $exec release $release $f
+ fi
+ done
+ break
+ fi
+ done
+ done
+ fi
+ done
+ done
+ ;;
+
+remove) echo "$command: $action: not implemented yet" >&2
+ exit 1
+ ;;
+
+results)set '' $target
+ shift
+ def=make
+ dir=$PACKAGEBIN/gen
+ case $verbose in
+ 0) filter=yes ;;
+ *) filter=cat ;;
+ esac
+ path=0
+ suf=out
+ on=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ admin) dir=$PACKAGESRC/admin
+ ;;
+ error*|fail*)
+ filter=errors
+ ;;
+ make|test|view|write)
+ def=$1
+ case $filter:$1:$SHELL in
+ errors:*:*) ;;
+ *:test:*/ksh*) filter=rt ;;
+ esac
+ ;;
+ old) suf=old
+ ;;
+ on) case $# in
+ 1) echo $command: $action: $1: host pattern argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ case $on in
+ ?*) on="$on|" ;;
+ esac
+ on="$on$1"
+ ;;
+ path) path=1
+ ;;
+ test) def=test
+ filter=rt
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ case $dir in
+ */admin)case $on in
+ '') on="*" ;;
+ *) on="@($on)" ;;
+ esac
+ def=$def.log/$on
+ ;;
+ esac
+ case $# in
+ 0) set "$def" ;;
+ esac
+ m=
+ t=
+ for i
+ do k=0
+ eval set '""' $i - $i.$suf - $dir/$i - $dir/$i.$suf -
+ shift
+ for j
+ do case $j in
+ -) case $k in
+ 1) continue 2 ;;
+ esac
+ ;;
+ *) if test -f $j
+ then k=1
+ case /$j in
+ */test.*) t="$t $j" ;;
+ *) m="$m $j" ;;
+ esac
+ fi
+ ;;
+ esac
+ done
+ echo "$command: $i action output not found" >&2
+ exit 1
+ done
+ sep=
+ case $t in
+ ?*) case $path in
+ 0) for j in $t
+ do echo "$sep==> $j <=="
+ sep=$nl
+ case $filter in
+ cat) $exec cat $j
+ ;;
+ errors) $exec egrep -i '\*\*\*|FAIL[ES]|^TEST.* [123456789][0123456789]* error|core.*dump' $j | sed -e '/^TEST.\//s,/[^ ]*/,,'
+ ;;
+ rt) $exec rt - $j
+ ;;
+ *) $exec egrep -i '^TEST|FAIL' $j
+ ;;
+ esac
+ done
+ ;;
+ 1) echo $t
+ ;;
+ esac
+ ;;
+ esac
+ case $m in
+ ?*) case $path in
+ 0) case $filter in
+ cat) cat $m
+ ;;
+ *) if test -f $HOME/.pkgresults
+ then i="`cat $HOME/.pkgresults`"
+ case $i in
+ '|'*) ;;
+ *) i="|$i" ;;
+ esac
+ else i=
+ fi
+ for j in $m
+ do echo "$sep==> $j <=="
+ sep=$nl
+ case $filter in
+ errors) $exeg egrep '^pax:|\*\*\*' $j
+ ;;
+ *) $exec egrep -iv '^($||[\+\[]|cc[^-:]|kill |make.*(file system time|has been replaced)|so|[0123456789]+ error|uncrate |[0123456789]+ block|ar: creat|iffe: test: |conf: (check|generate|test)|[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*=|gsf@research|ar:.*warning|cpio:|ld:.*(duplicate symbol|to obtain more information)|[0123456789]*$|(checking|creating|touch) [/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789])| obsolete predefined symbol | is (almost always misused|dangerous|deprecated|not implemented)| trigraph| assigned to | cast .* different size| integer overflow .*<<| optimization may be attained | passed as |::__builtin|pragma.*prototyped|^creating.*\.a$|warning.*not optimized|exceeds size thresh|ld:.*preempts|is unchanged|with value >=|(-l|lib)\*|/(ast|sys)/(dir|limits|param|stropts)\.h.*redefined|usage|base registers|`\.\.\.` obsolete'"$i" $j |
+ $exec grep :
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ 1) echo $m
+ ;;
+ esac
+ esac
+ ;;
+
+test) requirements source $package
+ components $package
+ package=$_components_
+ case $only in
+ 0) only= ;;
+ 1) only=--recurse=only ;;
+ esac
+
+ # must have nmake
+
+ if nonmake $MAKE
+ then echo $command: $action: must have $MAKE to test >&2
+ exit 1
+ fi
+
+ # all work under $INSTALLROOT/src
+
+ $make cd $INSTALLROOT/src
+
+ # disable core dumps (could be disasterous over nfs)
+
+ (ulimit -c 0) > /dev/null 2>&1 && ulimit -c 0
+
+ # do the tests
+
+ eval capture \$MAKE \$makeflags \$noexec \$only recurse test \$target \$nmakesep \$package $assign
+ ;;
+
+update) # download the latest release.version for selected packages
+
+ # all work in $PACKAGEROOT/lib/package/tgz
+
+ if test ! -d $PACKAGEROOT/lib/package/tgz
+ then $exec mkdir -p $PACKAGEROOT/lib/package/tgz || exit
+ $exec cd $PACKAGEROOT/lib/package/tgz
+ else cd $PACKAGEROOT/lib/package/tgz
+ fi
+
+ # get the architectures, update query url, and packages
+
+ set '' $args
+ op=update
+ tgz=tgz
+ source=
+ binary=
+ setup=
+ types=
+ url=
+ urlfile=$default_url
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ beta) op=beta
+ tgz=beta
+ ;;
+ binary) binary=1
+ ;;
+ setup) setup=1
+ ;;
+ source) source=1
+ ;;
+ *://*) url=$1
+ shift
+ break
+ ;;
+ *.url) urlfile=$1
+ if test ! -s $urlfile
+ then echo $command: $urlfile: not found >&2; exit 1
+ fi
+ break
+ ;;
+ $all_types)
+ binary=1
+ types="$types $1"
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ case $source:$binary in
+ :) source=1 binary=1
+ ;;
+ :1) case $types in
+ '') types=$HOSTTYPE ;;
+ esac
+ ;;
+ esac
+ case $url in
+ '') case $urlfile in
+ $default_url)
+ if test ! -s $urlfile
+ then echo $command: url argument expected >&2; exit 1
+ fi
+ ;;
+ *) default_url=
+ ;;
+ esac
+ url=
+ if grep '^url=' $urlfile >/dev/null
+ then a=$authorize
+ p=$password
+ case $urlfile in
+ */*) ;;
+ *) urlfile=./$urlfile ;;
+ esac
+ . $urlfile
+ case $a:$p in
+ $authorize:$password)
+ default_url=
+ ;;
+ *) case $a in
+ ?*) authorize=$a ;;
+ esac
+ case $p in
+ ?*) password=$p ;;
+ esac
+ ;;
+ esac
+ else url=`cat $urlfile`
+ fi
+ ;;
+ esac
+ case $exec in
+ ?*) default_url= ;;
+ esac
+
+ # get the update list
+
+ eval `echo $url | sed 's,\(.*\)://\([^/]*\)/\(.*\),prot=\"\1\" host=\"\2\" dir=\"\3\",'`
+ get $host $dir/$op.html
+
+ # get/check the package names
+
+ case " $* " in
+ *" - "*)case $source in
+ 1) source_packages=$* ;;
+ *) source_packages= ;;
+ esac
+ case $binary in
+ 1) binary_packages=$* ;;
+ *) binary_packages= ;;
+ esac
+ package_hit=$*
+ ;;
+ " ") nl="
+"
+ case $source in
+ 1) p=
+ for f in `ls *.????-??-??.* 2>/dev/null`
+ do case $f in
+ *.????-??-??.????-??-??.*.*)
+ ;;
+ *.????-??-??.????-??-??.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.*.*)
+ ;;
+ *.????-??-??.*)
+ p=$p$nl$f
+ ;;
+ esac
+ done
+ set '' `echo "$p" | sed 's,\..*,,' | sort -u`
+ shift
+ source_packages=$*
+ ;;
+ *) source_packages=
+ ;;
+ esac
+ case $binary in
+ 1) p=
+ for f in `ls *.????-??-??.* 2>/dev/null`
+ do case $f in
+ *.????-??-??.????-??-??.*.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.????-??-??.*)
+ ;;
+ *.????-??-??.*.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.*)
+ ;;
+ esac
+ done
+ set '' `echo "$p" | sed 's,\..*,,' | sort -u`
+ shift
+ binary_packages=$*
+ ;;
+ *) binary_packages=
+ ;;
+ esac
+ package_hit="$source_packages $binary_packages"
+ ;;
+ *) case $source in
+ 1) source_packages=$* ;;
+ *) source_packages= ;;
+ esac
+ case $binary in
+ 1) binary_packages=$* ;;
+ *) binary_packages= ;;
+ esac
+ package_hit=
+ ;;
+ esac
+
+ # get the latest updates
+
+ types_test=
+ types_local=
+ dir=$dir/$tgz
+ case $default_url in
+ ?*) echo "url='$url' authorize='$authorize' password='$password'" > $default_url
+ case $authorize in
+ ?*) chmod go-rwx $default_url ;;
+ esac
+ ;;
+ esac
+ echo "$got" > got.tmp
+ case $only in
+ 0) exec < got.tmp
+ covered=
+ while read name suffix type base base_size delta delta_size sync sync_size requires covers base_sum delta_sum sync_sum comment
+ do case $requires in
+ ''|-*) continue ;;
+ esac
+ IFS=:
+ set '' $requires
+ IFS=$ifs
+ case $type in
+ -) case " $source_packages " in
+ *" $name "*|*" - "*)
+ for name
+ do case " $source_packages " in
+ *" $name "*)
+ ;;
+ *) source_packages="$source_packages $name"
+ covered=$covered:$covers
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ *) case " $binary_packages " in
+ *" $name "*|*" - "*)
+ for name
+ do case " $binary_packages " in
+ *" $name "*)
+ ;;
+ *) binary_packages="$binary_packages $name"
+ covered=$covered:$covers
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $covered in
+ ?*) x=$source_packages
+ source_packages=
+ for name in $x
+ do case :$covered: in
+ *:$name:*) ;;
+ *) source_packages="$source_packages $name" ;;
+ esac
+ done
+ x=$binary_packages
+ binary_packages=
+ for name in $x
+ do case :$covered: in
+ *:$name:*) ;;
+ *) binary_packages="$binary_packages $name" ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ checksum=
+ for i in $checksum_commands
+ do case `( $i ) < /dev/null 2> /dev/null` in
+ ${checksum_empty}|${checksum_empty}[\ \ ]*)
+ checksum=$i
+ break
+ ;;
+ esac
+ done
+ case $checksum in
+ '') echo $command: warning: '{' $checksum_commands '}' command not found -- only download sizes will be checked >&2 ;;
+ esac
+ exec < got.tmp
+ while read name suffix type base base_size delta delta_size sync sync_size requires covers base_sum delta_sum sync_sum comment
+ do case $verbose in
+ 1) case $type in
+ -) i= ;;
+ *) i=.$type ;;
+ esac
+ j="$name.$base$i.$suffix"
+ case $delta in
+ -) j="$j -" ;;
+ *) j="$j $name.$base.$delta$i.$suffix" ;;
+ esac
+ case $sync in
+ -) j="$j -" ;;
+ *) j="$j $name.$base.$sync$i.$suffix" ;;
+ esac
+ echo $command: $j $base_size:$base_sum $delta_size:$delta_sum $sync_size:$sync_sum $requires >&2
+ esac
+ case " $package_hit " in
+ *" $name "*|*" - "*)
+ ;;
+ *) package_hit="$package_hit $name"
+ ;;
+ esac
+ case $type in
+ -) case " $source_packages " in
+ *" $name "*|*" - "*)
+ if test -s $name.tim
+ then continue
+ fi
+ lcl=$name.$base.$suffix
+ if test -f $lcl
+ then case $checksum:$base_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$base_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -a "X-" = "X$delta" -o "$base_size" != "$size" -o "$base_sum" != "$sum"
+ then rmt=
+ case $sync:$sync_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$base.$sync.$suffix
+ if test -f $lcl
+ then rmt=1
+ get $host $dir $lcl $sync_size $sync_sum
+ fi
+ ;;
+ esac
+ case $base:$base_size in
+ -*|*[-:])
+ ;;
+ *) case $rmt in
+ '') lcl=$name.$base.$suffix
+ get $host $dir $lcl $base_size $base_sum
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $delta:$delta_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$delta.$base.$suffix
+ if test -f $lcl
+ then case $checksum:$delta_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$delta_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -o "$delta_size" != "$size" -o "$delta_sum" != "$sum"
+ then get $host $dir $lcl $delta_size $delta_sum
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case " $binary_packages " in
+ *" $name "*|*" - "*)
+ if test -s $name.$type.tim
+ then continue
+ fi
+ case " $types " in
+ *" - "*);;
+ " ") case " $types_test " in
+ *" $type "*)
+ ;;
+ *) types_test="$types_test $type"
+ for i in *.????-??-??.$type.* *.????-??-??.????-??-??.$type.*
+ do if test -f $i
+ then types_local="$types_local $type"
+ fi
+ break
+ done
+ ;;
+ esac
+ case " $types_local " in
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ *) case " $types " in
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ esac
+ lcl=$name.$base.$type.$suffix
+ if test -f $lcl
+ then case $checksum:$base_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$base_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -a "X-" = "X$delta" -o "$base_size" != "$size" -o "$base_sum" != "$sum"
+ then rmt=
+ case $sync:$sync_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$base.$sync.$type.$suffix
+ if test -f $lcl
+ then rmt=1
+ get $host $dir $lcl $sync_size $sync_sum
+ fi
+ ;;
+ esac
+ case $base:$base_size in
+ -*|*[-:])
+ ;;
+ *) case $rmt in
+ '') lcl=$name.$base.$type.$suffix
+ get $host $dir $lcl $base_size $base_sum
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $delta:$delta_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$delta.$base.$type.$suffix
+ if test -f $lcl
+ then sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'`
+ else sum=X
+ fi
+ if test -f $lcl
+ then case $checksum:$delta_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$delta_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -o "$delta_size" != "$size" -o "$delta_sum" != "$sum"
+ then get $host $dir $lcl $delta_size $delta_sum
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ closure=
+ for name in $source_packages $binary_packages
+ do case $name in
+ -) ;;
+ *) case " $package_hit " in
+ *" $name "*)
+ case $setup in
+ 1) case " $closure " in
+ *" $name "*)
+ ;;
+ *) closure="$closure $name"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) echo $command: $name: unknown package >&2
+ ;;
+ esac
+ ;;
+ esac
+ done
+ exec <&-
+ rm -f got.tmp
+ case $closure in
+ ?*) echo $closure ;;
+ esac
+ ;;
+
+use) # finalize the environment
+
+ x=:..
+ for d in `( cd $PACKAGEROOT; ls src/*/Makefile src/*/Nmakefile 2>/dev/null | sed 's,/[^/]*$,,' | sort -u )`
+ do x=$x:$INSTALLROOT/$d
+ done
+ x=$x:$INSTALLROOT
+ case $CDPATH: in
+ $x:*) ;;
+ *) CDPATH=$x:$CDPATH
+ $show CDPATH=$CDPATH
+ $show export CDPATH
+ export CDPATH
+ ;;
+ esac
+ P=$PACKAGEROOT
+ $show P=$P
+ $show export P
+ export P
+ A=$INSTALLROOT
+ $show A=$A
+ $show export A
+ export A
+ case $NPROC in
+ '') hostinfo cpu
+ case $_hostinfo_ in
+ 0|1) ;;
+ *) NPROC=$_hostinfo_
+ $show NPROC=$NPROC
+ $show export NPROC
+ export NPROC
+ ;;
+ esac
+ ;;
+ esac
+ eval PACKAGE_USE=$package_use
+ export PACKAGE_USE
+
+ # run the command
+
+ case $run in
+ '') case $show in
+ ':') $exec exec $SHELL ;;
+ esac
+ ;;
+ *) $exec exec $SHELL -c "$run"
+ ;;
+ esac
+ ;;
+
+verify) cd $PACKAGEROOT
+ requirements binary $package
+ if executable ! $SUM
+ then echo "$command: $action: $SUM command required" >&2
+ exit 1
+ fi
+ case $target in
+ '') cd arch
+ set '' *
+ shift
+ target=$*
+ cd ..
+ ;;
+ esac
+ code=0
+ for a in $target
+ do case $package in
+ '') set '' arch/$a/lib/package/gen/*.sum
+ shift
+ if test -f $1
+ then for i
+ do package_verify $i || code=1
+ done
+ else echo "$command: warning: $a: no binary packages" >&2
+ fi
+ ;;
+ *) for i in $package
+ do if test -f arch/$a/lib/package/gen/$i.sum
+ then package_verify arch/$a/lib/package/gen/$i.sum || code=1
+ else echo "$command: warning: $a: no binary package for $i" >&2
+ fi
+ done
+ ;;
+ esac
+ done
+ exit $code
+ ;;
+
+write) set '' $target
+ shift
+ action=
+ list=
+ qualifier=
+ while :
+ do case $1 in
+ base|closure|delta|exp|lcl|pkg|rpm|tgz)
+ qualifier="$qualifier $1"
+ ;;
+ binary) action=$1
+ type=$HOSTTYPE
+ eval list=$PACKAGESRC/tgz/$admin_list
+ ;;
+ cyg) qualifier="$qualifier $1"
+ assign="$assign closure=1"
+ only=1
+ ;;
+ runtime|source)
+ action=$1
+ ;;
+ tst) qualifier="$qualifier tgz"
+ assign="$assign copyright=0 'PACKAGEDIR=\$(PACKAGESRC)/tst'"
+ ;;
+ nocopyright)
+ assign="$assign copyright=0"
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ case $action in
+ '') echo "$command: binary or source operand expected" >&2
+ exit 1
+ ;;
+ esac
+ set '' "$@" $package
+ shift
+ case $only in
+ 0) set '' `order "$@"`
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: at least one package name expected" >&2
+ exit 1
+ ;;
+ esac
+ if nonmake $MAKE
+ then echo "$command: must have $MAKE to generate archives" >&2
+ exit 1
+ fi
+
+ # all work under $PACKAGEBIN
+
+ $make cd $PACKAGEBIN
+ case $list in
+ ?*) $exec rm -f $list ;;
+ esac
+
+ # go for it
+
+ for package
+ do if view - all $package.pkg || view - all lib/package/$package.pkg
+ then eval capture \$MAKE \$makeflags -X ignore \$noexec -f \$package.pkg \$qualifier \$action $assign
+ else echo "$command: $package: not a package" >&2
+ fi
+ done
+ ;;
+
+TEST) set '' $target $package
+ shift
+ case $1 in
+ binary|source)
+ action=$1
+ shift
+ ;;
+ esac
+ order "$@"
+ ;;
+
+*) echo "$command: $action: internal error" >&2
+ exit 1
+ ;;
+
+esac
diff --git a/src/cmd/INIT/probe.win32 b/src/cmd/INIT/probe.win32
new file mode 100644
index 0000000..7939fcc
--- /dev/null
+++ b/src/cmd/INIT/probe.win32
@@ -0,0 +1,283 @@
+:
+# @(#)probe.win32 (AT&T Research) 2010-01-01
+#
+# win32 specific make C probe initialization
+# wrapped cc's are easy on uwin
+#
+# 2> easy.err to avoid mysterious hang with bcc
+
+# begin preamble shared with the pp probe.ini
+
+IFS=$'\n'
+
+chmod 777 . # cl.exe setuid workaround
+
+typeset -A header version
+
+# we are probing on behalf of libpp and nmake
+# so the native preprocessor must be forced in
+# order to bootstrap libpp and nmake
+
+nativepp=-1
+export nativepp
+
+probe_header="
+stddef.h
+"
+for inc in syslimits.h winerror.h ostream bits/ctype_base.h stream.h
+do echo "#include <$inc>" > easy.c
+ if $cc -E easy.c > /dev/null 2> easy.err
+ then probe_header="$probe_header
+$inc
+"
+ fi
+done
+
+{
+for i in $probe_header
+do echo "#include <$i>"
+done
+echo '#ifdef __cplusplus'
+echo "int _Pr0b3_cplus=__cplusplus;"
+echo '#endif'
+echo '#ifdef _UWIN'
+echo "int _Pr0b3_uwin=_UWIN;"
+echo '#endif'
+echo '#ifdef __BORLANDC__'
+echo "int _Pr0b3_version_BORLAND=__BORLANDC__;"
+echo '#endif'
+echo '#ifdef __DMC__'
+echo "int _Pr0b3_version_DM=__DMC__;"
+echo '#endif'
+echo '#ifdef _MSC_VER'
+echo "int _Pr0b3_version_MS=_MSC_VER;"
+echo '#endif'
+echo '#ifdef __ICL'
+echo "int _Pr0b3_version_ICL=__ICL;"
+echo '#endif'
+echo '#ifdef __LCC__'
+echo "int _Pr0b3_version_LCC=0+__LCC__;"
+echo '#endif'
+echo '#ifdef __MINGW32__'
+echo "int _Pr0b3_version_MINGW=__MINGW32__;"
+echo '#endif'
+echo '#ifdef __INTERIX'
+echo "int _Pr0b3_version_INTERIX=__INTERIX;"
+echo '#endif'
+echo '#ifdef __WATCOMC__'
+echo "int _Pr0b3_version_WATCOM=__WATCOMC__;"
+echo '#endif'
+} > easy.c
+
+include=
+uwin=
+cplus=
+
+$cc -E easy.c 2>&1 |
+egrep -i '^(#(line)? 1 .*\.[hH]| *int +_Pr0b3_[a-zA-Z_]* *= *[0-9])' |
+sed -e 's,_Pr0b3_,,' \
+ -e 's/.*"\(.*\)".*/\1/' \
+ -e 's,^ *,,' \
+ -e 's, *$,,' \
+ -e 's, *= *,=,' \
+ -e 's,^\(.\):[\\/]*,/\1/,' \
+ -e 's,[\\/][\\/]*,/,g' \
+ -e 's,^\(/.*\)/\(.*\)$,header[\2]="\1",' \
+ -e 's, *int *\(.*\);.*,\1,' \
+ -e 's,^version_\(.*\)=,version[\1]=,' \
+ > easy.sh
+. ./easy.sh
+
+include=
+for i in $probe_header
+do d=${header[$i]}
+ if [[ $d ]]
+ then include="$include
+$d"
+ elif [[ $i == */* ]]
+ then d=${header[${i##*/}]}
+ if [[ $d == */${i%/*} ]]
+ then include="$include
+${d%/${i%/*}}"
+ fi
+ fi
+done
+
+i=$($cc -V 2> easy.err)
+if test "" != "$i" -a -d "$i/include"
+then include="$i/include
+$include"
+fi
+
+stdinclude=
+for inc in $include
+do if [[ ${inc%/*} -ef /msdev/platformsdk ]]
+ then inc=/msdev/platformsdk/${inc##*/}
+ elif [[ ${inc%/*} -ef /platformsdk ]]
+ then inc=/platformsdk/${inc##*/}
+ fi
+ for dup in $stdinclude
+ do [[ $inc -ef $dup ]] && continue 2
+ done
+ stdinclude="$stdinclude
+$inc"
+done
+
+# end preamble shared with the pp probe.ini
+
+if [[ ${version[@]} == [0-9]* && $stdinclude ]]
+then : the payoff
+ set -- $cc
+ cmd=$1
+ shift
+ set -- $(whence $cmd) "$@"
+ typ=$(package)
+ dialect="ANSI CLOSURE DYNAMIC EXPORT=DLL LIBPP -I-"
+ case ${cc##*/} in
+ *CC*) dialect="$dialect C++"
+ cplus=1
+ ;;
+ esac
+ ld=${cc%cc}ld
+ if [[ ! -x $ld ]]
+ then ld=${cc%/*}/ld
+ if [[ ! -x $ld ]]
+ then case $cc in
+ */ncc) ld=/usr/bin/nld ;;
+ *) ld=/usr/bin/ld ;;
+ esac
+ fi
+ fi
+ {
+ if $cc -v >/dev/null 2>&1
+ then v=$($cc -v 2>/dev/null)
+ if [[ $v ]]
+ then print "# ;VERSION;-v;$v;PATH;$cc"
+ fi
+ else v=
+ fi
+ cat <<!
+CC.CC = $*
+CC.NATIVE = $*
+CC.EXECTYPE = $typ
+CC.HOSTTYPE = $typ
+CC.ALTPP.FLAGS = -Yp,\$(CPP:D)
+CC.ALTPP.ENV =
+CC.AR = ar
+CC.ARFLAGS =
+CC.DEBUG = -g
+CC.DIALECT = $dialect
+CC.DLL = -D_BLD_DLL
+CC.DLLBIG = -D_BLD_DLL
+CC.DLL.DEF = -D_BLD_DLL
+CC.DLL.DIR = \$(BINDIR)
+CC.DLL.LIBRARIES =
+CC.DLL.VARIANTS =
+CC.DYNAMIC =
+CC.EXPORT.DYNAMIC =
+CC.LD = $ld
+CC.LD.DYNAMIC = -Bdynamic
+CC.LD.LAZY =
+CC.LD.NOLAZY =
+CC.LD.ORIGIN =
+CC.LD.RECORD =
+CC.LD.NORECORD =
+CC.LD.RUNPATH =
+CC.LD.STATIC = -Bstatic
+CC.LD.STRIP =
+CC.LIB.DLL = option
+CC.LIB.ALL = -Bwhole-archive
+CC.LIB.UNDEF = -Bno-whole-archive
+CC.MAKE.OPTIONS = nativepp=0
+CC.NM = nm
+CC.NMEDIT =
+CC.NMFLAGS =
+CC.OPTIMIZE = -O
+CC.PIC =
+CC.PICBIG =
+CC.READONLY =
+CC.REPOSITORY =
+CC.SHARED = -G
+CC.SHARED.LD = $ld
+CC.SHARED.REGISTRY =
+CC.SHARED.REGISTRY.PATH =
+CC.SHELLMAGIC =
+CC.SIZE = size
+CC.STATIC = -Bstatic
+!
+ inc=
+ lib=
+ if [[ ${version[LCC]} ]]
+ then lib=/lcc
+ fi
+ if [[ $stdinclude == *' '* ]]
+ then stdinclude=${stdinclude//' '/''}
+ fi
+ stdinc=
+ stdlib=
+ for inc in $stdinclude
+ do stdinc="$stdinc $inc"
+ d=${inc%/*}/lib
+ if [[ -d $d ]]
+ then stdlib="$stdlib $d"
+ fi
+ done
+ case $uwin in
+ [0-9]*) cat <<!
+CC.STDINCLUDE = /usr/include $stdinc
+CC.STDLIB = /usr/lib$lib $stdlib
+!
+ ;;
+ *) cat <<!
+CC.STDINCLUDE = $stdinc
+CC.STDLIB = $stdlib
+!
+ ;;
+ esac
+ cat <<!
+CC.STRICT =
+CC.STRIP = strip
+CC.STRIP.FLAGS =
+CC.PREFIX.ARCHIVE = lib
+CC.PREFIX.DYNAMIC =
+CC.PREFIX.SHARED =
+CC.PREFIX.SYMBOL = _
+CC.SUFFIX.ARCHIVE = .a
+CC.SUFFIX.COMMAND =
+CC.SUFFIX.DEBUG = .pdb
+CC.SUFFIX.DYNAMIC = .dll
+CC.SUFFIX.LD = .def .exp .ign .res
+CC.SUFFIX.OBJECT = .o
+CC.SUFFIX.SHARED = .lib
+CC.SUFFIX.SOURCE = .c
+CC.SUFFIX.STATIC =
+!
+ if [[ $v ]]
+ then case $v in
+ *\"*) v=$(print -r -- | sed -e 's,",\\",g' -e 's,^ ,,' -e 's,.*,"&",') ;;
+ *\'*) v=\"$v\" ;;
+ esac
+ cat <<!
+CC.VERSION = -v
+CC.VERSION.STRING = $v
+!
+ else cat <<!
+CC.VERSION =
+CC.VERSION.STRING =
+!
+ fi
+ if [[ ${version[MINGW]} || ${version[MS]} ]]
+ then cat <<!
+CC.WARN = -Wall
+!
+ else cat <<!
+CC.WARN =
+!
+ fi
+ cat <<!
+CC.PREROOT =
+CC.UNIVERSE = att
+!
+ } >&3
+ exit 0
+fi
diff --git a/src/cmd/INIT/proto.c b/src/cmd/INIT/proto.c
new file mode 100644
index 0000000..d030a1d
--- /dev/null
+++ b/src/cmd/INIT/proto.c
@@ -0,0 +1,5283 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+
+/* : : generated by proto : : */
+
+#if !defined(__PROTO__)
+# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
+# if defined(__cplusplus)
+# define __LINKAGE__ "C"
+# else
+# define __LINKAGE__
+# endif
+# define __STDARG__
+# define __PROTO__(x) x
+# define __OTORP__(x)
+# define __PARAM__(n,o) n
+# if !defined(__STDC__) && !defined(__cplusplus)
+# if !defined(c_plusplus)
+# define const
+# endif
+# define signed
+# define void int
+# define volatile
+# define __V_ char
+# else
+# define __V_ void
+# endif
+# else
+# define __PROTO__(x) ()
+# define __OTORP__(x) x
+# define __PARAM__(n,o) o
+# define __LINKAGE__
+# define __V_ char
+# define const
+# define signed
+# define void int
+# define volatile
+# endif
+# define __MANGLE__ __LINKAGE__
+# if defined(__cplusplus) || defined(c_plusplus)
+# define __VARARG__ ...
+# else
+# define __VARARG__
+# endif
+# if defined(__STDARG__)
+# define __VA_START__(p,a) va_start(p,a)
+# else
+# define __VA_START__(p,a) va_start(p)
+# endif
+# if !defined(__INLINE__)
+# if defined(__cplusplus)
+# define __INLINE__ extern __MANGLE__ inline
+# else
+# if defined(_WIN32) && !defined(__GNUC__)
+# define __INLINE__ __inline
+# endif
+# endif
+# endif
+#endif
+#if !defined(__LINKAGE__)
+#define __LINKAGE__ /* 2004-08-11 transition */
+#endif
+#line 1 "proto.c"
+
+
+#line 151
+# ifndef __STDC__
+# ifndef creat
+# define creat _huh_creat
+# endif
+# if 1
+# ifndef access
+# define access _huh_access
+# endif
+# ifndef ctime
+# define ctime _huh_ctime
+# endif
+# ifndef mkdir
+# define mkdir _huh_mkdir
+# endif
+# endif
+# endif
+
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# if 1
+# include <stdio.h>
+# else
+# include <time.h>
+# endif
+
+# ifndef __STDC__
+# undef access
+# undef ctime
+# undef creat
+# undef mkdir
+# endif
+
+# ifndef O_RDONLY
+# define O_RDONLY 0
+# endif
+
+# ifndef S_IRUSR
+# define S_IRUSR 0400
+# endif
+# ifndef S_IWUSR
+# define S_IWUSR 0200
+# endif
+# ifndef S_IXUSR
+# define S_IXUSR 0100
+# endif
+# ifndef S_IRGRP
+# define S_IRGRP 0040
+# endif
+# ifndef S_IWGRP
+# define S_IWGRP 0020
+# endif
+# ifndef S_IXGRP
+# define S_IXGRP 0010
+# endif
+# ifndef S_IROTH
+# define S_IROTH 0004
+# endif
+# ifndef S_IWOTH
+# define S_IWOTH 0002
+# endif
+# ifndef S_IXOTH
+# define S_IXOTH 0001
+# endif
+
+# ifndef __STDC__
+# if !_WIN32 && !_WINIX
+# define remove(x) unlink(x)
+# define rename(x,y) ((link(x,y)||remove(x))?-1:0)
+# endif
+
+# if 1
+extern __MANGLE__ int access __PROTO__((const char*, int));
+extern __MANGLE__ int mkdir __PROTO__((const char*, int));
+# endif
+
+# endif
+
+# if 1
+extern __MANGLE__ int utime __PROTO__((const char*, time_t*));
+# endif
+
+
+
+
+
+
+int
+replace __PARAM__((const char* newfile, const char* oldfile, int preserve), (newfile, oldfile, preserve)) __OTORP__(const char* newfile; const char* oldfile; int preserve;){
+ struct stat st;
+ time_t ut[2];
+
+ if (stat(oldfile, &st))
+ {
+ if (preserve)
+ return -1;
+ st.st_mode = 0;
+ }
+ if (remove(oldfile) || rename(newfile, oldfile))
+ return -1;
+ if (st.st_mode &= (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))
+ chmod(oldfile, st.st_mode);
+ if (preserve)
+ {
+ ut[0] = st.st_atime;
+ ut[1] = st.st_mtime;
+ preserve = utime(oldfile, ut);
+ }
+ return preserve;
+}
+
+# undef utime
+# define utime ______utime
+
+#line 1 "../../lib/libpp/ppproto.c"
+
+#line 13
+static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2012-04-14 $\000\n";
+
+#line 1 "../../lib/libpp/ppfsm.c"
+
+#line 1 "../../lib/libpp/pplib.h"
+
+#line 108
+struct ppsymbol;
+struct ppindex;
+
+typedef char* (*PPBUILTIN) __PROTO__((char*, const char*, const char*));
+typedef void (*PPCOMMENT) __PROTO__((const char*, const char*, const char*, int));
+typedef void (*PPINCREF) __PROTO__((const char*, const char*, int, int));
+typedef void (*PPLINESYNC) __PROTO__((int, const char*));
+typedef void (*PPMACREF) __PROTO__((struct ppsymbol*, const char*, int, int, unsigned long));
+typedef int (*PPOPTARG) __PROTO__((int, int, const char*));
+typedef void (*PPPRAGMA) __PROTO__((const char*, const char*, const char*, const char*, int));
+
+struct ppinstk
+{
+ char* nextchr;
+ struct ppinstk* next;
+ struct ppinstk* prev;
+ long* control;
+ char* buffer;
+ char* file;
+ char* prefix;
+ struct ppsymbol* symbol;
+
+ struct ppindex* index;
+ int buflen;
+
+ int line;
+ int vendor;
+ short fd;
+ short hide;
+ short flags;
+ char type;
+};
+
+
+
+
+
+
+
+
+
+struct pplist
+{
+ char* value;
+ struct pplist* next;
+};
+
+struct oplist
+{
+ int op;
+ char* value;
+ struct oplist* next;
+};
+
+struct pphide
+{
+ struct ppmacro* macro;
+ unsigned long flags;
+ int level;
+};
+
+struct ppmacstk
+{
+ struct ppmacstk* next;
+ struct ppmacstk* prev;
+ int line;
+ char* arg[1];
+};
+
+struct ppmember
+{
+ struct ppdirs* archive;
+ unsigned long offset;
+ unsigned long size;
+};
+
+struct counter
+{
+ int candidate;
+ int function;
+ int macro;
+ int pplex;
+ int push;
+ int terminal;
+ int token;
+};
+
+struct pptuple
+{
+ struct pptuple* nomatch;
+ struct pptuple* match;
+ char token[1];
+};
+
+struct ppfileid
+{
+ unsigned long st_dev;
+ unsigned long st_ino;
+};
+
+struct pathid
+{
+ char* path;
+ struct ppfileid id;
+};
+
+#line 1 "../../lib/libpp/pp.h"
+
+#line 206
+
+#line 217
+
+#line 329
+struct ppdirs
+{
+ char* name;
+ struct ppdirs* next;
+
+
+ unsigned char c; unsigned char index; unsigned char type; union { char* buffer; char* sp; struct ppdirs* subdir; } info; struct ppfileid id;
+
+
+};
+
+struct ppkeyword
+{
+ char* name;
+ int value;
+};
+
+struct ppmacro
+{
+ int arity;
+ char* value;
+
+
+ struct pptuple* tuple; char* formals; int size;
+
+
+};
+
+struct ppsymbol
+{
+ int hash_header;
+ unsigned long flags;
+ struct ppmacro* macro;
+ __V_* value;
+
+
+ struct pphide* hidden;
+
+
+};
+
+#line 378
+struct ppglobals
+{
+ const char* version;
+ char* lineid;
+ char* outfile;
+ char* pass;
+ char* token;
+ struct ppsymbol* symbol;
+
+
+
+ char* outb;
+ char* outbuf;
+ char* outp;
+ char* oute;
+ unsigned long offset;
+
+
+ struct ppdirs* lcldirs; struct ppdirs* stddirs; int flags; char* symtab;
+
+
+
+ struct ppcontext* context; long state; long mode; long option; long test; struct { char* sp; long flags; } filedeps; struct ppdirs* firstdir; struct ppdirs* lastdir; int hide; int column; int pending; char* firstfile; char* lastfile; char* ignore; char* probe; char* filtab; char* prdtab; char* date; char* time; char* maps; long ro_state; long ro_mode; long ro_option; long ro_op[2]; struct pathid cdir; struct pathid hostdir; char* ppdefault; struct ppindex* firstindex; struct ppindex* lastindex; struct oplist* firstop; struct oplist* lastop; struct oplist* firsttx; struct oplist* lasttx; unsigned char arg_file; unsigned char arg_mode; unsigned char arg_style; unsigned char c; unsigned char hosted; unsigned char ignoresrc; unsigned char initialized; unsigned char standalone; unsigned char spare_1;
+
+
+
+ char* checkpoint; int constack; struct ppinstk* in; char* addp; char* args; char* addbuf; char* catbuf; char* hdrbuf; char* hidebuf; char* path; char* tmpbuf; char* valbuf; char* optflags; int lastout; char* include; char* prefix; struct ppmember* member; int hidden; int hiding; int level; struct { int input; int output; } pool; struct { long ro_state; long ro_mode; long ro_option; long ro_op[2]; int on; char* symtab; } reset; int truncate; struct ppmacstk* macp; char* maxmac; char* mactop; char* toknxt; long* control; long* maxcon; struct oplist* chop; struct ppfile* insert; struct ppfile* original; struct ppdirs* found; int vendor; char* dirtab; char* strtab; PPBUILTIN builtin; PPCOMMENT comment; PPINCREF incref; PPLINESYNC linesync; PPLINESYNC olinesync; PPMACREF macref; PPOPTARG optarg; PPPRAGMA pragma; struct counter counter; char funbuf[256];
+
+
+};
+
+
+
+
+
+
+
+extern __MANGLE__ struct ppglobals pp;
+extern __MANGLE__ char _pp_ctype[];
+
+extern __MANGLE__ int ppargs __PROTO__((char**, int));
+extern __MANGLE__ void ppcpp __PROTO__((void));
+extern __MANGLE__ void ppcomment __PROTO__((char*, char*, char*, int));
+extern __MANGLE__ __V_* ppcontext __PROTO__((__V_*, int));
+extern __MANGLE__ void pperror __PROTO__((int, ...));
+extern __MANGLE__ void ppincref __PROTO__((char*, char*, int, int));
+extern __MANGLE__ void ppinput __PROTO__((char*, char*, int));
+extern __MANGLE__ int pplex __PROTO__((void));
+extern __MANGLE__ void ppline __PROTO__((int, char*));
+extern __MANGLE__ void ppmacref __PROTO__((struct ppsymbol*, char*, int, int, unsigned long));
+extern __MANGLE__ void ppop __PROTO__((int, ...));
+extern __MANGLE__ void pppragma __PROTO__((char*, char*, char*, char*, int));
+extern __MANGLE__ int ppprintf __PROTO__((char*, ...));
+extern __MANGLE__ int ppsync __PROTO__((void));
+
+#line 368 "../../lib/libpp/pplib.h"
+
+#line 1 "../../lib/libpp/ppdef.h"
+
+#line 369 "../../lib/libpp/pplib.h"
+
+#line 1 "../../lib/libpp/ppkey.h"
+
+#line 16
+
+#line 125
+extern __MANGLE__ struct ppkeyword ppkey[];
+
+#line 370 "../../lib/libpp/pplib.h"
+
+#line 683
+struct ppcontext
+{
+ struct ppdirs* lcldirs; struct ppdirs* stddirs; int flags; char* symtab;
+ struct ppcontext* context; long state; long mode; long option; long test; struct { char* sp; long flags; } filedeps; struct ppdirs* firstdir; struct ppdirs* lastdir; int hide; int column; int pending; char* firstfile; char* lastfile; char* ignore; char* probe; char* filtab; char* prdtab; char* date; char* time; char* maps; long ro_state; long ro_mode; long ro_option; long ro_op[2]; struct pathid cdir; struct pathid hostdir; char* ppdefault; struct ppindex* firstindex; struct ppindex* lastindex; struct oplist* firstop; struct oplist* lastop; struct oplist* firsttx; struct oplist* lasttx; unsigned char arg_file; unsigned char arg_mode; unsigned char arg_style; unsigned char c; unsigned char hosted; unsigned char ignoresrc; unsigned char initialized; unsigned char standalone; unsigned char spare_1;
+};
+
+struct ppfile
+{
+ int hash_header;
+ struct ppsymbol* guard;
+ struct ppfile* bound[4];
+ int flags;
+};
+
+
+
+struct ppindex
+{
+ struct ppindex* next;
+ struct ppfile* file;
+ unsigned long begin;
+ unsigned long end;
+};
+
+
+
+struct ppsymkey
+{
+ struct ppsymbol sym;
+ int lex;
+};
+
+#line 729
+# ifdef __STDC__
+
+# include <stdlib.h>
+# include <unistd.h>
+# include <time.h>
+# include <string.h>
+
+# else
+
+# define size_t int
+
+extern __MANGLE__ __V_* realloc __PROTO__((__V_*, size_t));
+extern __MANGLE__ __V_* calloc __PROTO__((size_t, size_t));
+extern __MANGLE__ char* ctime __PROTO__((time_t*));
+extern __MANGLE__ void free __PROTO__((__V_*));
+
+# ifndef O_RDONLY
+
+extern __MANGLE__ int access __PROTO__((const char*, int));
+extern __MANGLE__ int close __PROTO__((int));
+extern __MANGLE__ int creat __PROTO__((const char*, int));
+extern __MANGLE__ void exit __PROTO__((int));
+extern __MANGLE__ int link __PROTO__((const char*, const char*));
+extern __MANGLE__ int open __PROTO__((const char*, int, ...));
+extern __MANGLE__ int read __PROTO__((int, __V_*, int));
+extern __MANGLE__ time_t time __PROTO__((time_t*));
+extern __MANGLE__ int unlink __PROTO__((const char*));
+extern __MANGLE__ int write __PROTO__((int, const __V_*, int));
+
+# endif
+
+# endif
+
+#line 802
+extern __MANGLE__ void ppassert __PROTO__((int, char*, char*));
+extern __MANGLE__ void ppbuiltin __PROTO__((void));
+extern __MANGLE__ int ppcall __PROTO__((struct ppsymbol*, int));
+extern __MANGLE__ int ppcontrol __PROTO__((void));
+extern __MANGLE__ void ppdump __PROTO__((void));
+extern __MANGLE__ char* ppexpand __PROTO__((char*));
+extern __MANGLE__ long ppexpr __PROTO__((int*));
+extern __MANGLE__ void ppfsm __PROTO__((int, char*));
+extern __MANGLE__ char* ppinstr __PROTO__((struct ppinstk*));
+extern __MANGLE__ char* ppkeyname __PROTO__((int, int));
+extern __MANGLE__ char* pplexstr __PROTO__((int));
+extern __MANGLE__ void ppload __PROTO__((char*));
+extern __MANGLE__ void ppmapinclude __PROTO__((char*, char*));
+extern __MANGLE__ char* ppmodestr __PROTO__((long));
+extern __MANGLE__ int ppmultiple __PROTO__((struct ppfile*, struct ppsymbol*));
+extern __MANGLE__ void ppnest __PROTO__((void));
+extern __MANGLE__ int ppoption __PROTO__((char*));
+extern __MANGLE__ char* ppoptionstr __PROTO__((long));
+extern __MANGLE__ void pppclose __PROTO__((char*));
+extern __MANGLE__ int pppdrop __PROTO__((char*));
+extern __MANGLE__ char* pppopen __PROTO__((char*, int, char*, char*, char*, char*, int));
+extern __MANGLE__ int pppread __PROTO__((char*));
+extern __MANGLE__ int pppredargs __PROTO__((void));
+extern __MANGLE__ void pppush __PROTO__((int, char*, char*, int));
+extern __MANGLE__ struct ppsymbol* pprefmac __PROTO__((char*, int));
+extern __MANGLE__ int ppsearch __PROTO__((char*, int, int));
+extern __MANGLE__ int ppset __PROTO__((long*, long, int));
+extern __MANGLE__ char* ppstatestr __PROTO__((long));
+extern __MANGLE__ char* pptokstr __PROTO__((char*, int));
+extern __MANGLE__ void pptrace __PROTO__((int));
+
+#line 11 "../../lib/libpp/ppfsm.c"
+
+#line 1 "../../lib/libpp/ppfsm.h"
+
+#line 185
+
+#line 249
+extern __MANGLE__ short _pp_fsmtab[(0+28)+1][255+1];
+
+
+
+
+
+extern __MANGLE__ char _pp_trigraph[255+1];
+
+extern __MANGLE__ void _pp_refill __PROTO__((int));
+
+#line 12 "../../lib/libpp/ppfsm.c"
+
+
+#line 67
+struct fsminit
+{
+ int state;
+ unsigned char ch[4];
+ int nextstate;
+};
+
+static struct fsminit fsminit[] =
+{
+
+ { 0, { 023 }, ((0+28)+11), },
+ { 0, { 002 }, (0), },
+ { 0, { 001 }, (0+23), },
+ { 0, { '.' }, (0+25), },
+ { 0, { 021 }, (0+19), },
+ { 0, { 'L' }, (0+20), },
+ { 0, { 'd', 'e', 'f', 'i' }, (0+1), },
+ { 0, { 'r', 's', 't', 'v' }, (0+1), },
+ { 0, { 'w', 'N' }, (0+1), },
+ { 0, { '"', '\'' }, ((0+28)+3), },
+ { 0, { '/' }, (0+12), },
+ { 0, { '\n' }, ((0+28)+7), },
+ { 0, { ' ','\t','\f','\013' }, (0+27), },
+
+
+ { (0+1), { 023 }, ((0+28)+6), },
+ { (0+1), { 021, 001 }, (0+19), },
+ { (0+1), { 'a' }, (0+2), },
+ { (0+1), { 'e' }, (0+3), },
+ { (0+1), { 'f' }, (0+4), },
+ { (0+1), { 'h' }, (0+5), },
+ { (0+1), { 'l' }, (0+6), },
+ { (0+1), { 'n' }, (0+7), },
+ { (0+1), { 'o' }, (0+8), },
+ { (0+1), { 't' }, (0+9), },
+ { (0+1), { 'x' }, (0+10), },
+ { (0+1), { 'y' }, (0+11), },
+
+
+ { (0+2), { 023 }, (((0+28)+12)), },
+ { (0+2), { 021, 001 }, (0+19), },
+ { (0+2), { '_','s','t','a' }, (0+2), },
+ { (0+2), { 'r' }, (0+2), },
+
+
+ { (0+3), { 023 }, (((0+28)+12)), },
+ { (0+3), { 021, 001 }, (0+19), },
+ { (0+3), { 't','u','r','n' }, (0+3), },
+
+
+ { (0+4), { 023 }, (((0+28)+12)), },
+ { (0+4), { 021, 001 }, (0+19), },
+
+
+ { (0+5), { 023 }, (((0+28)+12)), },
+ { (0+5), { 021, 001 }, (0+19), },
+ { (0+5), { 'i','l','e' }, (0+5), },
+
+
+ { (0+6), { 023 }, (((0+28)+12)), },
+ { (0+6), { 021, 001 }, (0+19), },
+ { (0+6), { 's','e' }, (0+6), },
+
+
+ { (0+7), { 023 }, (((0+28)+12)), },
+ { (0+7), { 021, 001 }, (0+19), },
+ { (0+7), { 'l','i','n','e' }, (0+7), },
+
+
+ { (0+8), { 023 }, (((0+28)+12)), },
+ { (0+8), { 021, 001 }, (0+19), },
+ { (0+8), { 'r','i','d','N' }, (0+8), },
+
+
+ { (0+9), { 023 }, (((0+28)+12)), },
+ { (0+9), { 021, 001 }, (0+19), },
+ { (0+9), { 'a','t','i','c' }, (0+9), },
+
+
+ { (0+10), { 023 }, (((0+28)+12)), },
+ { (0+10), { 021, 001 }, (0+19), },
+ { (0+10), { 't','e','r','n' }, (0+10), },
+
+
+ { (0+11), { 023 }, (((0+28)+12)), },
+ { (0+11), { 021, 001 }, (0+19), },
+ { (0+11), { 'p','e','d','f' }, (0+11), },
+
+
+ { (0+12), { 023 }, ((0+28)+0), },
+ { (0+12), { '*' }, (0+13), },
+
+ { (0+12), { '/' }, (0+16), },
+
+
+
+ { (0+13), { 023 }, (0+13), },
+ { (0+13), { '\n', 002 }, ((0+28)+1), },
+ { (0+13), { '/' }, (0+15), },
+ { (0+13), { '*' }, (0+14), },
+ { (0+13), { '#', ';', ')' }, ((( (0+13))<<(7+1))|(((0+28)+8))), },
+
+
+ { (0+14), { 023 }, (0+13), },
+ { (0+14), { '\n', 002 }, ((0+28)+1), },
+ { (0+14), { '#', ';', ')' }, ((( (0+13))<<(7+1))|(((0+28)+8))), },
+ { (0+14), { '*' }, (0+14), },
+ { (0+14), { '/' }, ((0+28)+1), },
+
+
+ { (0+15), { 023 }, (0+13), },
+ { (0+15), { '*', '\n', 002 }, ((0+28)+1), },
+ { (0+15), { '/' }, (0+15), },
+
+
+ { (0+16), { 023 }, (0+16), },
+ { (0+16), { '\n', 002 }, ((0+28)+1), },
+ { (0+16), { '/' }, (0+17), },
+ { (0+16), { '*' }, (0+18), },
+
+
+ { (0+17), { 023 }, (0+16), },
+ { (0+17), { '*', '\n', 002 }, ((0+28)+1), },
+ { (0+17), { '/' }, (0+17), },
+
+
+ { (0+18), { 023 }, (0+16), },
+ { (0+18), { '\n', 002 }, ((0+28)+1), },
+ { (0+18), { '*' }, (0+18), },
+ { (0+18), { '/' }, ((0+28)+1), },
+
+
+ { (0+19), { 023 }, ((0+28)+6), },
+ { (0+19), { 021, 001 }, (0+19), },
+
+
+ { (0+25), { 023 }, ((0+28)+0), },
+ { (0+25), { '.' }, (0+26), },
+ { (0+25), { 001 }, (0+23), },
+
+
+ { (0+26), { 023 }, (((( (0401+1))-0401)<<(7+1))|( ((0+28)+14))), },
+ { (0+26), { '.' }, (((( (0401+29))-0401)<<(7+1))|( ((0+28)+13))), },
+
+
+ { (0+20), { 023 }, ((0+28)+6), },
+ { (0+20), { 021, 001 }, (0+19), },
+ { (0+20), { '"', '\'' }, ((( (0+21))<<(7+1))|(((0+28)+8))), },
+
+
+ { (0+21), { 023 }, (0+21), },
+ { (0+21), { '"', '\'' }, ((0+28)+4), },
+ { (0+21), { '\n', 002 }, ((0+28)+4), },
+ { (0+21), { '\\' }, (0+22), },
+
+
+ { (0+22), { 023 }, ((0+28)+5), },
+ { (0+22), { '\n', 002 }, ((0+28)+4), },
+
+
+ { (0+23), { 023 }, (((( (0401+1))-0401)<<(7+1))|( ((0+28)+14))), },
+ { (0+23), { 021, 001, '.' }, (0+23), },
+ { (0+23), { 'e', 'E' }, (0+24), },
+
+
+ { (0+24), { 023 }, (((( (0401+1))-0401)<<(7+1))|( ((0+28)+14))), },
+ { (0+24), { 021, 001, '.' }, (0+23), },
+ { (0+24), { '+', '-' }, (0+23), },
+
+
+ { (0+27), { 023 }, ((0+28)+15), },
+ { (0+27), { ' ', '\t' }, (0+27), },
+ { (0+27), { '\f', '\013' }, ((0+28)+10), },
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 528
+ { (-1), { 0 }, 0, }
+};
+
+short _pp_fsmtab[(0+28)+1][255+1];
+
+char _pp_trigraph[255+1];
+
+
+static char spl[] = { '\\', '\r', 0 };
+static char aln[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$@";
+
+
+
+
+static char* let = &aln[10];
+static char hex[] = "fedcbaFEDCBA9876543210";
+static char* dec = &hex[12];
+static char* oct = &hex[14];
+
+
+
+
+
+
+void
+ppfsm __PARAM__((int op, register char* s), (op, s)) __OTORP__(int op; register char* s;){
+ register int c;
+ register int n;
+ register int i;
+ register short* rp;
+ register struct fsminit* fp;
+
+
+
+
+
+ switch (op)
+ {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ case 4:
+ for (fp = fsminit;; fp++)
+ {
+ if ((n = fp->nextstate) >= (0+28)) n = ~n;
+ if (fp->state == (-1))
+ {
+
+
+
+
+
+
+
+
+
+
+
+
+
+ break;
+ }
+ rp = _pp_fsmtab[fp->state];
+ for (i = 0; i < sizeof(fp->ch) && (c = fp->ch[i]); i++)
+ {
+ switch (c)
+ {
+ case 023:
+ for (c = 0; c <= 255; c++)
+ rp[c] = n;
+
+
+ case 002:
+ _pp_fsmtab[(0+28)][fp->state+1] = n < 0 ? ~n : n;
+ continue;
+
+ case 021:
+ s = let;
+ break;
+
+ case 003:
+ s = hex;
+ break;
+
+ case 001:
+ s = dec;
+ break;
+
+ case 022:
+ s = oct;
+ break;
+
+ default:
+ rp[c] = n;
+ continue;
+ }
+ while (c = *s++)
+ rp[c] = n;
+ }
+ }
+
+
+
+
+
+
+ for (i = 0; i < (0+28); i++)
+ {
+ rp = _pp_fsmtab[i];
+ s = spl;
+ while (c = *s++)
+ if (c != '@' || !(( rp)>=_pp_fsmtab[(0+13)]&&( rp)<=_pp_fsmtab[(0+18)]))
+ {
+ if (rp[c] >= 0) rp[c] = ~rp[c];
+ rp[c] &= ~(1<<7);
+ }
+ rp[0] = ~((0+28)+2);
+ for (c = 0; c <= 255; c++)
+ if (rp[c] == i)
+ rp[c] = 0;
+ }
+ _pp_fsmtab[(0+28)][0] = ~((0+28)+2);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 707
+ break;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 860
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 18 "../../lib/libpp/ppproto.c"
+
+#line 1 "../../../include/ast/hashkey.h"
+
+#line 24
+
+
+#line 68
+extern __MANGLE__ long strkey __PROTO__((const char*));
+
+#line 20 "../../lib/libpp/ppproto.c"
+
+#line 41
+typedef struct Key_s
+{
+ const char* name;
+ size_t size;
+ int hit;
+ int val;
+} Key_t;
+
+typedef struct Proto_s
+{
+ int brace;
+ int call;
+ int fd;
+ char* file;
+ long flags;
+ long options;
+ char* package;
+ int line;
+ int test;
+
+ char* tp;
+
+ int iz;
+ char* ib;
+ char* ip;
+
+ int oz;
+ char* ob;
+ char* op;
+ char* ox;
+
+ char cc[3];
+ char pushback[4];
+
+ char variadic[256];
+
+
+
+
+} Proto_t;
+
+
+#line 171
+static const Key_t pragmas[] =
+{
+ { "prototyped",sizeof( "prototyped")-1, 0x01, 1},
+ { "noprototyped",sizeof( "noprototyped")-1, 0x01, 0},
+ { "noticed",sizeof( "noticed")-1, 0x02, 1},
+ { "nonoticed",sizeof( "nonoticed")-1, 0x02, 0},
+};
+
+static const Key_t notices[] =
+{
+ { "Copyright",sizeof( "Copyright")-1, 0x02, 1},
+ { "COPYRIGHT",sizeof( "COPYRIGHT")-1, 0x02, 1},
+ { "copyright",sizeof( "copyright")-1, 0x02, 1},
+ { "Public Domain",sizeof( "Public Domain")-1, 0x02, 0},
+ { "PUBLIC DOMAIN",sizeof( "PUBLIC DOMAIN")-1, 0x02, 0},
+};
+
+
+
+
+
+
+static char*
+number __PARAM__((register char* p, register long n), (p, n)) __OTORP__(register char* p; register long n;){
+ register long d;
+
+ for (d = 1000000; d > 1; d /= 10)
+ if (n >= d) *p++ = '0' + (n / d) % 10;
+ *p++ = '0' + n % 10;
+ return p;
+}
+
+
+
+static int errors;
+
+
+#line 224
+
+
+
+
+static int
+sstrlen __PARAM__((register const char* s), (s)) __OTORP__(register const char* s;){
+ register const char* b;
+
+ for (b = s; *s; s++);
+ return s - b;
+}
+
+
+
+
+
+static int
+sstrncmp __PARAM__((register const char* s, register const char* t, register int n), (s, t, n)) __OTORP__(register const char* s; register const char* t; register int n;){
+ register const char* e = s + n;
+
+ while (s < e)
+ {
+ if (*s != *t || !*s)
+ return *s - *t;
+ s++;
+ t++;
+ }
+ return 0;
+}
+
+
+
+
+
+static char*
+strcopy __PARAM__((register char* s, register const char* t), (s, t)) __OTORP__(register char* s; register const char* t;){
+ while (*s++ = *t++);
+ return s - 1;
+}
+
+
+
+static void
+proto_error __PARAM__((char* iob, int level, char* msg, char* arg), (iob, level, msg, arg)) __OTORP__(char* iob; int level; char* msg; char* arg;){
+ register char* p;
+ char buf[1024];
+
+ p = strcopy(buf, "proto: ");
+ if (iob)
+ {
+ register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
+
+ if (proto->line)
+ {
+ if (proto->file)
+ {
+ *p++ = '"';
+ p = strcopy(p, proto->file);
+ *p++ = '"';
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ p = strcopy(p, "line ");
+ p = number(p, proto->line);
+ }
+ else if (proto->file)
+ p = strcopy(p, proto->file);
+ }
+ else
+ {
+ p = strcopy(p, msg);
+ msg = arg;
+ arg = 0;
+ }
+ if (*(p - 1) != ' ')
+ {
+ *p++ = ':';
+ *p++ = ' ';
+ }
+ if (level == 1)
+ p = strcopy(p, "warning: ");
+ p = strcopy(p, msg);
+ if (arg)
+ {
+ *p++ = ' ';
+ p = strcopy(p, arg);
+ }
+ *p++ = '\n';
+ write(2, buf, p - buf);
+ if (level >= 3)
+ exit(level - 2);
+ if (level >= 2)
+ errors++;
+}
+
+
+
+
+
+static char*
+memcopy __PARAM__((register char* s, register char* t, int n), (s, t, n)) __OTORP__(register char* s; register char* t; int n;){
+ register char* e = t + n;
+
+ while (t < e) *s++ = *t++;
+ return s;
+}
+
+#line 1 "../../lib/libast/port/astlicense.c"
+
+
+
+#line 84
+typedef struct Buffer_s
+{
+ char* buf;
+ char* nxt;
+ char* end;
+ int siz;
+} Buffer_t;
+
+typedef struct Item_s
+{
+ char* data;
+ int size;
+ int quote;
+} Item_t;
+
+typedef struct Id_s
+{
+ Item_t name;
+ Item_t value;
+} Id_t;
+
+
+
+
+
+
+
+static const Item_t key[] =
+{
+ { "author",sizeof( "author")-1,0},
+ { "class",sizeof( "class")-1,0},
+ { "company",sizeof( "company")-1,0},
+ { "component",sizeof( "component")-1,0},
+ { "contributor",sizeof( "contributor")-1,0},
+ { "corporation",sizeof( "corporation")-1,0},
+ { "domain",sizeof( "domain")-1,0},
+ { "id",sizeof( "id")-1,0},
+ { "incorporation",sizeof( "incorporation")-1,0},
+ { "license",sizeof( "license")-1,0},
+ { "location",sizeof( "location")-1,0},
+ { "name",sizeof( "name")-1,0},
+ { "notice",sizeof( "notice")-1,0},
+ { "organization",sizeof( "organization")-1,0},
+ { "package",sizeof( "package")-1,0},
+ { "parent",sizeof( "parent")-1,0},
+ { "query",sizeof( "query")-1,0},
+ { "since",sizeof( "since")-1,0},
+ { "source",sizeof( "source")-1,0},
+ { "start",sizeof( "start")-1,0},
+ { "type",sizeof( "type")-1,0},
+ { "url",sizeof( "url")-1,0},
+ { "urlmd5",sizeof( "urlmd5")-1,0},
+ { "version",sizeof( "version")-1,0},
+ {0}
+};
+
+
+
+
+
+static const Item_t lic[] =
+{
+ { "none",sizeof( "none")-1, 0},
+ { "inline",sizeof( "inline")-1, 12},
+ { "test",sizeof( "test")-1, 2},
+ { "verbose",sizeof( "verbose")-1, 3},
+ { "usage",sizeof( "usage")-1, 4},
+ { "open",sizeof( "open")-1, 5},
+ { "cpl",sizeof( "cpl")-1, 5},
+ { "epl",sizeof( "epl")-1, 5},
+ { "bsd",sizeof( "bsd")-1, 5},
+ { "zlib",sizeof( "zlib")-1, 5},
+ { "mit",sizeof( "mit")-1, 5},
+ { "gpl",sizeof( "gpl")-1, 11},
+ { "special",sizeof( "special")-1, 12},
+ { "nonexclusive",sizeof( "nonexclusive")-1, 12},
+ { "noncommercial",sizeof( "noncommercial")-1, 12},
+ { "proprietary",sizeof( "proprietary")-1, 15},
+ {0}
+};
+
+typedef struct Notice_s
+{
+ int test;
+ int type;
+ int verbose;
+ int ids;
+ Item_t item[(sizeof(key)/sizeof(key[0])-1)];
+ Id_t id[64];
+ char cc[3];
+} Notice_t;
+
+
+
+
+
+static int
+lookup __PARAM__((register const Item_t* item, const char* name, int size), (item, name, size)) __OTORP__(register const Item_t* item; const char* name; int size;){
+ register int c;
+ register int i;
+
+ c = name[0];
+ for (i = 0; item[i].data; i++)
+ if (c == item[i].data[0] && size == item[i].size && !sstrncmp( name, item[i].data, size))
+ return i;
+ return -1;
+}
+
+
+
+
+
+
+static void
+copy __PARAM__((register Buffer_t* b, register char* s, int n), (b, s, n)) __OTORP__(register Buffer_t* b; register char* s; int n;){
+ if (n < 0)
+ n = sstrlen( s);
+ while (n--)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( *s++)):(( *s++),(-1)));
+}
+
+
+#line 217
+static void
+comment __PARAM__((Notice_t* notice, register Buffer_t* b, register char* s, register int n, int u), (notice, b, s, n, u)) __OTORP__(Notice_t* notice; register Buffer_t* b; register char* s; register int n; int u;){
+ register int i;
+ register int m;
+ register int x;
+ int cc;
+
+ cc = notice->cc[1];
+ if (!s)
+ {
+ if (n)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( notice->cc[n > 0 ? 0 : 1])):(( notice->cc[n > 0 ? 0 : 1]),(-1)));
+ for (i = 0; i < 70; i++)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( cc)):(( cc),(-1)));
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( notice->cc[n > 0 ? 1 : 2])):(( notice->cc[n > 0 ? 1 : 2]),(-1)));
+ }
+ else
+ s = "";
+ }
+ if (s)
+ {
+ if (n > 70)
+ n = 70;
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( cc)):(( cc),(-1)));
+ m = (u < 0) ? 1 : (70 - n) / 2;
+ if ((x = 70 - m - n) < 0)
+ n--;
+ while (m-- > 0)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ while (n-- > 0)
+ {
+ i = *s++;
+ if (u > 0 && i >= 'a' && i <= 'z')
+ i = i - 'a' + 'A';
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( i)):(( i),(-1)));
+ }
+ while (x-- > 0)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( cc)):(( cc),(-1)));
+ }
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( '\n')):(( '\n'),(-1)));
+}
+
+
+
+
+
+static void
+expand __PARAM__((Notice_t* notice, register Buffer_t* b, const Item_t* item), (notice, b, item)) __OTORP__(Notice_t* notice; register Buffer_t* b; const Item_t* item;){
+ register char* t;
+ register char* e;
+ register int q;
+ register char* x;
+ register char* z;
+ register int c;
+ int m;
+ int i;
+ int k;
+
+ if (t = item->data)
+ {
+ q = item->quote;
+ e = t + item->size;
+ i = 0;
+ while (t < e)
+ {
+ if (*t == '$' && t < (e + 2) && *(t + 1) == '{')
+ {
+ k = m = 0;
+ x = t += 2;
+ while (t < e && (c = *t++) != '}')
+ if (c == '.')
+ x = t;
+ else if (c == '-')
+ {
+ k = 1;
+ break;
+ }
+ else if (c == '/')
+ {
+ m = 1;
+ break;
+ }
+ if ((c = lookup(key, x, t - x - 1)) >= 0 && (x = notice->item[c].data))
+ {
+ z = x + notice->item[c].size;
+ while (x < z)
+ {
+ c = *x++;
+ if (!m || c >= '0' && c <= '9')
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( c)):(( c),(-1)));
+ }
+ }
+ else if (k)
+ {
+ k = 0;
+ i++;
+ }
+ if (k || m)
+ {
+ k = 1;
+ while (t < e)
+ if ((c = *t++) == '{')
+ k++;
+ else if (c == '}' && !--k)
+ break;
+ }
+ }
+ else if (q > 0 && *t == '\\' && (*(t + 1) == q || *(t + 1) == '\\'))
+ t++;
+ else if (*t == '}' && i)
+ {
+ t++;
+ i--;
+ }
+ else
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( *t++)):(( *t++),(-1)));
+ }
+ }
+}
+
+
+
+
+
+static void
+copyright __PARAM__((Notice_t* notice, register Buffer_t* b), (notice, b)) __OTORP__(Notice_t* notice; register Buffer_t* b;){
+ register char* x;
+ register char* t;
+ time_t clock;
+
+ copy(b, "Copyright (c) ", -1);
+ if (notice->test)
+ clock = (time_t)1000212300;
+ else if (!(t = notice->item[18].data))
+ {
+ time(&clock);
+ t = ctime(&clock) + 20;
+ }
+ if ((x = notice->item[19].data) && sstrncmp( t, x, 4) < 0)
+ t = x;
+ if ((x = notice->item[17].data) && sstrncmp( x, t, 4) < 0)
+ {
+ expand(notice, b, &notice->item[17]);
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( '-')):(( '-'),(-1)));
+ }
+ copy(b, t, 4);
+ if (notice->item[15].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[15]);
+ }
+ if (notice->item[5].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[5]);
+ if (notice->item[8].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[8]);
+ }
+ }
+ else if (notice->item[2].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[2]);
+ }
+}
+
+typedef struct Stack_s
+{
+ char* info;
+ char* file;
+ int line;
+ int size;
+} Stack_t;
+
+static int
+push __PARAM__((Stack_t* sp, char* file, char* parent, char* info, int size, Buffer_t* buf), (sp, file, parent, info, size, buf)) __OTORP__(Stack_t* sp; char* file; char* parent; char* info; int size; Buffer_t* buf;){
+ char* s;
+ char* t;
+ int i;
+ int n;
+ char path[1024];
+
+ if (size <= 8)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": no space", -1);
+ ((( buf)->nxt<( buf)->end)?(*( buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ if (*file != '/' && parent && (s = strrchr(parent, '/')))
+ {
+ n = s - parent + 1;
+ if ((sstrlen( file) + n + 1) <= sizeof(path))
+ {
+ memcopy( path, parent, n);
+ strcopy( path + n, file);
+ file = path;
+ }
+ }
+ if ((i = open(file, O_RDONLY)) < 0)
+ {
+
+ if (file == path)
+ for (s = path; *s; s++)
+ if (s[0] == '/' && s[1] == 'a' && s[2] == 'r' && s[3] == 'c' && s[4] == 'h' && s[5] == '/')
+ {
+ t = s;
+ for (s += 6; *s && *s != '/'; s++);
+ while (*t++ = *s++);
+ i = open(file, O_RDONLY);
+ }
+ if (i < 0)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": cannot open", -1);
+ ((( buf)->nxt<( buf)->end)?(*( buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ }
+ n = read(i, info, size - 1);
+ close(i);
+ if (n < 0)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": cannot read", -1);
+ ((( buf)->nxt<( buf)->end)?(*( buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ info[n++] = 0;
+ sp->file = file;
+ sp->info = info;
+ sp->line = 0;
+ sp->size = n;
+ return 0;
+}
+
+
+
+
+
+
+
+int
+astlicense __PARAM__((char* p, int size, char* file, char* options, int cc1, int cc2, int cc3), (p, size, file, options, cc1, cc2, cc3)) __OTORP__(char* p; int size; char* file; char* options; int cc1; int cc2; int cc3;){
+ register char* s;
+ register char* v;
+ register char* x;
+ register int c;
+ int i;
+ int h;
+ int k;
+ int n;
+ int q;
+ int contributor;
+ int first;
+ int level;
+ int quote;
+ char* data;
+ char tmpbuf[(70+4)];
+ char info[8 * 1024];
+ Stack_t input[4];
+ Notice_t notice;
+ Item_t item;
+ Buffer_t buf;
+ Buffer_t tmp;
+
+ buf.end = (buf.buf = buf.nxt = p) + size;
+ tmp.end = (tmp.buf = tmp.nxt = tmpbuf) + sizeof(tmpbuf);
+ level = 0;
+ data = info;
+ level = -1;
+ if (options)
+ {
+ level++;
+ input[level].file = "<options>";
+ input[level].info = options;
+ input[level].line = 0;
+ }
+ if (file && *file)
+ {
+ if (push(&input[++level], file, 0, data, &info[sizeof(info)] - data, &buf))
+ return -1;
+ data += input[level].size;
+ }
+ if (level < 0)
+ return 0;
+ s = input[level].info;
+ notice.test = 0;
+ notice.type = 0;
+ notice.verbose = 0;
+ notice.ids = 0;
+ notice.cc[0] = cc1;
+ notice.cc[1] = cc2;
+ notice.cc[2] = cc3;
+ for (i = 0; i < (sizeof(key)/sizeof(key[0])-1); i++)
+ notice.item[i].data = 0;
+ notice.item[20] = notice.item[1] = lic[notice.type];
+ notice.item[20].quote = notice.item[1].quote = 0;
+ contributor = i = k = 0;
+ for (;;)
+ {
+ first = 1;
+ while (c = *s)
+ {
+ while (c == ' ' || c == '\t' || c == '\n' && ++input[level].line || c == '\r' || c == ',' || c == ';' || c == ')')
+ c = *++s;
+ if (!c)
+ break;
+ if (c == '#')
+ {
+ while (*++s && *s != '\n');
+ if (*s)
+ s++;
+ input[level].line++;
+ continue;
+ }
+ if (c == '.')
+ {
+ while ((c = *++s) && (c == ' ' || c == '\t'));
+ file = s;
+ while (c && c != ' ' && c != '\t' && c != '\r' && c != '\n')
+ c = *++s;
+ *s = 0;
+ while (c && c != '\n')
+ c = *++s;
+ if (*file)
+ {
+ input[level].info = s + (c != 0);
+ if (++level >= (sizeof(input) / sizeof(input[0])) || push(&input[level], file, input[level-1].file, data, &info[sizeof(info)] - data, &buf))
+ return -1;
+ data += input[level].size;
+ s = input[level].info;
+ }
+ continue;
+ }
+ if (c == '\n')
+ {
+ s++;
+ input[level].line++;
+ continue;
+ }
+ if (c == '[')
+ c = *++s;
+ x = s;
+ n = 0;
+ while (c && c != '+' && c != '=' && c != ']' && c != ')' && c != ',' && c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ c = *++s;
+ n = s - x;
+ h = lookup(key, x, n);
+ if (c == '+' || c == ']')
+ c = *++s;
+ quote = 0;
+ if (c == '=' || first)
+ {
+ if (c == '=')
+ {
+ q = ((c = *++s) == '"' || c == '\'') ? *s++ : 0;
+ if (c == '(')
+ {
+ s++;
+ if (h == 9)
+ contributor = 0;
+ else if (h == 4)
+ contributor = 1;
+ else
+ {
+ q = 1;
+ i = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ s--;
+ break;
+ case '(':
+ if (!i)
+ q++;
+ continue;
+ case ')':
+ if (!i && !--q)
+ break;
+ continue;
+ case '"':
+ case '\'':
+ if (!i)
+ i = *(s - 1);
+ else if (i == *(s - 1))
+ i = 0;
+ continue;
+ case '\\':
+ if (*s == i && i == '"')
+ i++;
+ continue;
+ case '\n':
+ input[level].line++;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ continue;
+ }
+ v = s;
+ while ((c = *s) && (q == '"' && (c == '\\' && (*(s + 1) == '"' || *(s + 1) == '\\') && s++ && (quote = q)) || q && c != q || !q && c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != ',' && c != ';'))
+ {
+ if (c == '\n')
+ input[level].line++;
+ s++;
+ }
+ }
+ else
+ {
+ h = 20;
+ v = x;
+ }
+ if (c == '\n')
+ input[level].line++;
+ if (contributor)
+ {
+ for (i = 0; i < notice.ids; i++)
+ if (n == notice.id[i].name.size && !sstrncmp( x, notice.id[i].name.data, n))
+ break;
+ if (i < 64)
+ {
+ notice.id[i].name.data = x;
+ notice.id[i].name.size = n;
+ notice.id[i].name.quote = 0;
+ notice.id[i].value.data = v;
+ notice.id[i].value.size = s - v;
+ notice.id[i].value.quote = quote;
+ if (notice.ids <= i)
+ notice.ids = i + 1;
+ }
+ }
+ else if (h == 16)
+ {
+ if ((s - v) == 3 && v[0] == 'a' && v[1] == 'l' && v[2] == 'l')
+ {
+ for (i = 0; i < (sizeof(key)/sizeof(key[0])-1); i++)
+ if (notice.item[i].size)
+ {
+ expand(&notice, &buf, &key[i]);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '=')):(( '='),(-1)));
+ for (h = 0;; h++)
+ if (h >= notice.item[i].size)
+ {
+ h = 0;
+ break;
+ }
+ else if (notice.item[i].data[h] == ' ' || notice.item[i].data[h] == '\t')
+ break;
+ if (h)
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\'')):(( '\''),(-1)));
+ expand(&notice, &buf, &notice.item[i]);
+ if (h)
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\'')):(( '\''),(-1)));
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\n')):(( '\n'),(-1)));
+ }
+ }
+ else
+ {
+ if ((h = lookup(key, v, s - v)) < 0)
+ {
+ item.data = v;
+ item.size = s - v;
+ item.quote = 0;
+ expand(&notice, &buf, &item);
+ }
+ else
+ expand(&notice, &buf, &notice.item[h]);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\n')):(( '\n'),(-1)));
+ }
+ return (*(( &buf)->nxt>=( &buf)->end?(( &buf)->nxt=( &buf)->end-1):( &buf)->nxt)=0,( &buf)->nxt-( &buf)->buf);
+ }
+ else
+ {
+ if (h == 20)
+ switch (c = lookup(lic, v, s - v))
+ {
+ case 0:
+ return 0;
+ case 2:
+ notice.test = 1;
+ h = -1;
+ break;
+ case 3:
+ notice.verbose = 1;
+ h = -1;
+ break;
+ case 4:
+ notice.type = c;
+ h = -1;
+ break;
+ case -1:
+ c = 12;
+
+ default:
+ notice.type = c;
+ notice.item[1].data = lic[lic[c].quote].data;
+ notice.item[1].size = lic[lic[c].quote].size;
+ if (notice.item[20].data != lic[0].data)
+ h = -1;
+ break;
+ }
+ if (h >= 0)
+ {
+ notice.item[h].data = (notice.item[h].size = s - v) ? v : (char*)0;
+ notice.item[h].quote = quote;
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ if (input[level].file)
+ {
+ copy(&buf, "\"", -1);
+ copy(&buf, input[level].file, -1);
+ copy(&buf, "\", line ", -1);
+ x = &tmpbuf[sizeof(tmpbuf)];
+ *--x = 0;
+ n = ++input[level].line;
+ do *--x = ("0123456789")[n % 10]; while (n /= 10);
+ copy(&buf, x, -1);
+ copy(&buf, ": ", -1);
+ }
+ copy(&buf, "option error: assignment expected", -1);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ if (*s)
+ s++;
+ first = 0;
+ }
+ if (!level--)
+ break;
+ s = input[level].info;
+ }
+ if (!k)
+ return 0;
+ if (notice.type == 1 && (!notice.verbose || !notice.item[12].data))
+ return 0;
+ if (notice.type != 4)
+ {
+ if (!notice.type)
+ notice.type = 12;
+ comment(&notice, &buf, ((char*)0), 1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ if (notice.item[14].data)
+ {
+ copy(&tmp, "This software is part of the ", -1);
+ expand(&notice, &tmp, &notice.item[14]);
+ copy(&tmp, " package", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ if (notice.type >= 5)
+ {
+ copyright(&notice, &tmp);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.type >= 12)
+ comment( &notice, &buf, "All Rights Reserved",sizeof( "All Rights Reserved")-1, 0);
+ }
+ if (notice.type == 6 || notice.type == 7)
+ {
+ copy(&tmp, notice.item[14].data ? "and": "This software", -1);
+ copy(&tmp, " is licensed under the", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.type == 7)
+ copy(&tmp, "Eclipse Public License", -1);
+ else
+ copy(&tmp, "Common Public License", -1);
+ if (notice.item[23].data)
+ {
+ copy(&tmp, ", Version ", -1);
+ expand(&notice, &tmp, &notice.item[23]);
+ }
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[5].data || notice.item[2].data)
+ {
+ copy(&tmp, "by ", -1);
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[15]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[5].data)
+ {
+ expand(&notice, &tmp, &notice.item[5]);
+ if (notice.item[8].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[8]);
+ }
+ }
+ else if (notice.item[2].data)
+ expand(&notice, &tmp, &notice.item[2]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "A copy of the License is available at",sizeof( "A copy of the License is available at")-1, 0);
+ if (notice.item[21].data)
+ {
+ expand(&notice, &tmp, &notice.item[21]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[22].data)
+ {
+ copy(&tmp, "(with md5 checksum ", -1);
+ expand(&notice, &tmp, &notice.item[22]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ }
+ else if (notice.type == 7)
+ comment( &notice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html",sizeof( "http://www.eclipse.org/org/documents/epl-v10.html")-1, 0);
+ else
+ comment( &notice, &buf, "http://www.opensource.org/licenses/cpl",sizeof( "http://www.opensource.org/licenses/cpl")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 5)
+ {
+ copy(&tmp, notice.item[14].data ? "and it": "This software", -1);
+ copy(&tmp, " may only be used by you under license from", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[i = 5].data)
+ {
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = 15]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[5]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ else if (notice.item[i = 2].data)
+ {
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = 15]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[2]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ else
+ i = -1;
+ if (notice.item[21].data)
+ {
+ comment( &notice, &buf, "A copy of the Source Code Agreement is available",sizeof( "A copy of the Source Code Agreement is available")-1, 0);
+ copy(&tmp, "at the ", -1);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " Internet web site URL", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ expand(&notice, &tmp, &notice.item[21]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[22].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[22]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ comment( &notice, &buf, "If you have copied or used this software without agreeing",sizeof( "If you have copied or used this software without agreeing")-1, 0);
+ comment( &notice, &buf, "to the terms of the license you are infringing on",sizeof( "to the terms of the license you are infringing on")-1, 0);
+ comment( &notice, &buf, "the license and copyright and are violating",sizeof( "the license and copyright and are violating")-1, 0);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, "'s", -1);
+ if (n >= (70-32))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ else
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ copy(&tmp, "intellectual property rights.", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 11)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "This is free software; you can redistribute it and/or",sizeof( "This is free software; you can redistribute it and/or")-1, 0);
+ comment( &notice, &buf, "modify it under the terms of the GNU General Public License",sizeof( "modify it under the terms of the GNU General Public License")-1, 0);
+ comment( &notice, &buf, "as published by the Free Software Foundation;",sizeof( "as published by the Free Software Foundation;")-1, 0);
+ comment( &notice, &buf, "either version 2, or (at your option) any later version.",sizeof( "either version 2, or (at your option) any later version.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "This software is distributed in the hope that it",sizeof( "This software is distributed in the hope that it")-1, 0);
+ comment( &notice, &buf, "will be useful, but WITHOUT ANY WARRANTY;",sizeof( "will be useful, but WITHOUT ANY WARRANTY;")-1, 0);
+ comment( &notice, &buf, "without even the implied warranty of MERCHANTABILITY",sizeof( "without even the implied warranty of MERCHANTABILITY")-1, 0);
+ comment( &notice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.",sizeof( "or FITNESS FOR A PARTICULAR PURPOSE.")-1, 0);
+ comment( &notice, &buf, "See the GNU General Public License for more details.",sizeof( "See the GNU General Public License for more details.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "You should have received a copy of the",sizeof( "You should have received a copy of the")-1, 0);
+ comment( &notice, &buf, "GNU General Public License",sizeof( "GNU General Public License")-1, 0);
+ comment( &notice, &buf, "along with this software (see the file COPYING.)",sizeof( "along with this software (see the file COPYING.)")-1, 0);
+ comment( &notice, &buf, "If not, a copy is available at",sizeof( "If not, a copy is available at")-1, 0);
+ comment( &notice, &buf, "http://www.gnu.org/copyleft/gpl.html",sizeof( "http://www.gnu.org/copyleft/gpl.html")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 8)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "Redistribution and use in source and binary forms, with or",sizeof( "Redistribution and use in source and binary forms, with or")-1, -1);
+ comment( &notice, &buf, "without modification, are permitted provided that the following",sizeof( "without modification, are permitted provided that the following")-1, -1);
+ comment( &notice, &buf, "conditions are met:",sizeof( "conditions are met:")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 1. Redistributions of source code must retain the above",sizeof( " 1. Redistributions of source code must retain the above")-1, -1);
+ comment( &notice, &buf, " copyright notice, this list of conditions and the",sizeof( " copyright notice, this list of conditions and the")-1, -1);
+ comment( &notice, &buf, " following disclaimer.",sizeof( " following disclaimer.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 2. Redistributions in binary form must reproduce the above",sizeof( " 2. Redistributions in binary form must reproduce the above")-1, -1);
+ comment( &notice, &buf, " copyright notice, this list of conditions and the",sizeof( " copyright notice, this list of conditions and the")-1, -1);
+ comment( &notice, &buf, " following disclaimer in the documentation and/or other",sizeof( " following disclaimer in the documentation and/or other")-1, -1);
+ comment( &notice, &buf, " materials provided with the distribution.",sizeof( " materials provided with the distribution.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ copy(&tmp, " 3. Neither the name of ", -1);
+ if (notice.item[i = 15].data || notice.item[i = 5].data || notice.item[i = 2].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ else
+ copy(&tmp, "the copyright holder", -1);
+ copy(&tmp, " nor the", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), -1);
+ comment( &notice, &buf, " names of its contributors may be used to endorse or",sizeof( " names of its contributors may be used to endorse or")-1, -1);
+ comment( &notice, &buf, " promote products derived from this software without",sizeof( " promote products derived from this software without")-1, -1);
+ comment( &notice, &buf, " specific prior written permission.",sizeof( " specific prior written permission.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND",sizeof( "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND")-1, -1);
+ comment( &notice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,",sizeof( "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,")-1, -1);
+ comment( &notice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF",sizeof( "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF")-1, -1);
+ comment( &notice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE",sizeof( "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE")-1, -1);
+ comment( &notice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS",sizeof( "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS")-1, -1);
+ comment( &notice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,",sizeof( "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,")-1, -1);
+ comment( &notice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED",sizeof( "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED")-1, -1);
+ comment( &notice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,",sizeof( "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,")-1, -1);
+ comment( &notice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON",sizeof( "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON")-1, -1);
+ comment( &notice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,",sizeof( "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,")-1, -1);
+ comment( &notice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY",sizeof( "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY")-1, -1);
+ comment( &notice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE",sizeof( "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE")-1, -1);
+ comment( &notice, &buf, "POSSIBILITY OF SUCH DAMAGE.",sizeof( "POSSIBILITY OF SUCH DAMAGE.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 9)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "This software is provided 'as-is', without any express or implied",sizeof( "This software is provided 'as-is', without any express or implied")-1, -1);
+ comment( &notice, &buf, "warranty. In no event will the authors be held liable for any",sizeof( "warranty. In no event will the authors be held liable for any")-1, -1);
+ comment( &notice, &buf, "damages arising from the use of this software.",sizeof( "damages arising from the use of this software.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "Permission is granted to anyone to use this software for any",sizeof( "Permission is granted to anyone to use this software for any")-1, -1);
+ comment( &notice, &buf, "purpose, including commercial applications, and to alter it and",sizeof( "purpose, including commercial applications, and to alter it and")-1, -1);
+ comment( &notice, &buf, "redistribute it freely, subject to the following restrictions:",sizeof( "redistribute it freely, subject to the following restrictions:")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 1. The origin of this software must not be misrepresented;",sizeof( " 1. The origin of this software must not be misrepresented;")-1, -1);
+ comment( &notice, &buf, " you must not claim that you wrote the original software. If",sizeof( " you must not claim that you wrote the original software. If")-1, -1);
+ comment( &notice, &buf, " you use this software in a product, an acknowledgment in the",sizeof( " you use this software in a product, an acknowledgment in the")-1, -1);
+ comment( &notice, &buf, " product documentation would be appreciated but is not",sizeof( " product documentation would be appreciated but is not")-1, -1);
+ comment( &notice, &buf, " required.",sizeof( " required.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 2. Altered source versions must be plainly marked as such,",sizeof( " 2. Altered source versions must be plainly marked as such,")-1, -1);
+ comment( &notice, &buf, " and must not be misrepresented as being the original",sizeof( " and must not be misrepresented as being the original")-1, -1);
+ comment( &notice, &buf, " software.",sizeof( " software.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 3. This notice may not be removed or altered from any source",sizeof( " 3. This notice may not be removed or altered from any source")-1, -1);
+ comment( &notice, &buf, " distribution.",sizeof( " distribution.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 10)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "Permission is hereby granted, free of charge, to any person",sizeof( "Permission is hereby granted, free of charge, to any person")-1, 0);
+ comment( &notice, &buf, "obtaining a copy of this software and associated",sizeof( "obtaining a copy of this software and associated")-1, 0);
+ comment( &notice, &buf, "documentation files (the \"Software\"), to deal in the",sizeof( "documentation files (the \"Software\"), to deal in the")-1, 0);
+ comment( &notice, &buf, "Software without restriction, including without limitation",sizeof( "Software without restriction, including without limitation")-1, 0);
+ comment( &notice, &buf, "the rights to use, copy, modify, merge, publish, distribute,",sizeof( "the rights to use, copy, modify, merge, publish, distribute,")-1, 0);
+ comment( &notice, &buf, "sublicense, and/or sell copies of the Software, and to",sizeof( "sublicense, and/or sell copies of the Software, and to")-1, 0);
+ comment( &notice, &buf, "permit persons to whom the Software is furnished to do so,",sizeof( "permit persons to whom the Software is furnished to do so,")-1, 0);
+ comment( &notice, &buf, "subject to the following conditions:",sizeof( "subject to the following conditions:")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "The above copyright notice and this permission notice shall",sizeof( "The above copyright notice and this permission notice shall")-1, 0);
+ comment( &notice, &buf, "be included in all copies or substantial portions of the",sizeof( "be included in all copies or substantial portions of the")-1, 0);
+ comment( &notice, &buf, "Software.",sizeof( "Software.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY",sizeof( "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY")-1, 0);
+ comment( &notice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE",sizeof( "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE")-1, 0);
+ comment( &notice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR",sizeof( "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR")-1, 0);
+ comment( &notice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS",sizeof( "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS")-1, 0);
+ comment( &notice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR",sizeof( "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR")-1, 0);
+ comment( &notice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR",sizeof( "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR")-1, 0);
+ comment( &notice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE",sizeof( "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE")-1, 0);
+ comment( &notice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",sizeof( "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else
+ {
+ if (notice.type == 15)
+ {
+ if (notice.item[i = 15].data || notice.item[i = 5].data || notice.item[i = 2].data)
+ {
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " - ", -1);
+ }
+ else
+ i = -1;
+ copy(&tmp, "Proprietary", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ if (notice.item[21].data)
+ {
+ copy(&tmp, "This is proprietary source code", -1);
+ if (i >= 0)
+ copy(&tmp, " licensed by", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[15]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[5].data)
+ {
+ expand(&notice, &tmp, &notice.item[5]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ }
+ else if (notice.item[2].data)
+ {
+ expand(&notice, &tmp, &notice.item[2]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ }
+ }
+ else
+ {
+ copy(&tmp, "This is unpublished proprietary source code", -1);
+ if (i >= 0)
+ copy(&tmp, " of", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ if (notice.item[i = 15].data || notice.item[i = 5].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[2].data)
+ {
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(&notice, &tmp, &notice.item[2]);
+ }
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ comment( &notice, &buf, "and is not to be disclosed or used except in",sizeof( "and is not to be disclosed or used except in")-1, 1);
+ comment( &notice, &buf, "accordance with applicable agreements",sizeof( "accordance with applicable agreements")-1, 1);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 13)
+ {
+ comment( &notice, &buf, "For nonexclusive individual use",sizeof( "For nonexclusive individual use")-1, 1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 14)
+ {
+ comment( &notice, &buf, "For noncommercial use",sizeof( "For noncommercial use")-1, 1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.type >= 15 && !notice.item[21].data)
+ {
+ comment( &notice, &buf, "Unpublished & Not for Publication",sizeof( "Unpublished & Not for Publication")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.item[21].data)
+ {
+ copy(&tmp, "This software is licensed", -1);
+ if (notice.item[5].data || notice.item[2].data)
+ {
+ copy(&tmp, " by", -1);
+ if ((notice.item[15].size + (notice.item[5].data ? (notice.item[5].size + notice.item[8].size) : notice.item[2].size)) >= ((70-32) - 6))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ else
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[15]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[5].data)
+ {
+ expand(&notice, &tmp, &notice.item[5]);
+ if (notice.item[8].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[8]);
+ }
+ }
+ else if (notice.item[2].data)
+ expand(&notice, &tmp, &notice.item[2]);
+ }
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ comment( &notice, &buf, "under the terms and conditions of the license in",sizeof( "under the terms and conditions of the license in")-1, 0);
+ expand(&notice, &tmp, &notice.item[21]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[22].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[22]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 15)
+ {
+ comment( &notice, &buf, "The copyright notice above does not evidence any",sizeof( "The copyright notice above does not evidence any")-1, 0);
+ comment( &notice, &buf, "actual or intended publication of such source code",sizeof( "actual or intended publication of such source code")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ }
+ if (v = notice.item[12].data)
+ {
+ x = v + notice.item[12].size;
+ if (*v == '\n')
+ v++;
+ item.quote = notice.item[12].quote;
+ do
+ {
+ for (item.data = v; v < x && *v != '\n'; v++);
+ if ((item.size = v - item.data) && *item.data == '\t')
+ {
+ item.data++;
+ item.size--;
+ h = 0;
+ }
+ else
+ h = -1;
+ expand(&notice, &tmp, &item);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), h);
+ } while (v++ < x);
+ if (item.size)
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.item[13].data)
+ {
+ expand(&notice, &tmp, &notice.item[13]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[i = 15].data || notice.item[i = 5].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[2].data)
+ {
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(&notice, &tmp, &notice.item[2]);
+ }
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[10].data)
+ {
+ expand(&notice, &tmp, &notice.item[10]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ }
+ if (v = notice.item[0].data)
+ {
+ x = v + notice.item[0].size;
+ q = (x - v) == 1 && (*v == '*' || *v == '-');
+ k = q && notice.type != 4 ? -1 : 0;
+ for (;;)
+ {
+ if (!q)
+ {
+ while (v < x && (*v == ' ' || *v == '\t' || *v == '\r' || *v == '\n' || *v == ',' || *v == '+'))
+ v++;
+ if (v >= x)
+ break;
+ item.data = v;
+ while (v < x && *v != ',' && *v != '+' && *v++ != '>');
+ item.size = v - item.data;
+ item.quote = notice.item[0].quote;
+ }
+ h = 0;
+ for (i = 0; i < notice.ids; i++)
+ if (q || item.size == notice.id[i].name.size && !sstrncmp( item.data, notice.id[i].name.data, item.size))
+ {
+ h = 1;
+ if (notice.type == 4)
+ {
+ copy(&buf, "[-author?", -1);
+ expand(&notice, &buf, &notice.id[i].value);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ }
+ else
+ {
+ if (k < 0)
+ {
+ comment( &notice, &buf, "CONTRIBUTORS",sizeof( "CONTRIBUTORS")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &notice.id[i].value);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ if (!q)
+ break;
+ }
+ if (q)
+ break;
+ if (!h)
+ {
+ if (notice.type == 4)
+ {
+ copy(&buf, "[-author?", -1);
+ expand(&notice, &buf, &item);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ }
+ else
+ {
+ if (k < 0)
+ {
+ comment( &notice, &buf, "CONTRIBUTORS",sizeof( "CONTRIBUTORS")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &item);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ }
+ }
+ if (k > 0)
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.type == 4)
+ {
+ copy(&buf, "[-copyright?", -1);
+ copyright(&notice, &buf);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ if (notice.item[21].data)
+ {
+ copy(&buf, "[-license?", -1);
+ expand(&notice, &buf, &notice.item[21]);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ }
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\n')):(( '\n'),(-1)));
+ }
+ else
+ comment(&notice, &buf, ((char*)0), -1, 0);
+ return (*(( &buf)->nxt>=( &buf)->end?(( &buf)->nxt=( &buf)->end-1):( &buf)->nxt)=0,( &buf)->nxt-( &buf)->buf);
+}
+#line 336 "../../lib/libpp/ppproto.c"
+
+#line 348
+static char*
+linesync __PARAM__((register Proto_t* proto, register char* p, register long n), (proto, p, n)) __OTORP__(register Proto_t* proto; register char* p; register long n;){
+
+ if (proto->flags & (1L<<13))
+
+ {
+
+ p = strcopy(p, "\n#line ");
+
+
+
+ p = number(p, n);
+ *p++ = '\n';
+ }
+ return p;
+}
+
+
+
+
+
+
+static char*
+init __PARAM__((Proto_t* proto, char* op, int flags), (proto, op, flags)) __OTORP__(Proto_t* proto; char* op; int flags;){
+ register char* s;
+
+ if (flags & (1L<<10))
+ {
+ op = strcopy(op, "\
+\n\
+#if !defined(__PROTO__)\n\
+# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
+# if defined(__cplusplus)\n\
+# define __LINKAGE__ \"C\"\n\
+# else\n\
+# define __LINKAGE__\n\
+# endif\n\
+# define __STDARG__\n\
+# define __PROTO__(x) x\n\
+# define __OTORP__(x)\n\
+# define __PARAM__(n,o) n\n\
+# if !defined(__STDC__) && !defined(__cplusplus)\n\
+# if !defined(c_plusplus)\n\
+# define const\n\
+# endif\n\
+# define signed\n\
+# define void int\n\
+# define volatile\n\
+# define __V_ char\n\
+# else\n\
+# define __V_ void\n\
+# endif\n\
+# else\n\
+# define __PROTO__(x) ()\n\
+# define __OTORP__(x) x\n\
+# define __PARAM__(n,o) o\n\
+# define __LINKAGE__\n\
+# define __V_ char\n\
+# define const\n\
+# define signed\n\
+# define void int\n\
+# define volatile\n\
+# endif\n\
+# define __MANGLE__ __LINKAGE__\n\
+# if defined(__cplusplus) || defined(c_plusplus)\n\
+# define __VARARG__ ...\n\
+# else\n\
+# define __VARARG__\n\
+# endif\n\
+# if defined(__STDARG__)\n\
+# define __VA_START__(p,a) va_start(p,a)\n\
+# else\n\
+# define __VA_START__(p,a) va_start(p)\n\
+# endif\n\
+# if !defined(__INLINE__)\n\
+# if defined(__cplusplus)\n\
+# define __INLINE__ extern __MANGLE__ inline\n\
+# else\n\
+# if defined(_WIN32) && !defined(__GNUC__)\n\
+# define __INLINE__ __inline\n\
+# endif\n\
+# endif\n\
+# endif\n\
+#endif\n\
+#if !defined(__LINKAGE__)\n\
+#define __LINKAGE__ /* 2004-08-11 transition */\n\
+#endif\n\
+");
+ }
+ else
+ op = strcopy(op, "\
+\n\
+#if !defined(__PROTO__)\n\
+#include <prototyped.h>\n\
+#endif\n\
+#if !defined(__LINKAGE__)\n\
+#define __LINKAGE__ /* 2004-08-11 transition */\n\
+#endif\n\
+");
+ if (proto->package)
+ {
+ s = "\
+#ifndef __MANGLE_%_DATA__\n\
+# ifdef _BLD_%\n\
+# ifdef __EXPORT__\n\
+# define __MANGLE_%_DATA__ __MANGLE__ __EXPORT__\n\
+# else\n\
+# define __MANGLE_%_DATA__ __MANGLE__\n\
+# endif\n\
+# define __MANGLE_%_FUNC__ __MANGLE__\n\
+# else\n\
+# ifdef __IMPORT__\n\
+# define __MANGLE_%_DATA__ __MANGLE__ __IMPORT__\n\
+# else\n\
+# define __MANGLE_%_DATA__ __MANGLE__\n\
+# endif\n\
+# define __MANGLE_%_FUNC__ __MANGLE__\n\
+# endif\n\
+#endif\n\
+";
+ for (;;)
+ {
+ switch (*op++ = *s++)
+ {
+ case 0:
+ op--;
+ break;
+ case '%':
+ op = strcopy(op - 1, proto->package);
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ return op;
+}
+
+
+#line 422
+static char*
+nns __PARAM__((register char* s), (s)) __OTORP__(register char* s;){
+ while (*s == ' ' || *s == '\t' || *s == '\n')
+ s++;
+ return s;
+}
+
+
+#line 439
+static int
+directive __PARAM__((register char* s, int dir), (s, dir)) __OTORP__(register char* s; int dir;){
+ switch (*(s = nns(s)))
+ {
+ case 'e':
+ case 'i':
+ dir <<= 2;
+ switch (*++s)
+ {
+ case 'f':
+ dir |= 01;
+ break;
+ case 'l':
+ dir |= 02;
+ break;
+ case 'n':
+ dir |= 03;
+ break;
+ }
+ break;
+ }
+ return dir;
+}
+
+
+
+
+
+
+
+static int
+lex __PARAM__((register Proto_t* proto, register long flags), (proto, flags)) __OTORP__(register Proto_t* proto; register long flags;){
+ register char* ip;
+ register char* op;
+ register int c;
+ register int state;
+ register short* rp;
+ char* m;
+ char* e;
+ char* t;
+ char* bp;
+ char* v;
+ char* im;
+ char* ko;
+ char* aom;
+ int n;
+ int line;
+ int quot;
+ int brack;
+ int sub;
+ int x;
+ int vc;
+
+ char* ie = 0;
+ char* om = 0;
+ char* aim = 0;
+ char* aie = 0;
+ char* func = 0;
+ int call = 0;
+ int dir = 0;
+ int group = 0;
+ int last = 0;
+ int paren = 0;
+
+ char* qe = 0;
+ int qn = 0;
+ int args = 0;
+
+
+ do{(ip=proto->ip);(op=proto->op);call=proto->call;}while(0);
+
+ if (flags & (1L<<5)) (ko=op);
+
+ fsm_start:
+ proto->tp = ip;
+ state = 0;
+ bp = ip;
+ do
+ {
+ rp = _pp_fsmtab[state];
+ fsm_get:
+ while (!(state = rp[c = (*(unsigned char*)ip++)]));
+ fsm_next:
+ ;
+ } while (state > 0);
+ if ((n = ip - bp - 1) > 0)
+ {
+ ip = bp;
+ do switch( n) { default : memcopy( op, ip, n); op += n; ip += n; break; case 7 : * op++ = * ip++; case 6 : * op++ = * ip++; case 5 : * op++ = * ip++; case 4 : * op++ = * ip++; case 3 : * op++ = * ip++; case 2 : * op++ = * ip++; case 1 : * op++ = * ip++; case 0 : break; } while (0);
+ ip++;
+ }
+ state = ~state;
+ fsm_terminal:
+ switch ((( state)&((1<<(7+1))-1)))
+ {
+ case ((0+28)+11):
+ if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
+ {
+ case '+':
+ case '-':
+ case '*':
+ case '&':
+ (*op++=( ' '));
+ break;
+ }
+ (*op++=( c));
+ break;
+
+ case ((0+28)+0):
+ (ip--);
+ c = (*(op-1));
+ break;
+
+ case ((0+28)+1):
+ switch (c)
+ {
+ case '\n':
+ if ((( rp)>=_pp_fsmtab[(0+16)]&&( rp)<=_pp_fsmtab[(0+18)])) goto fsm_newline;
+ (*op++=( c));
+ proto->line++;
+ rp = _pp_fsmtab[(0+13)];
+ break;
+ case '/':
+
+ if ((flags & ((1L<<5)|(1L<<15))) == (1L<<5)) (op=ko);
+ else
+
+ (*op++=( c));
+ if ((( rp)>=_pp_fsmtab[(0+16)]&&( rp)<=_pp_fsmtab[(0+18)]))
+ {
+ rp = _pp_fsmtab[(0+16)];
+ break;
+ }
+ goto fsm_start;
+ case (255+1):
+ break;
+ default:
+
+ if ((flags & ((1L<<5)|(1L<<15))) == (1L<<5)) (op=ko);
+ else
+
+ (*op++=( c));
+ rp = _pp_fsmtab[(( rp)>=_pp_fsmtab[(0+16)]&&( rp)<=_pp_fsmtab[(0+18)]) ? (0+16) : (0+14)];
+ break;
+ }
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+2):
+ if (c)
+ {
+ if (state = _pp_fsmtab[(0+28)][((( rp)-_pp_fsmtab[0])/(255+1))+1])
+ goto fsm_terminal;
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ (ip--);
+ fsm_eob:
+ if ((flags & ((1L<<1)|((1L<<16))|(1L<<21))) == ((1L<<16)) && (proto->flags & (1L<<16)))
+ {
+
+ if (!(flags & (1L<<5)))
+
+ flags |= (1L<<24);
+ c = ip - proto->ib;
+ if (!(flags & (1L<<15)))
+ im = proto->tp;
+ if (ip > proto->ib)
+ {
+ n = ip - im;
+ if (ip - n < proto->ib)
+ proto->flags |= (1L<<4);
+ memcopy(proto->ib - n, ip - n, n);
+ ip = proto->ib;
+ }
+ proto->tp -= c;
+ if (flags & (1L<<15))
+ {
+ im -= c;
+ ie -= c;
+ }
+ if (aim)
+ aim -= c;
+ if (aie)
+ aie -= c;
+ if ((n = read(proto->fd, ip, proto->iz)) > 0)
+ {
+ if ((proto->options & (1L<<0)) && n < proto->iz)
+ {
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ *(ip + n) = 0;
+ if (state & (1<<7))
+ goto fsm_splice;
+ bp = ip;
+ goto fsm_get;
+ }
+ *ip = 0;
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ if (state & (1<<7))
+ goto fsm_splice;
+
+ if (!(flags & (1L<<21)) && (state = rp[c = (255+1)]))
+ {
+ bp = ip;
+ goto fsm_next;
+ }
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+
+ case ((0+28)+3):
+ quot = c;
+
+ if (c == '"' && qe)
+ {
+ for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++);
+ if (t == op)
+ {
+ op = qe;
+ qe = 0;
+ qn = n;
+ }
+ else (*op++=( c));
+ }
+ else
+
+ (*op++=( c));
+ rp = _pp_fsmtab[(0+21)];
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+4):
+ if (c == quot)
+ {
+
+ if (!(flags & (1L<<3)))
+ qe = (c == '"') ? op : (char*)0;
+
+ (*op++=( c));
+
+ while (qn > 0)
+ {
+ qn--;
+ (*op++=( '\n'));
+ }
+
+ }
+ else if (c != '\n' && c != (255+1))
+ {
+ (*op++=( c));
+ bp = ip;
+ goto fsm_get;
+ }
+ else
+ {
+
+ while (qn > 0)
+ {
+ qn--;
+ (*op++=( '\n'));
+ }
+
+ (ip--);
+ }
+ c = (0401+1);
+ break;
+
+ case ((0+28)+5):
+
+ if (flags & (1L<<0)) (*op++=( c));
+ else
+
+ switch (c)
+ {
+ case 'a':
+ n = (('A'==0301)?0057:0007);
+ goto fsm_oct;
+ case 'E':
+ n = (('A'==0301)?0047:0033);
+ goto fsm_oct;
+ case 'v':
+ n = 0013;
+ goto fsm_oct;
+ case 'x':
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ lex(proto, (flags & ((1L<<16))) | (1L<<21));
+ for (n = x = 0; (c = (*(unsigned char*)ip++)), x < 3; x++) switch (c)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9':
+ n = (n << 4) + c - '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd':
+ case 'e': case 'f':
+ n = (n << 4) + c - 'a' + 10;
+ break;
+ case 'A': case 'B': case 'C': case 'D':
+ case 'E': case 'F':
+ n = (n << 4) + c - 'A' + 10;
+ break;
+ default:
+ goto fsm_hex;
+ }
+ fsm_hex:
+ (ip--);
+ fsm_oct:
+ (*op++=( ((n >> 6) & 07) + '0'));
+ (*op++=( ((n >> 3) & 07) + '0'));
+ (*op++=( (n & 07) + '0'));
+ break;
+ default:
+ (*op++=( c));
+ break;
+ }
+ rp = _pp_fsmtab[(0+21)];
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+6):
+ (ip--);
+
+ if ((flags & (1L<<5)) && *proto->tp == 's' && !sstrncmp( proto->tp, "static", 6))
+ {
+ c = ((0500+4)+9);
+ break;
+ }
+
+ if (*proto->tp == '_' && !sstrncmp( proto->tp, "__STDPP__directive", 6)) c = '#';
+ else c = (0401+0);
+
+ break;
+
+ case ((0+28)+7):
+ fsm_newline:
+ proto->line++;
+
+ if (flags & (1L<<5))
+ {
+ if (op != proto->ob && (*(op-1)) != ' ' && (*(op-1)) != '\n')
+ (*op++=( ' '));
+ }
+ else
+
+ (*op++=( c));
+ if (flags & (1L<<3))
+ {
+
+ if (flags & (1L<<0))
+ {
+ if (flags & (1L<<5)) (op=ko);
+ if (flags & (1L<<12))
+ {
+ *(ip - 1) = 0;
+ op = strcopy(om, "/* ");
+ op = strcopy(op, im);
+ op = strcopy(op, " */\n");
+ }
+ flags &= ~((1L<<2)|(1L<<3)|(1L<<7)|(1L<<8)|(1L<<12)|(1L<<15)|(1L<<22)|(1L<<26));
+ }
+ else
+
+ {
+ if ((flags & ((1L<<2)|(1L<<22))) == ((1L<<2)|(1L<<22)))
+ {
+ *(ip - 1) = 0;
+ op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n");
+ op = strcopy(op, im);
+ op = strcopy(op, "\n#else\n");
+ bp = ip;
+ ip = im;
+ *op++ = *ip++;
+ while (*op = *ip++)
+ if (*op++ == '#' && *ip != '(')
+ {
+ op--;
+ while (*--op == ' ' || *op == '\t');
+ if (*ip == '#')
+ {
+ op = strcopy(op + 1, "/**/");
+ while (*++ip == ' ' || *ip == '\t');
+ }
+ else
+ {
+ if (*op != '"') *++op = '"';
+ op++;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip == '"') ip++;
+ else *op++ = '"';
+ }
+ }
+ ip = bp;
+ op = strcopy(op, "\n#endif\n");
+ op = linesync(proto, op, proto->line);
+ }
+ flags &= ~((1L<<2)|(1L<<3)|(1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<22)|(1L<<23)|(1L<<25)|(1L<<26));
+ }
+ call = 0;
+ group = 0;
+ paren = 0;
+ last = '\n';
+ }
+ if (paren == 0 && (flags & ((1L<<15)|(1L<<21)|(1L<<23)|(1L<<24))) == (1L<<24))
+ {
+
+ if (flags & (1L<<5)) (op=ko);
+
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ goto fsm_start;
+
+ case ((0+28)+8):
+ (*op++=( c));
+ rp = _pp_fsmtab[((( state)>>(7+1))&((1<<7)-1))];
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+13):
+ (*op++=( c));
+ c = (((( state)>>(7+1))&((1<<7)-1))+0401);
+ break;
+
+ case ((0+28)+14):
+ (ip--);
+ c = (((( state)>>(7+1))&((1<<7)-1))+0401);
+ break;
+
+ case (((0+28)+12)):
+ (ip--);
+ c = (0401+0);
+ if (!(flags & (1L<<1))) switch (((((long)( *proto->tp))<<16)|(((long)( *(ip - 1)))<<8)|((long)( ip - proto->tp))))
+ {
+ case ((((long)( 'N'))<<16)|(((long)( 'N'))<<8)|((long)( 3))):
+ if (proto->tp[1] == 'o')
+ c = ((0500+4)+6);
+ break;
+ case ((((long)( 'd'))<<16)|(((long)( 'o'))<<8)|((long)( 2))):
+ c = ((0500+4)+6);
+ break;
+ case ((((long)( 'e'))<<16)|(((long)( 'e'))<<8)|((long)( 4))):
+ if (!(flags & (1L<<21)) && (flags & ((1L<<3)|(1L<<25))) != (1L<<3) && !sstrncmp( proto->tp, "else", 4))
+ {
+ c = ((0500+4)+8);
+ goto fsm_id;
+ }
+ break;
+ case ((((long)( 'e'))<<16)|(((long)( 'n'))<<8)|((long)( 6))):
+ if (!sstrncmp( proto->tp, "extern", 6))
+ c = ((0500+4)+9);
+ break;
+ case ((((long)( 'f'))<<16)|(((long)( 'r'))<<8)|((long)( 3))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "for", 3))
+ {
+ c = ((0500+4)+11);
+ goto fsm_id;
+ }
+ break;
+ case ((((long)( 'i'))<<16)|(((long)( 'f'))<<8)|((long)( 2))):
+ c = ((0500+4)+13);
+ break;
+ case ((((long)( 'i'))<<16)|(((long)( 'e'))<<8)|((long)( 6))):
+ if (!sstrncmp( proto->tp, "inline", 6) && !(flags & ((1L<<15)|(1L<<23)|(1L<<25)|(1L<<26))) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0))
+ {
+ flags |= (1L<<23);
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ line = proto->line;
+ op = strcopy(op - 6, "__INLINE__");
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ }
+ break;
+ case ((((long)( 'r'))<<16)|(((long)( 'n'))<<8)|((long)( 6))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "return", 6))
+ {
+ c = ((0500+4)+17);
+ goto fsm_id;
+ }
+ break;
+ case ((((long)( 's'))<<16)|(((long)( 'c'))<<8)|((long)( 6))):
+ if ((proto->options & (1L<<6)) && !sstrncmp( proto->tp, "static", 6))
+ {
+ proto->ox = op - 6;
+ flags |= (1L<<6);
+ }
+ break;
+ case ((((long)( 't'))<<16)|(((long)( 'f'))<<8)|((long)( 7))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "typedef", 7))
+ {
+ flags |= (1L<<26);
+ c = ((0500+4)+9);
+ }
+ break;
+ case ((((long)( 'v'))<<16)|(((long)( 't'))<<8)|((long)( 8))):
+ if (*ip == '(' && !sstrncmp( proto->tp, "va_start", 8)) c = (0500+1);
+ break;
+ case ((((long)( 'v'))<<16)|(((long)( 'd'))<<8)|((long)( 4))):
+ if (!sstrncmp( proto->tp, "void", 4))
+ {
+ if (flags & ((1L<<0)|(1L<<19)|(1L<<10)|(1L<<11))) c = ((0500+4)+30);
+ else
+ {
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ line = proto->line;
+ if (lex(proto, (flags & ((1L<<16))) | (1L<<21)) == '*')
+ {
+ memcopy(op - 4, "__V_", 4);
+ memcopy(ip - 4, "__V_", 4);
+ }
+ else c = ((0500+4)+30);
+ proto->line = line;
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ bp = ip;
+ }
+ }
+ break;
+ case ((((long)( 'w'))<<16)|(((long)( 'e'))<<8)|((long)( 5))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "while", 5))
+ {
+ c = ((0500+4)+26);
+ goto fsm_id;
+ }
+ break;
+ }
+
+ if ((flags & (1L<<0)) && c != ((0500+4)+9))
+ c = (0401+0);
+
+ break;
+
+ case ((0+28)+10):
+ goto fsm_start;
+
+ case ((0+28)+15):
+ (ip--);
+
+ if ((flags & ((1L<<5)|(1L<<15))) == (1L<<5))
+ {
+ while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t'))
+ op--;
+ if (op > proto->ob && *(op - 1) != '\n') *op++ = ' ';
+ }
+
+ goto fsm_start;
+
+ default:
+ if (state & (1<<7))
+ {
+ if (c == '\\')
+ {
+ if (!(n = (*(unsigned char*)ip++)))
+ {
+ goto fsm_eob;
+ fsm_splice:
+ c = '\\';
+ n = (*(unsigned char*)ip++);
+ }
+ if (n == '\n')
+ {
+ proto->line++;
+ (*op++=( '\\'));
+ (*op++=( '\n'));
+ bp = ip;
+ goto fsm_get;
+ }
+ (ip--);
+ }
+ state &= ~(1<<7);
+ if (state >= (0+28))
+ goto fsm_terminal;
+ rp = _pp_fsmtab[state];
+ }
+ (*op++=( c));
+ bp = ip;
+ goto fsm_get;
+ }
+ if (!(flags & ((1L<<10)|(1L<<11)|(1L<<21))))
+ {
+ if (!(flags & (1L<<3))) switch (c)
+ {
+ case '(':
+
+ if (!(flags & (1L<<0)) || proto->brace == 0)
+
+ {
+ if (paren++ == 0)
+ {
+
+ if (!(flags & (1L<<0)) || group <= 1)
+
+ {
+
+ args = 0;
+
+ if (group++ == 0) group++;
+ else if (flags & (1L<<8)) call++;
+ flags |= (1L<<15);
+ im = ip - 1;
+ om = op - 1;
+ }
+ sub = 0;
+ }
+ else if (paren == 2 && !aim)
+ {
+ sub++;
+ if (last == '(')
+ {
+ flags &= ~(1L<<15);
+ om = 0;
+ }
+ else if (flags & (1L<<8))
+ {
+ aim = ip - 1;
+ aom = op - 1;
+ }
+ else if ((flags & ((1L<<15)|(1L<<25))) == (1L<<15))
+ {
+ for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--);
+ if (m != im && sub == 1)
+ {
+ m = im + (*nns(ip) == '*');
+ }
+ if (m == im)
+ {
+ flags &= ~(1L<<15);
+ om = 0;
+ }
+ }
+ else if ((flags & (1L<<15)) && sub == 1 && *nns(ip) != '*')
+ {
+ flags &= ~(1L<<15);
+ om = 0;
+ }
+ }
+ flags &= ~(1L<<25);
+ }
+ break;
+ case ')':
+
+ if (!(flags & (1L<<0)) || proto->brace == 0)
+
+ if (--paren == 0)
+ {
+
+ if (flags & (1L<<0))
+ {
+ if (group != 2)
+ {
+ c = (0401+0);
+ break;
+ }
+ group++;
+ }
+
+ ie = ip;
+ }
+ else if (paren == 1 && (flags & (1L<<8)) && !aie)
+ aie = ip;
+ break;
+ case '*':
+ if (last == '(' && group == 2)
+ {
+ group--;
+ if (paren == 1)
+ {
+ flags |= (1L<<8);
+ aim = aie = 0;
+ }
+ }
+ break;
+ case '#':
+ dir = directive(ip, dir);
+ if (proto->brace == 0 && paren == 0 && last != '=' && (flags & ((1L<<0)|(1L<<1)|(1L<<3)|(1L<<15)|(1L<<19)|(1L<<23)|(1L<<25))) == ((1L<<15)|(1L<<25)) && ((dir & 03) != 03 || ((dir>>2) & 03) != 01))
+ flags |= (1L<<3);
+ else if (!(flags & ((1L<<1)|(1L<<3))))
+ {
+ flags |= (1L<<3);
+ if (!(flags & (1L<<19)))
+ {
+ bp = ip;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e')
+ {
+ if (*++ip == ' ' || *ip == '\t')
+ {
+ proto->line = 0;
+ while (*++ip >= '0' && *ip <= '9')
+ proto->line = proto->line * 10 + *ip - '0';
+ proto->line--;
+ }
+ }
+
+ else if ((flags & ((1L<<0)|(1L<<5))) == (1L<<0))
+ {
+ n = 0;
+ t = ip + 6;
+ while (ip < t && *ip >= 'a' && *ip <= 'z')
+ n = ((( n)<<5)+(( *ip++)-('a'-1)));
+ switch (n)
+ {
+ case ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'l')-('a'-1))))<<5)+(( 's')-('a'-1))))<<5)+(( 'e')-('a'-1))):
+ case ((( ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'n')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'i')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*')
+ {
+ flags |= (1L<<12)|(1L<<15);
+ im = ip;
+ om = op + (ip - bp);
+ }
+ break;
+ case ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'l')-('a'-1))))<<5)+(( 'i')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'r')-('a'-1))))<<5)+(( 'r')-('a'-1))))<<5)+(( 'o')-('a'-1))))<<5)+(( 'r')-('a'-1))):
+ case ((( (( 'i')-('a'-1)))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( (( 'i')-('a'-1)))<<5)+(( 'f')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( ((( (( 'i')-('a'-1)))<<5)+(( 'f')-('a'-1))))<<5)+(( 'n')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( (( 'u')-('a'-1)))<<5)+(( 'n')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ break;
+ case ((( ((( ((( ((( ((( (( 'i')-('a'-1)))<<5)+(( 'n')-('a'-1))))<<5)+(( 'c')-('a'-1))))<<5)+(( 'l')-('a'-1))))<<5)+(( 'u')-('a'-1))))<<5)+(( 'd')-('a'-1))):
+ if (*ip == 'e') ip++;
+
+ case ((( ((( ((( ((( ((( (( 'd')-('a'-1)))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))))<<5)+(( 'i')-('a'-1))))<<5)+(( 'n')-('a'-1))))<<5)+(( 'e')-('a'-1))):
+ case ((( ((( ((( ((( ((( (( 'p')-('a'-1)))<<5)+(( 'r')-('a'-1))))<<5)+(( 'a')-('a'-1))))<<5)+(( 'g')-('a'-1))))<<5)+(( 'm')-('a'-1))))<<5)+(( 'a')-('a'-1))):
+ if (*ip < 'a' || *ip > 'z') break;
+
+ default:
+ flags |= (1L<<12)|(1L<<15);
+ im = bp - 1;
+ om = op - 1;
+ break;
+ }
+ }
+ else
+
+ {
+ if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e')
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>')
+ {
+ op = strcopy(op, "\
+if !defined(va_start)\n\
+#if defined(__STDARG__)\n\
+#include <stdarg.h>\n\
+#else\n\
+#include <varargs.h>\n\
+#endif\n\
+#endif\n\
+");
+ op = linesync(proto, op, proto->line);
+ break;
+ }
+ }
+ else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t'))
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t'))
+ {
+ t = ip;
+ while (*++t == ' ' || *t == '\t');
+ if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'))
+ ip = t;
+ t = ip;
+ while (*++t == ' ' || *t == '\t');
+ if (*t == '_' && *(t + 1) == '_')
+ {
+ op = strcopy(op, "undef __MANGLE__\n");
+ op = linesync(proto, op, proto->line);
+ op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
+ break;
+ }
+ }
+ flags |= (1L<<2)|(1L<<15);
+ im = bp - 1;
+ om = op - 1;
+ }
+ else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t'))
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r'))
+ {
+ op = strcopy(op, "undef __MANGLE__\n");
+ op = linesync(proto, op, proto->line);
+ op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
+ break;
+ }
+ flags |= (1L<<2)|(1L<<15);
+ im = bp - 1;
+ om = op - 1;
+ }
+ }
+ ip = bp;
+ }
+ break;
+ }
+ else
+ break;
+
+ case '{':
+ if (proto->brace++ == 0 && paren == 0)
+ {
+ if (last == '=') flags |= (1L<<9);
+
+ else if (flags & (1L<<0))
+ {
+ if ((flags & ((1L<<15)|(1L<<17)|(1L<<23))) == (1L<<15))
+ {
+ if (args)
+ {
+ v = number(op, args < 0 ? -args : args);
+ v = strcopy(v, " argument actual/formal mismatch");
+ *v++ = ' ';
+ v = memcopy(v, im, ie - im);
+ *v = 0;
+ proto_error((char*)proto + sizeof(Proto_t), 2, op, ((char*)0));
+ }
+ ip--;
+
+ v = ie;
+ while (ie < ip)
+ if (*ie++ == '/' && *ie == '*')
+ {
+ e = ie - 1;
+ while (++ie < ip)
+ {
+ if (*ie == '*')
+ {
+ while (ie < ip && *ie == '*') ie++;
+ if (ie < ip && *ie == '/')
+ {
+ while (++ie < ip && (*ie == ' ' || *ie == '\t'));
+ while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--;
+ if (e > v && *e != '\n') *e++ = ' ';
+ t = ie;
+ while (--e >= v)
+ *--t = *e;
+ v = t;
+ break;
+ }
+ }
+ }
+ }
+ ie = v;
+
+ op = om++;
+ if (flags & (1L<<5))
+ {
+ v = op;
+ while (v > ko && *--v != ' ');
+ if (*v != ' ')
+ {
+ om = (v = (op += 4)) + 1;
+ while (v >= ko + 4)
+ {
+ *v = *(v - 4);
+ v--;
+ }
+ memcopy(ko, "int ", 4);
+ }
+ if (*v == ' ')
+ {
+ while (*(v + 1) == '*')
+ *v++ = '*';
+ *v = '\t';
+ if ((v - ko) <= 8)
+ {
+ om = (e = ++op) + 1;
+ while (e > v)
+ {
+ *e = *(e - 1);
+ e--;
+ }
+ }
+ }
+ om = (v = (op += 7)) + 1;
+ while (v >= ko + 7)
+ {
+ *v = *(v - 7);
+ v--;
+ }
+ memcopy(ko, "extern ", 7);
+ }
+ (*op++=( '('));
+ t = op;
+ e = 0;
+
+ while (ie < ip)
+ {
+ if ((c = *ie) == ' ' || c == '\t' || c == '\n')
+ {
+ while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
+ if (ie >= ip) break;
+ if (c != '*' && op > om) (*op++=( ' '));
+ }
+ if ((n = ((c = *ie) == ',')) || c == ';')
+ {
+ if (flags & (1L<<5))
+ {
+ m = op;
+ while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']'))
+ op--;
+ v = op;
+ while (op > om && (c = *(op - 1)) != ' ' && c != '*')
+ op--;
+ while (*(op - 1) == ' ')
+ op--;
+ if (!e)
+ {
+ e = op;
+ while (e > om && *(e - 1) == '*')
+ e--;
+ }
+
+
+
+
+ if (op <= om)
+ op = strcopy(op, "int");
+ else if (*(op - 1) == ',')
+ op = strcopy(op, " int");
+
+ while (v < m)
+ (*op++=( *v++));
+ }
+ (*op++=( ','));
+ if (n)
+ {
+ if (x = !e) e = op - 1;
+ (*op++=( ' '));
+ m = t;
+ while (m < e)
+ (*op++=( *m++));
+ if (x)
+ {
+ m = e;
+ while (*--e != ' ');
+ while (*(e - 1) == '*') e--;
+ op -= m - e;
+ }
+ }
+ while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
+ if (ie >= ip) (op--);
+ else (*op++=( ' '));
+ if (!n)
+ {
+ t = op;
+ e = 0;
+ }
+ }
+ else if (*ie == '*')
+ {
+ if (op > om && (c = *(op - 1)) == ' ') op--;
+ while (*ie == '*') (*op++=( *ie++));
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ if (c != '(') (*op++=( ' '));
+ }
+ else if (*ie == '(')
+ {
+ if (op > om && *(op - 1) == ' ') op--;
+ (*op++=( *ie++));
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ }
+ else if (*ie == ')')
+ {
+ if (op > om && *(op - 1) == '(')
+ proto_error((char*)proto + sizeof(Proto_t), 1, "function pointer argument prototype omitted", ((char*)0));
+ (*op++=( *ie++));
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ }
+ else if ((flags & (1L<<5)) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !sstrncmp( ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n'))
+ {
+ ie += 8;
+ if (op > om) (op--);
+ }
+ else (*op++=( *ie++));
+ }
+
+ if (op <= om) op = strcopy(op, "void");
+ (*op++=( ')'));
+ if (flags & (1L<<5))
+ {
+ (*op++=( ';'));
+ (*op++=( '\n'));
+ (proto->op=op);
+ (ko=op);
+ }
+ else
+ {
+ (*op++=( '\n'));
+ (*op++=( *ip));
+ }
+ ip++;
+ flags &= ~((1L<<15)|(1L<<23));
+ }
+ }
+
+ else if ((flags & ((1L<<15)|(1L<<19)|(1L<<23)|(1L<<25))) == ((1L<<15)|(1L<<25)))
+ {
+ line = proto->line;
+ op = strcopy(om, " __PARAM__(");
+ op = memcopy(op, im, ie - im);
+ (*op++=( ','));
+ (*op++=( ' '));
+ (*op++=( '('));
+ flags &= ~((1L<<15)|(1L<<23));
+ if (flags & (1L<<27))
+ {
+ if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic);
+ memcopy(proto->variadic, im, vc);
+ op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{");
+ }
+ else
+ {
+ flags |= (1L<<23);
+ proto->ip = im;
+ proto->op = op;
+ group = 0;
+ brack = 0;
+ for (;;)
+ {
+ switch (lex(proto, (flags & ((1L<<16))) | (1L<<21)))
+ {
+ case '[':
+ brack++;
+ continue;
+ case ']':
+ brack--;
+ continue;
+ case '(':
+ if (paren++) group++;
+ continue;
+ case ')':
+ if (--paren == 0)
+ {
+ group = 0;
+ if (flags & (1L<<15))
+ {
+ flags &= ~((1L<<15)|(1L<<23));
+ op = memcopy(op, m, e - m);
+ }
+ break;
+ }
+ continue;
+ case ',':
+ if (paren == 1)
+ {
+ group = 0;
+ if (flags & (1L<<15))
+ {
+ flags &= ~((1L<<15)|(1L<<23));
+ op = memcopy(op, m, e - m);
+ }
+ (*op++=( ','));
+ (*op++=( ' '));
+ proto->op = op;
+ }
+ continue;
+ case (0401+0):
+ if (group <= 1 && !brack)
+ {
+ flags |= (1L<<15);
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ (*op++=( ')'));
+ (*op++=( ')'));
+ }
+ if (!(flags & (1L<<23)))
+ {
+ flags |= (1L<<23);
+ proto->op = strcopy(op, " __OTORP__(");
+ proto->ip = im + 1;
+ n = *(ie - 1);
+ *(ie - 1) = ';';
+ c = *ie;
+ *ie = 0;
+ lex(proto, (flags & ((1L<<16))) | (1L<<1));
+ *(ie - 1) = n;
+ *ie = c;
+ proto->ip = ie;
+ op = proto->op;
+ (*op++=( ')'));
+ }
+ if (flags & (1L<<6)) memcopy( proto->ox, "extern", 6);
+ op = linesync(proto, op, proto->line = line);
+ if (flags & (1L<<3))
+ {
+ proto->brace = 0;
+ (*op++=( '\n'));
+ (*op++=( '#'));
+ }
+ else if (!(flags & (1L<<27))) (*op++=( '{'));
+ }
+ }
+ flags &= ~((1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<23));
+ call = 0;
+ group = 0;
+ break;
+ case '}':
+ flags &= ~((1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<23)|(1L<<25));
+ if (--proto->brace == 0)
+ {
+ flags &= ~((1L<<9)|(1L<<27)|(1L<<28));
+
+ if (flags & (1L<<5)) (op=ko);
+
+ }
+ call = 0;
+ group = 0;
+ paren = 0;
+ break;
+ case '=':
+ if (last == '?') flags |= (1L<<3);
+ else if (paren == 0 && (flags & ((1L<<9)|(1L<<15)|(1L<<23))) == (1L<<15))
+ {
+ if (last == ')' && proto->brace && (group != 2 || call != 2)) flags |= (1L<<23);
+ else goto fsm_statement;
+ }
+ goto fsm_other;
+ case ',':
+
+ if (flags & (1L<<0))
+ {
+ if (paren == 1) args++;
+ else
+ {
+ args--;
+ flags &= ~(1L<<15);
+ }
+ break;
+ }
+
+ if (paren == 0 && (flags & (1L<<1))) *(op - 1) = c = ';';
+
+ case ';':
+ fsm_statement:
+ if (flags & (1L<<9)) ;
+
+ else if (flags & (1L<<0))
+ {
+ if (paren == 0)
+ {
+ if ((flags & (1L<<15)) && last == ')')
+ flags &= ~(1L<<15);
+ if (!(flags & (1L<<15)))
+ {
+ call = 0;
+ group = 0;
+ flags &= ~(1L<<23);
+ if (flags & (1L<<5)) (op=ko);
+ if (flags & (1L<<24))
+ {
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ }
+ else
+ {
+ args--;
+ if ((flags & ((1L<<5)|(1L<<23))) == ((1L<<5)|(1L<<23)))
+ (op=ko);
+ }
+ }
+ }
+
+ else if (paren == 0)
+ {
+ if ((flags & ((1L<<15)|(1L<<17)|(1L<<23))) == (1L<<15) && call > 1)
+ {
+ if ((flags & (1L<<14)) && func)
+ {
+ func[0] = 'F';
+ func[1] = 'U';
+ func[2] = 'N';
+ func[3] = 'C';
+ func = 0;
+ }
+ if ((flags & ((1L<<1)|(1L<<8))) == (1L<<8) && aim && aie < im)
+ {
+ while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++;
+ v = aim;
+ while (v < aie)
+ if (*v++ == ')') break;
+ while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++;
+ if (v == aie || !(flags & (1L<<20)))
+ {
+ if (flags & (1L<<20)) n = 3;
+ else if (v == aie && *v == '(') n = 10;
+ else n = 11;
+ ko = op;
+ om += n;
+ v = op += n;
+ while (v >= ko + n)
+ {
+ *v = *(v - n);
+ v--;
+ }
+ if (flags & (1L<<20)) memcopy(aom, "(...))", 6);
+ else if (n == 10) memcopy(aom, "(__VARARG__))", 13);
+ else
+ {
+ ko = strcopy(aom, " __PROTO__(");
+ ko = memcopy(ko, aim, aie - aim);
+ *ko = ')';
+ if (++ko >= om)
+ {
+ *ko++ = ')';
+ om = ko;
+ }
+ }
+ }
+ }
+ else if (flags & (1L<<26))
+ {
+ op = om;
+ while (*--op == ' ' || *op == '\t' || *op == '\n');
+ if (*op != ')')
+ {
+ op = om += 14;
+ *--op = ')';
+ while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_')
+ *--op = x;
+ memcopy(op - 13, "(__OTORP__(*)", 13);
+ }
+ }
+ if (flags & (1L<<17))
+ ;
+ else if (flags & (1L<<20))
+ {
+ op = om;
+ if (!(flags & (1L<<25))) op = strcopy(op, "(...)");
+ else op = memcopy(op, im, ie - im);
+ (*op++=( c));
+ }
+ else
+ {
+ if (flags & (1L<<1)) op = strcopy(om, "()");
+ else if (!(flags & (1L<<25))) op = strcopy(om, "(__VARARG__)");
+ else
+ {
+ op = strcopy(om, " __PROTO__(");
+ op = memcopy(op, im, ie - im);
+ (*op++=( ')'));
+ }
+ if (flags & (1L<<6)) memcopy( proto->ox, "extern", 6);
+ (*op++=( c));
+ }
+ flags &= ~((1L<<15)|(1L<<27)|(1L<<28));
+ if (c == ',' && !(flags & (1L<<8)))
+ {
+ call = 1;
+ group = 0;
+ break;
+ }
+ }
+ else if (flags & ((1L<<17)|(1L<<23))) call = 0;
+ if (c == ';')
+ {
+ flags &= ~((1L<<6)|(1L<<14)|(1L<<25)|(1L<<26));
+ call = 0;
+ if (flags & (1L<<24))
+ {
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ }
+ else call = call > 1 && c == ',';
+ group = 0;
+ flags &= ~((1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<23));
+ }
+ else if (paren == 1 && group == 1 && !(flags & ((1L<<7)|(1L<<14)))) flags |= (1L<<25)|(1L<<17);
+ break;
+ case ((0500+4)+6):
+ case ((0500+4)+13):
+ flags |= (1L<<25)|(1L<<23);
+ break;
+ case ((0500+4)+9):
+
+ if (flags & (1L<<0))
+ {
+ if (proto->brace == 0)
+ flags |= (1L<<23);
+ }
+ else
+
+ if (paren == 0 && !(flags & (1L<<26)))
+ {
+ flags |= (1L<<14);
+ if (!(flags & (1L<<19)) || proto->package)
+ {
+ op = strcopy(op, " __MANGLE__");
+ if (proto->package)
+ {
+ op = strcopy(op - 1, proto->package);
+ func = op + 1;
+ op = strcopy(op, "_DATA__");
+ }
+ }
+ else
+ func = 0;
+ }
+ break;
+ case (0401+29):
+ if (paren == 0 && (flags & ((1L<<1)|(1L<<27))) == (1L<<1))
+ {
+ op -= 3;
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return c;
+ }
+ if (paren == 1 && !(flags & (1L<<23)))
+ flags |= (1L<<27);
+ flags |= (1L<<25);
+ break;
+ case ((0500+4)+30):
+ goto fsm_id;
+ case (0500+1):
+ if ((flags & ((1L<<19)|(1L<<27))) == (1L<<27))
+ {
+ flags &= ~(1L<<15);
+ line = proto->line;
+ op = strcopy(op - 8, "__VA_START__");
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ for (;;)
+ {
+ switch (lex(proto, (flags & ((1L<<16))) | (1L<<21)))
+ {
+ case 0:
+ case ';':
+ break;
+ case (0401+0):
+ if (!(flags & (1L<<15)))
+ {
+ flags |= (1L<<15);
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ do{(ip=proto->ip);(op=proto->op);call=proto->call;}while(0);
+ if (flags & (1L<<15))
+ {
+ v = m;
+ n = e - m;
+ }
+ else
+ {
+ v = "ap";
+ n = 2;
+ }
+ op = strcopy(op, " __OTORP__(");
+ proto->ip = proto->variadic;
+ proto->op = op;
+ flags &= ~(1L<<15);
+ group = 0;
+ bp = proto->ip + 1;
+ if (*bp == 'r' && !sstrncmp( bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
+ for (;;)
+ {
+ switch (lex(proto, (flags & ((1L<<16))) | (1L<<21)))
+ {
+ case '(':
+ if (paren++) group++;
+ continue;
+ case ')':
+ if (--paren == 0)
+ {
+ if (flags & (1L<<15))
+ {
+ flags &= ~(1L<<15);
+ if (!(flags & (1L<<28)))
+ {
+ op = memcopy(op, m, e - m);
+ op = strcopy(op, " = ");
+ }
+ op = strcopy(op, "va_arg(");
+ op = memcopy(op, v, n);
+ (*op++=( ','));
+ (*op++=( ' '));
+ if (m > bp) op = memcopy(op, bp, m - bp);
+ else op = strcopy(op, "int ");
+ if (group > 1) op = strcopy(op, ")()");
+ else op = memcopy(op, e, proto->ip - e - 1);
+ (*op++=( ')'));
+ (*op++=( ';'));
+ }
+ group = 0;
+ break;
+ }
+ continue;
+ case ',':
+ if (paren == 1)
+ {
+ if (flags & (1L<<15))
+ {
+ flags &= ~(1L<<15);
+ if (!(flags & (1L<<28)))
+ {
+ op = memcopy(op, m, e - m);
+ op = strcopy(op, " = ");
+ }
+ op = strcopy(op, "va_arg(");
+ op = memcopy(op, v, n);
+ (*op++=( ','));
+ (*op++=( ' '));
+ if (m > bp) op = memcopy(op, bp, m - bp);
+ else op = strcopy(op, "int ");
+ if (group > 1) op = strcopy(op, ")()");
+ else op = memcopy(op, e, proto->ip - e - 1);
+ (*op++=( ')'));
+ (*op++=( ';'));
+ bp = proto->ip + 1;
+ if (*bp == 'r' && !sstrncmp( bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
+ }
+ group = 0;
+ proto->op = op;
+ }
+ continue;
+ case (0401+0):
+ if (group <= 1)
+ {
+ flags |= (1L<<15);
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ op = strcopy(op, ")");
+ flags |= (1L<<28);
+ proto->line = line;
+ call = 0;
+ break;
+ }
+
+ case (0401+0):
+ fsm_id:
+
+ if (flags & (1L<<0))
+ {
+ if (!args && paren == 1) args++;
+ break;
+ }
+
+ if (paren == 0)
+ {
+ if (last == ')')
+ {
+ if (proto->brace == 0 && !(flags & (1L<<1))) flags |= (1L<<23);
+ call = !call;
+ }
+ else if ((flags & (1L<<23)) || c == (0401+0) || c == ((0500+4)+30)) call++;
+ else flags |= (1L<<23);
+ if (last == (0401+0)) flags |= (1L<<7);
+ }
+ c = (0401+0);
+ flags |= (1L<<25);
+ break;
+ case (0401+1):
+ if (*proto->tp >= '0' && *proto->tp <= '9')
+ {
+ n = 0;
+ for (;; op--)
+ {
+ switch (*(op - 1))
+ {
+ case 'f':
+ case 'F':
+ t = op;
+ while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
+ if (*t == '.')
+ op--;
+ n = 0;
+ break;
+ case 'l':
+ case 'L':
+ if (!(n & 01))
+ {
+ n |= 01;
+ t = op;
+ while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
+ if (*t == '.')
+ {
+ n = 0;
+ op--;
+ break;
+ }
+ }
+ continue;
+ case 'u':
+ case 'U':
+ n |= 02;
+ continue;
+ }
+ break;
+ }
+ if (n & 01)
+ *op++ = 'L';
+ if (n & 02)
+ {
+ m = op;
+ t = op = m + 10;
+ while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
+ *--t = c;
+ c = *t;
+ strcopy(m + 1, "(unsigned)");
+ *t = c;
+ break;
+ }
+ }
+ goto fsm_other;
+
+ case '[':
+ if ((flags & (1L<<0)) && paren == 0 && group <= 2) flags |= (1L<<23);
+
+
+ default:
+ fsm_other:
+
+ if (flags & (1L<<0)) break;
+
+ flags |= (1L<<25);
+ if (paren == 0) flags |= (1L<<17);
+ break;
+ }
+ else if (c == '#' && *ip != '(') flags |= (1L<<22);
+ last = c;
+
+ if ((flags & ((1L<<5)|(1L<<15))) == ((1L<<5)|(1L<<15)) && ((flags & ((1L<<3)|(1L<<23))) || proto->brace || c != '(' && c != ')' && c != '*' && c != (0401+0)))
+ (op=proto->op);
+ else
+
+ (proto->op=op);
+ goto fsm_start;
+ }
+ else if (flags & ((1L<<10)|(1L<<11)))
+ {
+
+ if ((flags & (1L<<29)) && c == '%' && *ip == '{')
+ t = 0;
+ else
+
+ {
+ if (c == '#')
+ {
+ for (t = ip; *t == ' ' || *t == '\t'; t++);
+ if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f')
+ {
+
+
+
+
+ t = 0;
+ }
+ }
+ else
+ t = "";
+ }
+ if (t)
+ {
+
+ n = ip - proto->tp;
+ ip -= n;
+ op -= n;
+
+
+
+
+ }
+ else
+ while (*ip != '\n')
+ *op++ = *ip++;
+ op = init(proto, op, flags);
+ op = linesync(proto, op, proto->line);
+ flags &= ~((1L<<10)|(1L<<11));
+ proto->flags &= ~((1L<<10)|(1L<<11));
+ goto fsm_start;
+ }
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return c;
+}
+
+
+
+
+
+void
+pppclose __PARAM__((char* iob), (iob)) __OTORP__(char* iob;){
+ register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
+
+ if (proto->flags & (1L<<16)) close(proto->fd);
+ free((char*)proto);
+}
+
+
+#line 2055
+char*
+pppopen __PARAM__((char* file, int fd, char* notice, char* options, char* package, char* comment, int flags), (file, fd, notice, options, package, comment, flags)) __OTORP__(char* file; int fd; char* notice; char* options; char* package; char* comment; int flags;){
+ register Proto_t* proto;
+ register char* iob;
+ register long n;
+ register char* s;
+ char* t;
+ int pragma;
+ int clr;
+ int hit;
+ int i;
+ int z;
+ char* b;
+
+ int comlen;
+ char com[80];
+
+ int m = 0;
+
+ static int retain;
+
+
+
+
+
+
+ if (flags & (1<<0)) flags &= ~(1<<5);
+
+ if (flags & (1<<11)) flags &= ~retain;
+ else retain &= (1<<6);
+ if (file && (fd = open(file, O_RDONLY)) < 0) return 0;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+
+
+
+
+ n = (16*1024);
+ if (!(proto = (( 0)?( Proto_t*)realloc((char*)( 0),sizeof( Proto_t)*( 1)+( 5 * n + 2)):( Proto_t*)calloc(1,sizeof( Proto_t)*( 1)+( 5 * n + 2)))))
+ return 0;
+ proto->iz = n;
+ proto->oz = 3 * n;
+ proto->flags |= (1L<<16);
+ }
+ proto->fd = fd;
+ proto->package = package;
+ iob = (char*)proto + sizeof(Proto_t);
+ proto->op = proto->ob = iob;
+ proto->ip = proto->ib = iob + proto->oz + n;
+ if (m) proto->options |= (1L<<0);
+ if (!comment)
+ comment = "/*";
+ if (!(proto->cc[0] = comment[0]))
+ notice = options = 0;
+ else if (comment[1])
+ {
+ proto->cc[1] = comment[1];
+ proto->cc[2] = comment[2] ? comment[2] : comment[0];
+ }
+ else
+ proto->cc[1] = proto->cc[2] = comment[0];
+
+
+
+
+
+ n = read(fd, proto->ip, proto->iz);
+ if (!(proto->flags & (1L<<16)))
+ close(fd);
+ if (n < 0)
+ {
+ pppclose(iob);
+ return 0;
+ }
+ *(proto->ip + n) = 0;
+
+
+#line 2165
+ if (!notice && !options || (comlen = astlicense(com, sizeof(com), ((char*)0), "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0)
+ *com = 0;
+
+ hit = (notice || options) ? 0 : 0x02;
+ pragma = -1;
+ s = proto->ip;
+ m = 80;
+ while (m-- > 0 && *s && hit != (0x01|0x02))
+ {
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == '#')
+ {
+ b = s++;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == *"pragma"&& !sstrncmp( s, "pragma", sizeof("pragma") - 1) && (*(s += sizeof("pragma") - 1) == ' ' || *s == '\t'))
+ {
+ clr = 0;
+ while (*s && *s != '\r' && *s != '\n')
+ {
+ for (; *s == ' ' || *s == '\t'; s++);
+ for (t = s; *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n'; s++);
+ z = s - t;
+ for (i = 0; i < (sizeof( pragmas)/sizeof( pragmas[0])); i++)
+ if (pragmas[i].size == z && !sstrncmp( t, pragmas[i].name, z))
+ {
+ clr = 1;
+ hit |= pragmas[i].hit;
+ switch (pragmas[i].hit)
+ {
+ case 0x02:
+ notice = options = 0;
+ break;
+ case 0x01:
+ pragma = pragmas[i].val;
+ break;
+ }
+ }
+ }
+ if (clr)
+ {
+
+ if (!(flags & (1<<1)) || (flags & (1<<8)))
+
+ for (; b < s; *b++ = ' ');
+ }
+ }
+ }
+ else if (*s == *"/* : : generated by proto : : */\n"&& !sstrncmp( s, "/* : : generated by proto : : */\n", sizeof("/* : : generated by proto : : */\n") - 1))
+ {
+ pragma = 0;
+ break;
+ }
+
+ else if (*s == '%' && *(s + 1) == '{')
+ proto->flags |= (1L<<29);
+ else if (!(hit & 0x02))
+ {
+ if (*s == *com && !sstrncmp( s, com, comlen))
+ {
+ hit |= 0x02;
+ notice = options = 0;
+ }
+ else
+ for (; *s && *s != '\n' && !(hit & 0x02); s++)
+ for (i = 0; i < (sizeof( notices)/sizeof( notices[0])); i++)
+ if (*s == notices[i].name[0] && !sstrncmp( s, notices[i].name, notices[i].size))
+ {
+ s += notices[i].size;
+ if (notices[i].val)
+ {
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9')
+ {
+ hit |= notices[i].hit;
+ notice = options = 0;
+ }
+ }
+ else
+ {
+ hit |= notices[i].hit;
+ notice = options = 0;
+ }
+ break;
+ }
+ }
+
+ while (*s && *s++ != '\n');
+ }
+ if (flags & (1<<10)) proto->flags |= (1L<<20);
+ if (flags & (1<<12)) proto->test = 1;
+ if (flags & (1<<2)) proto->options |= (1L<<6);
+
+ if (flags & (1<<0)) pragma = -pragma;
+ if (flags & (1<<1)) pragma = 0;
+ if (flags & (1<<7)) proto->flags |= (1L<<13);
+ if (!(proto->flags & (1L<<29)) && file && (m = sstrlen( file)) > 2 && file[--m] == 'y' && file[--m] == '.')
+ proto->flags |= (1L<<29);
+
+ if (pragma <= 0)
+ {
+ if (flags & (1<<10))
+ {
+ flags &= ~((1<<4)|(1<<5));
+ proto->flags |= (1L<<19);
+ }
+ else if (!(flags & ((1<<3)|(1<<9))))
+ {
+ pppclose(iob);
+ return 0;
+ }
+ else if ((flags & ((1<<3)|(1<<9))) == (1<<9) || !pragma)
+ {
+ proto->flags |= (1L<<18);
+ if (proto->flags & (1L<<16))
+ proto->oz += proto->iz;
+ proto->iz = n;
+ if (notice || options)
+ {
+ if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!')
+ {
+ s = proto->ip;
+ while (*s && *s++ != '\n');
+ m = s - proto->ip;
+ proto->op = memcopy(proto->op, proto->ip, m);
+ proto->ip = s;
+ proto->iz = n -= m;
+ }
+
+ if (proto->cc[0])
+ {
+ if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
+ proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, ((char*)0));
+ else
+ proto->op += comlen;
+ }
+ if (!(flags & (1<<0)) && !(proto->flags & (1L<<29)))
+
+ proto->op = linesync(proto, proto->op, 1);
+ proto->iz += proto->op - proto->ob;
+ }
+ memcopy(proto->op, proto->ip, n);
+ return iob;
+ }
+ }
+
+ if (!(retain & (1<<6)))
+ {
+ retain |= (1<<6);
+ ppfsm(4, ((char*)0));
+ }
+
+ proto->line = 1;
+
+ if (notice || options || (flags & ((1<<4)|(1<<5))))
+ {
+
+ if (notice || options)
+ {
+ if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
+ proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, ((char*)0));
+ else
+ proto->op += comlen;
+ }
+
+ if (flags & (1<<5))
+ {
+ proto->flags |= (1L<<11);
+ if (flags & (1<<11))
+ retain |= (1<<5);
+ }
+ else if (flags & (1<<4))
+ {
+ if (flags & (1<<11)) retain |= (1<<4);
+
+ if (flags & (1<<0))
+ {
+ *proto->op++ = '#';
+ proto->op = strcopy(proto->op, "pragma");
+ *proto->op++ = ' ';
+ proto->op = strcopy(proto->op, pragmas[0].name);
+ *proto->op++ = '\n';
+ }
+ else
+
+ proto->flags |= (1L<<10);
+ }
+
+ if (!(flags & (1<<0)))
+ {
+ if (proto->flags & (1L<<29))
+ {
+ proto->op = strcopy(proto->op, "\n%{\n"+ !notice);
+ proto->op = strcopy(proto->op, "/* : : generated by proto : : */\n");
+ proto->op = strcopy(proto->op, "%}\n");
+ }
+ else
+ {
+ if (n || notice || options)
+ *proto->op++ = '\n';
+ proto->op = strcopy(proto->op, "/* : : generated by proto : : */\n");
+ if (n)
+ proto->op = linesync(proto, proto->op, proto->line);
+ else if (proto->flags & ((1L<<10)|(1L<<11)))
+ proto->op = init(proto, proto->op, proto->flags);
+ }
+ }
+
+ }
+
+
+ proto->file = file;
+ if (flags & (1<<0))
+ {
+ proto->flags |= (1L<<0);
+ if (!(flags & (1<<4))) proto->flags |= (1L<<5);
+ }
+
+ return iob;
+}
+
+
+
+
+
+
+int
+pppread __PARAM__((char* iob), (iob)) __OTORP__(char* iob;){
+ register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
+ register int n;
+
+ if (proto->flags & (1L<<18))
+ {
+ if (proto->iz)
+ {
+ n = proto->iz;
+ proto->iz = 0;
+ }
+ else if (!(proto->flags & (1L<<16))) n = 0;
+ else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & (1L<<0)) && n < proto->oz)
+ {
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ }
+ else
+ {
+ if (proto->op == proto->ob)
+ {
+ if (proto->flags & (1L<<4)) return -1;
+
+ if (proto->flags & (1L<<29))
+ {
+ register char* ip = proto->ip;
+ register char* op = proto->ob;
+ register char* ep = proto->ob + proto->oz - 2;
+
+ if (!*ip)
+ {
+ ip = proto->ip = proto->ib;
+ if (!(proto->flags & (1L<<16))) n = 0;
+ else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & (1L<<0)) && n < proto->iz)
+ {
+ if (n < 0) n = 0;
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ ip[n] = 0;
+ }
+ if (proto->flags & (1L<<30))
+ {
+ proto->flags &= ~(1L<<30);
+ if (*ip == '%')
+ {
+ *op++ = *ip++;
+ if (proto->flags & (1L<<31)) proto->flags &= ~(1L<<29);
+ else proto->flags |= (1L<<31);
+ }
+ }
+ if (proto->flags & (1L<<29))
+ while (op < ep && (n = *op++ = *ip))
+ {
+ ip++;
+ if (n == '%')
+ {
+ if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n'))
+ {
+ *op++ = *ip++;
+ if (proto->flags & (1L<<31)) proto->flags &= ~(1L<<29);
+ else proto->flags |= (1L<<31);
+ break;
+ }
+ if (!*ip)
+ {
+ *op++ = '%';
+ proto->flags |= (1L<<30);
+ break;
+ }
+ }
+ else if (n == '\n') proto->line++;
+ }
+ proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip);
+ proto->ip = ip;
+ }
+ else
+
+ lex(proto, proto->flags);
+ if ((proto->flags & ((1L<<4)|(1L<<16))) == (1L<<4))
+ proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n");
+ }
+ n = proto->op - proto->ob;
+ proto->op = proto->ob;
+ }
+ return n;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+#line 269 "proto.c"
+
+
+
+
+
+static int
+proto __PARAM__((char* file, char* license, char* options, char* package, char* copy, char* comment, int flags), (file, license, options, package, copy, comment, flags)) __OTORP__(char* file; char* license; char* options; char* package; char* copy; char* comment; int flags;){
+ char* b;
+ char* e;
+ char* p;
+ int n;
+ int m;
+ int x;
+ int fd;
+ char buf[1024];
+
+ if (file && access(file, 4))
+ proto_error(((char*)0), 2, file, "not found");
+ else if (b = pppopen(file, 0, license, options, package, comment, flags))
+ {
+ if (!file)
+ fd = 1;
+ else if (flags & ((1<<13)<<1))
+ {
+ e = file + sstrlen( file) - 1;
+ x = *e;
+ *e = '_';
+ if ((fd = creat(file, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ {
+ proto_error(b, 2, file, "cannot create temporary file");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ *e = x;
+ }
+ else if (copy)
+ {
+ if (((n = sstrlen( copy)) + sstrlen( file) + 2) > sizeof(buf))
+ {
+ proto_error(b, 2, copy, "copy path too long");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ strcopy( buf, copy);
+ e = buf + n;
+ if (*file != '/')
+ *e++ = '/';
+ strcopy( e, file);
+ if ((fd = creat(buf, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ {
+ for (e = buf; *e == '/'; e++);
+ do
+ {
+ if (*e == '/')
+ {
+ *e = 0;
+ if (access(buf, 0) && mkdir(buf, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH))
+ {
+ proto_error(b, 2, buf, "cannot create copy directory");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ *e = '/';
+ }
+ } while (*e++);
+ if ((fd = creat(buf, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ {
+ proto_error(b, 2, buf, "cannot create copy file");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ }
+ file = buf;
+ }
+ else
+ fd = 1;
+ if (file && (flags & ((1<<13)<<2)))
+ proto_error(b, 0, "convert to", file);
+ while ((n = pppread(b)) > 0)
+ {
+ p = b;
+ for (;;)
+ {
+ if ((m = write(fd, p, n)) <= 0)
+ {
+ proto_error(b, 2, "write error", ((char*)0));
+ flags |= ((1<<13)<<0);
+ break;
+ }
+ if ((n -= m) <= 0)
+ break;
+ p += m;
+ }
+ if (m < 0)
+ break;
+ }
+ if (fd > 1)
+ close(fd);
+ if (file && (flags & ((1<<13)<<1)))
+ {
+ *e = '_';
+ strcopy( b, file);
+ *e = x;
+ if (replace(b, file, !(flags & (1<<0))))
+ proto_error(b, 2, "cannot rename to", file);
+ }
+ pppclose(b);
+ }
+ return flags;
+}
+
+
+
+
+
+typedef struct Sufcom_s
+{
+ char suffix[4];
+ char comment[4];
+} Sufcom_t;
+
+static const Sufcom_t sufcom[] =
+{
+ "c", "/*",
+ "cpp", "/*",
+ "cxx", "/*",
+ "c++", "/*",
+ "C", "/*",
+ "CPP", "/*",
+ "CXX", "/*",
+ "C++", "/*",
+ "f", "C",
+ "F", "C",
+ "h", "/*",
+ "hpp", "/*",
+ "hxx", "/*",
+ "H", "/*",
+ "HPP", "/*",
+ "HXX", "/*",
+ "ksh", "#",
+ "KSH", "#",
+ "l", "/*",
+ "L", "/*",
+ "p", "(*)",
+ "pas", "(*)",
+ "P", "(*)",
+ "PAS", "(*)",
+ "pl", "#",
+ "PL", "#",
+ "pl1", "/*",
+ "pli", "/*",
+ "PL1", "/*",
+ "PLI", "/*",
+ "sh", "#",
+ "SH", "#",
+ "sml", "(*)",
+ "SML", "(*)",
+ "y", "/*",
+ "Y", "/*",
+};
+
+
+
+
+
+static char*
+type __PARAM__((register char* file, char* comment), (file, comment)) __OTORP__(register char* file; char* comment;){
+ register char* suffix;
+ register int i;
+
+ if (file && (!comment || !*comment))
+ {
+ suffix = 0;
+ while (*file)
+ if (*file++ == '.')
+ suffix = file;
+ if (suffix && sstrlen( suffix) <= 3)
+ for (i = 0; i < sizeof(sufcom) / sizeof(sufcom[0]); i++)
+ if (!strcmp(suffix, sufcom[i].suffix))
+ return (char*)sufcom[i].comment;
+ }
+ return comment;
+}
+
+int
+main __PARAM__((int argc, char** argv), (argc, argv)) __OTORP__(int argc; char** argv;){
+ char* b;
+ char* file;
+ int fd;
+ int n;
+ char* op;
+ char* oe;
+ char* comment = 0;
+ char* copy = 0;
+ char* list = 0;
+ char* license = 0;
+ char* options = 0;
+ char* package = 0;
+ int flags = (1<<4);
+ char buf[1024];
+ char opt[4 * 1024];
+
+ ;
+
+ while ((file = *++argv) && *file == '-' && *(file + 1))
+ {
+ for (;;)
+ {
+ switch (*++file)
+ {
+ case 0:
+ break;
+ case 'c':
+ if (!*(comment = ++file))
+ comment = *++argv;
+ break;
+ case 'd':
+ flags |= (1<<1);
+ continue;
+ case 'e':
+ if (!*(package = ++file) && !(package = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'f':
+ flags |= (1<<3);
+ continue;
+ case 'h':
+ flags &= ~(1<<4);
+ continue;
+ case 'i':
+ flags |= (1<<0);
+ continue;
+ case 'l':
+ if (!*(license = ++file) && !(license = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'n':
+ flags |= (1<<7);
+ continue;
+ case 'o':
+ if (!*(b = ++file) && !(b = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ if (!options)
+ {
+ options = op = opt;
+ oe = op + sizeof(opt) - 1;
+ }
+ n = sstrlen( b);
+ if ((n + 1) >= (oe - op))
+ proto_error(((char*)0), 3, b, "too many options");
+ else
+ {
+ *op++ = '\n';
+ memcopy( op, b, n + 1);
+ op += n;
+ }
+ break;
+ case 'p':
+ flags |= (1<<9);
+ continue;
+ case 'r':
+ flags |= ((1<<13)<<1);
+ continue;
+ case 's':
+ flags |= (1<<5);
+ continue;
+ case 't':
+ flags |= (1<<12);
+ continue;
+ case 'v':
+ flags |= ((1<<13)<<2);
+ continue;
+ case 'x':
+ flags |= (1<<2);
+ continue;
+ case 'z':
+ flags |= (1<<1)|(1<<8);
+ continue;
+ case 'C':
+ if (!*(copy = ++file) && !(copy = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'L':
+ if (!*(list = ++file) && !(list = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'P':
+ case '+':
+ flags |= (1<<10);
+ continue;
+ case 'S':
+ comment = "#";
+ continue;
+ default:
+ proto_error(((char*)0), 2, file, "unknown option");
+
+ case '?':
+ b = "Usage: proto [-dfhinprstvzP+S] [-C directory] [-e package] [-l file]\n [-o \"name='value' ...\"] [-L file] file ...\n";
+ write(2, b, sstrlen( b));
+ return 2;
+ }
+ break;
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if (list)
+ {
+ if (*list == '-' && !*(list + 1))
+ fd = 0;
+ else if ((fd = open(list, O_RDONLY)) < 0)
+ proto_error(((char*)0), 3, list, "not found");
+ do
+ {
+ for (b = buf; (n = read(fd, b, 1)) > 0 && *b != '\n' && b < &buf[sizeof(buf) - 1]; b++);
+ if (b > buf)
+ {
+ *b = 0;
+ flags = proto(buf, license, options, package, copy, type(buf, comment), flags);
+ }
+ } while (n > 0);
+ if (fd > 0)
+ close(fd);
+ }
+ if (file)
+ do flags = proto(file, license, options, package, copy, type(file, comment), flags); while (file = *++argv);
+ else if (!list)
+ flags = proto(file, license, options, package, copy, type(file, comment), flags);
+ return errors ? 1 : (flags & ((1<<13)<<0)) ? 2 : 0;
+}
diff --git a/src/cmd/INIT/ratz.c b/src/cmd/INIT/ratz.c
new file mode 100644
index 0000000..df7d1e3
--- /dev/null
+++ b/src/cmd/INIT/ratz.c
@@ -0,0 +1,5293 @@
+/*
+ * ratz -- read a tar gzip archive from the standard input
+ *
+ * coded for portability
+ * _SEAR_* macros for win32 self extracting archives -- see sear(1).
+ */
+
+static char id[] = "\n@(#)$Id: ratz (Jean-loup Gailly, Mark Adler, Glenn Fowler) 1.2.3 2010-10-10 $\0\n";
+
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <error.h>
+
+static const char usage[] =
+"[-?\n@(#)$Id: ratz (Jean-loup Gailly, Mark Adler, Glenn Fowler) 1.2.3 2010-10-10 $\n]"
+"[-author?Jean-loup Gailly]"
+"[-author?Mark Adler]"
+"[-author?Glenn Fowler <gsf@research.att.com>]"
+"[-copyright?Copyright (c) 1995-2005 Jean-loup Gailly and Mark Adler]"
+"[-license?http://www.opensource.org/licenses/zlib-license]"
+"[+NAME?ratz - read a tar gzip archive]"
+"[+DESCRIPTION?\bratz\b extracts files and directories from a tar gzip"
+" archive on the standard input. It is a standalone program for systems"
+" that do not have \bpax\b(1), \btar\b(1) or \bgunzip\b(1). Only regular"
+" files and directories are extracted; all other file types are ignored.]"
+"[+?\b.exe\b files generated by \bsear\b(1) are fully functional \bratz\b"
+" executables, so any \bratz\b option may be used on a \bsear\b file."
+" This allows \bsear\b file contents to be examined and extracted without"
+" executing any embedded installation scripts.]"
+"[c:cat|uncompress?Uncompress the standard input and copy it to the standard"
+" output.]"
+#if defined(_SEAR_EXEC)
+"[i!:install?Execute the sear installation script.]"
+#endif
+"[l:local?Reject files that traverse outside the current directory.]"
+"[m:meter?Display a one line text meter showing archive read progress.]"
+"[n!:convert?In ebcdic environments convert text archive members from ascii"
+" to the native ebcdic.]"
+"[t:list?List each file path on the standard output but do not extract.]"
+"[v:verbose?List each file path on the standard output as it is extracted.]"
+"[V?Print the program version and exit.]"
+"[+SEE ALSO?\bgunzip\b(1), \bpackage\b(1), \bpax\b(1), \bsear\b(1), \btar\b(1)]"
+;
+
+#else
+
+#define NiL ((char*)0)
+
+#endif
+
+#define METER_width 80
+#define METER_parts 20
+
+#ifndef _GUNZIP_H
+#define _GUNZIP_H 1
+
+/*
+ * stripped down zlib containing public gzfopen()+gzread() in one file
+ * USE THE REAL ZLIB AFTER BOOTSTRAP
+ */
+
+#define ZLIB_INTERNAL 1
+#define NO_GZCOMPRESS 1
+
+#define gz_headerp voidp
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if _PACKAGE_ast || defined(__STDC__) || defined(_SEAR_EXEC) || defined(_WIN32)
+
+#define FOPEN_READ "rb"
+#define FOPEN_WRITE "wb"
+
+#else
+
+#define FOPEN_READ "r"
+#define FOPEN_WRITE "w"
+
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if _PACKAGE_ast
+
+#define setmode(d,m)
+
+#else
+
+#if !defined(_WINIX) && (_UWIN || __CYGWIN__ || __EMX__)
+#define _WINIX 1
+#endif
+
+#if _WIN32 && !_WINIX
+
+#include <direct.h>
+#include <io.h>
+#include <fcntl.h>
+#include <windows.h>
+
+#define access _access
+#define chmod _chmod
+#define close _close
+#define dup _dup
+#define lseek _lseek
+#define open _open
+#define read _read
+#define setmode _setmode
+#define unlink _unlink
+
+#define mkdir(a,b) _mkdir(a)
+
+#else
+
+#define HAVE_UNISTD_H 1
+
+#include <unistd.h>
+#include <errno.h>
+
+#define setmode(d,m)
+
+#endif
+
+#if defined(__STDC__)
+
+#include <stdlib.h>
+#include <string.h>
+
+#endif
+
+#endif
+
+#ifndef _ZLIB_H
+#define _ZLIB_H 1
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZCONF_H
+#define _ZCONF_H 1
+
+#if _PACKAGE_ast
+#include <ast_std.h> /* for { _WINIX __IMPORT__ __EXPORT__ } */
+#define z_off_t int32_t
+#if _typ_int64_t
+#define z_off64_t int64_t
+#endif
+#else
+#if !defined(_WINIX) && (_UWIN || __CYGWIN__ || __EMX__)
+#define _WINIX 1
+#endif
+#endif
+
+#if _BLD_z && defined(__EXPORT__)
+#define ZEXTERN __EXPORT__
+#define ZEXPORT
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if HAVE_UNISTD_H
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* _ZCONF_H */
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+#endif /* _ZLIB_H */
+
+#ifndef _ZUTIL_H
+#define _ZUTIL_H 1
+
+#if !_PACKAGE_ast && !defined(STDC)
+#if defined(__STDC__)
+# include <stddef.h>
+#endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+# ifdef M_I86
+ #include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifdef WIN32
+# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
+# define OS_CODE 0x0b
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# ifndef _PTRDIFF_T_DEFINED
+ typedef int ptrdiff_t;
+# define _PTRDIFF_T_DEFINED
+# endif
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+ /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+ /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+#endif
+#ifdef VMS
+# define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef Z_DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+#endif /* _ZUTIL_H */
+
+#ifndef _ZUTIL_C
+#define _ZUTIL_C
+
+#if 0 && !_PACKAGE_ast && !defined(STDC)
+extern void exit OF((int));
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#if 0 && !_PACKAGE_ast
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* _ZUTIL_C */
+
+#ifndef _CRC32_H
+#define _CRC32_H 1
+
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+#ifndef TBLS
+#define TBLS 1
+#endif
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+ {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d
+ },
+};
+
+#endif /* _CRC32_H */
+
+#ifndef _CRC32_C
+#define _CRC32_C 1
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ u4 endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffff;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffff;
+}
+
+#undef DO1
+#undef DO8
+
+#endif /* _CRC32_C */
+
+#ifndef _ADLER32_C
+#define _ADLER32_C 1
+
+#define BASE 65521 /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+# define MOD(a) \
+ do { \
+ if (a >= (BASE << 16)) a -= (BASE << 16); \
+ if (a >= (BASE << 15)) a -= (BASE << 15); \
+ if (a >= (BASE << 14)) a -= (BASE << 14); \
+ if (a >= (BASE << 13)) a -= (BASE << 13); \
+ if (a >= (BASE << 12)) a -= (BASE << 12); \
+ if (a >= (BASE << 11)) a -= (BASE << 11); \
+ if (a >= (BASE << 10)) a -= (BASE << 10); \
+ if (a >= (BASE << 9)) a -= (BASE << 9); \
+ if (a >= (BASE << 8)) a -= (BASE << 8); \
+ if (a >= (BASE << 7)) a -= (BASE << 7); \
+ if (a >= (BASE << 6)) a -= (BASE << 6); \
+ if (a >= (BASE << 5)) a -= (BASE << 5); \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+#endif /* _ADLER32_C */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H 1
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef Z_DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef Z_DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch _length_code[];
+ extern uch _dist_code[];
+#else
+ extern const uch _length_code[];
+ extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* _DEFLATE_H */
+
+#ifndef _INFTREES_H
+#define _INFTREES_H 1
+
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1444 code structures (852 for length/literals
+ and 592 for distances, the latter actually the result of an
+ exhaustive search). The true maximum is not known, but the value
+ below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+#endif /* _INFTREES_H */
+
+#ifndef _INFLATE_H
+#define _INFLATE_H 1
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN, /* i: waiting for length/lit code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+ NAME -> COMMENT -> HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ Read deflate blocks:
+ TYPE -> STORED or TABLE or LEN or CHECK
+ STORED -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN
+ Read deflate codes:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 7K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+};
+#endif /* _INFLATE_H */
+
+#ifndef _INFTREES_C
+#define _INFTREES_C 1
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code this; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)1;
+ this.val = (unsigned short)0;
+ *(*table)++ = this; /* make a table to force an error */
+ *(*table)++ = this;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min <= MAXBITS; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked when a LENS table is being made
+ against the space in *table, ENOUGH, minus the maximum space needed by
+ the worst case distance code, MAXD. This should never happen, but the
+ sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+ This assumes that when type == LENS, bits == 9.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = ((unsigned int)1) << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ this.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ this.op = (unsigned char)0;
+ this.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ this.op = (unsigned char)(extra[work[sym]]);
+ this.val = base[work[sym]];
+ }
+ else {
+ this.op = (unsigned char)(32 + 64); /* end of block */
+ this.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = ((unsigned int)1) << (len - drop);
+ fill = ((unsigned int)1) << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = this;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = ((unsigned int)1) << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += ((unsigned int)1) << curr;
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /*
+ Fill in rest of table for incomplete codes. This loop is similar to the
+ loop above in incrementing huff for table indices. It is assumed that
+ len is equal to curr + drop, so there is no loop needed to increment
+ through high index bits. When the current sub-table is filled, the loop
+ drops back to the root table to fill in any remaining entries there.
+ */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)(len - drop);
+ this.val = (unsigned short)0;
+ while (huff != 0) {
+ /* when done with sub-table, drop back to root table */
+ if (drop != 0 && (huff & mask) != low) {
+ drop = 0;
+ len = root;
+ next = *table;
+ this.bits = (unsigned char)len;
+ }
+
+ /* put invalid code marker in table */
+ next[huff >> drop] = this;
+
+ /* backwards increment the len-bit code huff */
+ incr = ((unsigned int)1) << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
+
+#endif /* _INFTREES_C */
+
+#ifndef _INFFAST_C
+#define _INFFAST_C 1
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#undef OFF /* (ancient) sunos <locale.h> */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start; /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code this; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ write = state->write;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (((unsigned int)1) << state->lenbits) - 1;
+ dmask = (((unsigned int)1) << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ PUP(out) = (unsigned char)(this.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((((unsigned int)1) << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((((unsigned int)1) << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ from = window - OFF;
+ if (write == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (write < op) { /* wrap around window */
+ from += wsize + write - op;
+ op -= write;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (write < len) { /* some from start of window */
+ op = write;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += write - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ this = dcode[this.val + (hold & ((((unsigned int)1) << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ this = lcode[this.val + (hold & ((((unsigned int)1) << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (((unsigned int)1) << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and write == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* _INFFAST_C */
+
+#ifndef _INFLATE_C
+#define _INFLATE_C 1
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+ unsigned len));
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ strm->adler = 1; /* to support ill-conceived Java test suite */
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768;
+ state->head = Z_NULL;
+ state->wsize = 0;
+ state->whave = 0;
+ state->write = 0;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ if (windowBits < 0) {
+ state->wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48) windowBits &= 15;
+#endif
+ }
+ if (windowBits < 8 || windowBits > 15) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ return Z_STREAM_ERROR;
+ }
+ state->wbits = (unsigned)windowBits;
+ state->window = Z_NULL;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifndef _INFFIXED_H
+#define _INFFIXED_H 1
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
+#endif /* _INFFIXED_H */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, ((unsigned int)1) << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = ((unsigned int)1) << state->wbits;
+ state->write = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->write = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->write;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->write = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->write += dist;
+ if (state->write == state->wsize) state->write = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((((unsigned int)1) << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code this; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = ((unsigned int)1) << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = REVERSE(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.val < 16) {
+ NEEDBITS(this.bits);
+ DROPBITS(this.bits);
+ state->lens[state->have++] = this.val;
+ }
+ else {
+ if (this.val == 16) {
+ NEEDBITS(this.bits + 2);
+ DROPBITS(this.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (this.val == 17) {
+ NEEDBITS(this.bits + 3);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(this.bits + 7);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ break;
+ }
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.op && (this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ state->length = (unsigned)this.val;
+ if ((int)(this.op) == 0) {
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ state->mode = LIT;
+ break;
+ }
+ if (this.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ this = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)this.val;
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ if (state->offset > state->whave + out - left) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->write) {
+ copy -= state->write;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->write - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ REVERSE(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffff)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ struct inflate_state FAR *state;
+ unsigned long id;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary id */
+ if (state->mode == DICT) {
+ id = adler32(0L, Z_NULL, 0);
+ id = adler32(id, dictionary, dictLength);
+ if (id != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window */
+ if (updatewindow(strm, strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ if (dictLength > state->wsize) {
+ zmemcpy(state->window, dictionary + dictLength - state->wsize,
+ state->wsize);
+ state->whave = state->wsize;
+ }
+ else {
+ zmemcpy(state->window + state->wsize - dictLength, dictionary,
+ dictLength);
+ state->whave = dictLength;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+#ifdef GUNZIP
+ head->done = 0;
+#endif
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+ source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, ((unsigned int)1) << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = ((unsigned int)1) << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
+
+#endif /* _INFLATE_C */
+
+#ifndef _GZIO_C
+#define _GZIO_C 1
+
+typedef voidp gzFile;
+
+#ifndef Z_BUFSIZE
+# ifdef MAXSEG_64K
+# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
+# else
+# define Z_BUFSIZE 16384
+# endif
+#endif
+#ifndef Z_PRINTF_BUFSIZE
+# define Z_PRINTF_BUFSIZE 4096
+#endif
+
+#ifdef __MVS__
+# pragma map (fdopen , "\174\174FDOPEN")
+ FILE *fdopen(int, const char *);
+#endif
+
+#if 0 && !_PACKAGE_ast
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern void free OF((voidpf ptr));
+#endif
+#endif
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+ z_stream stream;
+ int z_err; /* error code for last stream operation */
+ int z_eof; /* set if end of input file */
+ FILE *file; /* .gz file */
+ Byte *inbuf; /* input buffer */
+ Byte *outbuf; /* output buffer */
+ uLong crc; /* crc32 of uncompressed data */
+ char *msg; /* error message */
+ char *path; /* path name for debugging only */
+ int transparent; /* 1 if input file is not a .gz file */
+#if _PACKAGE_ast
+ int fatal; /* fatal stream error => all other ops fail */
+ int nocrc; /* 1 to skip 'r' crc checks */
+ int noclose; /* 1 to skip destroy fclose */
+ int verified;/* 2-byte magic read and verified ('v') */
+#endif
+ char mode; /* 'w' or 'r' */
+ z_off_t start; /* start of compressed data in file (header skipped) */
+ z_off_t in; /* bytes into deflate or inflate */
+ z_off_t out; /* bytes out of deflate or inflate */
+ int back; /* one character push-back */
+ int last; /* true if push-back is last character */
+} gz_stream;
+
+
+local gzFile gz_open OF((const char *path, const char *mode, FILE* fp));
+local int get_byte OF((gz_stream *s));
+local void check_header OF((gz_stream *s));
+local int destroy OF((gz_stream *s));
+local uLong getLong OF((gz_stream *s));
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb"). The file is given either by FILE pointer
+ or path name (if fp == 0).
+ gz_open returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fp)
+ const char *path;
+ const char *mode;
+ FILE *fp;
+{
+ int err;
+ int level = Z_DEFAULT_COMPRESSION; /* compression level */
+ int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+ char *p = (char*)mode;
+ gz_stream *s;
+ char fmode[80]; /* copy of mode, without the compression level */
+ char *m = fmode;
+
+ if (!path || !mode) return Z_NULL;
+
+ s = (gz_stream *)ALLOC(sizeof(gz_stream));
+ if (!s) return Z_NULL;
+
+ s->stream.zalloc = (alloc_func)0;
+ s->stream.zfree = (free_func)0;
+ s->stream.opaque = (voidpf)0;
+ s->stream.next_in = s->inbuf = Z_NULL;
+ s->stream.next_out = s->outbuf = Z_NULL;
+ s->stream.avail_in = s->stream.avail_out = 0;
+ s->file = NULL;
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->in = 0;
+ s->out = 0;
+ s->back = EOF;
+ s->crc = crc32(0L, Z_NULL, 0);
+#if _PACKAGE_ast
+ s->fatal = 0;
+ s->nocrc = 0;
+ s->verified = 0;
+#endif
+ s->msg = NULL;
+ s->transparent = 0;
+
+ s->path = (char*)ALLOC(strlen(path)+1);
+ if (s->path == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ strcpy(s->path, path); /* do this early for debugging */
+
+ s->mode = '\0';
+ do {
+ if (*p == 'r') s->mode = 'r';
+ if (*p == 'w' || *p == 'a') s->mode = 'w';
+ if (*p >= '0' && *p <= '9') {
+ level = *p - '0';
+ } else if (*p == 'f') {
+ strategy = Z_FILTERED;
+ } else if (*p == 'h') {
+ strategy = Z_HUFFMAN_ONLY;
+ } else if (*p == 'R') {
+ strategy = Z_RLE;
+#if _PACKAGE_ast
+ } else if (*p == 'n') {
+ s->nocrc = 1;
+ } else if (*p == 'o') {
+ s->noclose = 1;
+ } else if (*p == 'v') {
+ s->verified = 1;
+#endif
+ } else {
+ *m++ = *p; /* copy the mode */
+ }
+ } while (*p++ && m != fmode + sizeof(fmode));
+ if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ err = Z_STREAM_ERROR;
+#else
+#if _PACKAGE_ast
+ s->nocrc = 0;
+#endif
+ err = deflateInit2(&(s->stream), level,
+ Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
+ /* windowBits is passed < 0 to suppress zlib header */
+
+ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+#endif
+ if (err != Z_OK || s->outbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ } else {
+ s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ err = inflateInit2(&(s->stream), -MAX_WBITS);
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+ * present after the compressed stream.
+ */
+ if (err != Z_OK || s->inbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+
+ errno = 0;
+
+ if (!(s->file = fp) && !(s->file = F_OPEN(path, fmode))) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ if (s->mode == 'w') {
+ /* Write a very simple .gz header:
+ */
+ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+ s->start = 10L;
+ /* We use 10L instead of ftell(s->file) to because ftell causes an
+ * fflush on some systems. This version of the library doesn't use
+ * start anyway in write mode, so this initialization is not
+ * necessary.
+ */
+ } else {
+#if _PACKAGE_ast
+ sfsetbuf(s->file, (void*)s->file, SF_UNBOUND);
+#endif
+ check_header(s); /* skip the .gz header */
+ s->start = ftell(s->file) - s->stream.avail_in;
+ }
+
+ return (gzFile)s;
+}
+
+/* ===========================================================================
+ Associate a gzFile with the stdio stream fp.
+*/
+gzFile ZEXPORT gzfopen (fp, mode)
+ FILE* fp;
+ const char *mode;
+{
+ FILE* sp = (FILE*)fp;
+ char name[20];
+
+ if (!sp)
+ return (gzFile)Z_NULL;
+ sprintf(name, "<fd:%d>", fileno(sp)); /* for debugging */
+
+ return gz_open (name, mode, sp);
+}
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+ gz_stream *s;
+{
+ if (s->z_eof) return EOF;
+ if (s->stream.avail_in == 0) {
+ errno = 0;
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) s->z_err = Z_ERRNO;
+ return EOF;
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->stream.avail_in--;
+ return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+ Check the gzip header of a gz_stream opened for reading. Set the stream
+ mode to transparent if the gzip magic header is not present; set s->err
+ to Z_DATA_ERROR if the magic header is present but the rest of the header
+ is incorrect.
+ IN assertion: the stream s has already been created sucessfully;
+ s->stream.avail_in is zero for the first time, but may be non-zero
+ for concatenated .gz files.
+*/
+local void check_header(s)
+ gz_stream *s;
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ int c;
+
+#if _PACKAGE_ast
+ if (!s->verified)
+ for (len = 0; len < 2; len++) {
+ c = get_byte(s);
+ if (c != gz_magic[len]) {
+ if (len != 0) s->stream.avail_in++, s->stream.next_in--;
+ if (c != EOF) {
+ s->stream.avail_in++, s->stream.next_in--;
+ s->transparent = 1;
+ }
+ s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
+ return;
+ }
+ }
+#else
+ /* Assure two bytes in the buffer so we can peek ahead -- handle case
+ where first byte of header is at the end of the buffer after the last
+ gzip segment */
+ len = s->stream.avail_in;
+ if (len < 2) {
+ if (len) s->inbuf[0] = s->stream.next_in[0];
+ errno = 0;
+ len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+ if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
+ s->stream.avail_in += len;
+ s->stream.next_in = s->inbuf;
+ if (s->stream.avail_in < 2) {
+ s->transparent = s->stream.avail_in;
+ return;
+ }
+ }
+
+ /* Peek ahead to check the gzip magic header */
+ if (s->stream.next_in[0] != gz_magic[0] ||
+ s->stream.next_in[1] != gz_magic[1]) {
+ s->transparent = 1;
+ return;
+ }
+ s->stream.avail_in -= 2;
+ s->stream.next_in += 2;
+#endif
+
+ /* Check the rest of the gzip header */
+ method = get_byte(s);
+ flags = get_byte(s);
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ s->z_err = Z_DATA_ERROR;
+ return;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(s);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ len = (uInt)get_byte(s);
+ len += ((uInt)get_byte(s))<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte(s) != EOF) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(s);
+ }
+ s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+ Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+ gz_stream *s;
+{
+ int err = Z_OK;
+
+ if (!s) return Z_STREAM_ERROR;
+
+ TRYFREE(s->msg);
+
+ if (s->stream.state != NULL) {
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ err = Z_STREAM_ERROR;
+#else
+ err = deflateEnd(&(s->stream));
+#endif
+ } else if (s->mode == 'r') {
+ err = inflateEnd(&(s->stream));
+ }
+ }
+#if _PACKAGE_ast
+ if (s->file != NULL && (s->noclose ? (s->mode == 'r' ? 0 : fflush(s->file)) : fclose(s->file))) {
+#else
+ if (s->file != NULL && fclose(s->file)) {
+#endif
+#ifdef ESPIPE
+ if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+#endif
+ err = Z_ERRNO;
+ }
+ if (s->z_err < 0) err = s->z_err;
+
+ TRYFREE(s->inbuf);
+ TRYFREE(s->outbuf);
+ TRYFREE(s->path);
+ TRYFREE(s);
+ return err;
+}
+
+/* ===========================================================================
+ Reads the given number of uncompressed bytes from the compressed file.
+ gzread returns the number of bytes actually read (0 for end of file).
+*/
+int ZEXPORT gzread (file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+ Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+ if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+ if (s->z_err == Z_STREAM_END) return 0; /* EOF */
+
+ next_out = (Byte*)buf;
+ s->stream.next_out = (Bytef*)buf;
+ s->stream.avail_out = len;
+
+ if (s->stream.avail_out && s->back != EOF) {
+ *next_out++ = s->back;
+ s->stream.next_out++;
+ s->stream.avail_out--;
+ s->back = EOF;
+ s->out++;
+ start++;
+ if (s->last) {
+ s->z_err = Z_STREAM_END;
+ return 1;
+ }
+ }
+
+ while (s->stream.avail_out != 0) {
+
+ if (s->transparent) {
+ /* Copy first the lookahead bytes: */
+ uInt n = s->stream.avail_in;
+ if (n > s->stream.avail_out) n = s->stream.avail_out;
+ if (n > 0) {
+ zmemcpy(s->stream.next_out, s->stream.next_in, n);
+ next_out += n;
+ s->stream.next_out = next_out;
+ s->stream.next_in += n;
+ s->stream.avail_out -= n;
+ s->stream.avail_in -= n;
+ }
+ if (s->stream.avail_out > 0) {
+ s->stream.avail_out -=
+ (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
+ }
+ len -= s->stream.avail_out;
+ s->in += len;
+ s->out += len;
+ if (len == 0) s->z_eof = 1;
+ return (int)len;
+ }
+ if (s->stream.avail_in == 0 && !s->z_eof) {
+
+ errno = 0;
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->in += s->stream.avail_in;
+ s->out += s->stream.avail_out;
+ s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+ s->in -= s->stream.avail_in;
+ s->out -= s->stream.avail_out;
+
+ if (s->z_err == Z_STREAM_END) {
+ /* Check CRC and original size */
+#if _PACKAGE_ast
+ if (!s->nocrc)
+#endif
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+ start = s->stream.next_out;
+
+#if _PACKAGE_ast
+ if (getLong(s) != s->crc && !s->nocrc) {
+#else
+ if (getLong(s) != s->crc) {
+#endif
+ s->z_err = Z_DATA_ERROR;
+ } else {
+ (void)getLong(s);
+ /* The uncompressed length returned by above getlong() may be
+ * different from s->out in case of concatenated .gz files.
+ * Check for such files:
+ */
+ check_header(s);
+ if (s->z_err == Z_OK) {
+ inflateReset(&(s->stream));
+#if _PACKAGE_ast
+ if (!s->nocrc)
+#endif
+ s->crc = crc32(0L, Z_NULL, 0);
+#if _PACKAGE_ast
+ else
+ s->z_err = Z_STREAM_END;
+#endif
+ }
+ }
+ }
+ if (s->z_err != Z_OK || s->z_eof) break;
+ }
+#if _PACKAGE_ast
+ if (!s->nocrc)
+#endif
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+ if (len == s->stream.avail_out &&
+ (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
+ return -1;
+ return (int)(len - s->stream.avail_out);
+}
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets z_err in case
+ of error.
+*/
+local uLong getLong (s)
+ gz_stream *s;
+{
+ uLong x = (uLong)get_byte(s);
+ int c;
+
+ x += ((uLong)get_byte(s))<<8;
+ x += ((uLong)get_byte(s))<<16;
+ c = get_byte(s);
+ if (c == EOF) s->z_err = Z_DATA_ERROR;
+ x += ((uLong)c)<<24;
+ return x;
+}
+
+#endif /* _GZIO_C */
+
+#endif /* _GUNZIP_H */
+
+#undef local
+
+#ifndef _RATZ_C
+#define _RATZ_C 1
+
+#include <sys/stat.h>
+
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0200
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 0100
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0040
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0020
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0004
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0002
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001
+#endif
+
+/*
+ * Standard Archive Format
+ * USTAR - Uniform Standard Tape ARchive
+ */
+
+#define TBLOCK 512
+#define NAMSIZ 100
+#define PFXSIZ 155
+
+#define TMODLEN 8
+#define TUIDLEN 8
+#define TGIDLEN 8
+#define TSIZLEN 12
+#define TMTMLEN 12
+#define TCKSLEN 8
+
+#define TMAGIC "ustar" /* ustar and a null */
+#define TMAGLEN 6
+#define TVERSION "00" /* 00 and no null */
+#define TVERSLEN 2
+#define TUNMLEN 32
+#define TGNMLEN 32
+#define TDEVLEN 8
+#define TPADLEN 12
+
+/*
+ * values used in typeflag field
+ */
+
+#define REGTYPE '0' /* regular file */
+#define AREGTYPE 0 /* alternate REGTYPE */
+#define LNKTYPE '1' /* hard link */
+#define SYMTYPE '2' /* soft link */
+#define CHRTYPE '3' /* character special */
+#define BLKTYPE '4' /* block special */
+#define DIRTYPE '5' /* directory */
+#define FIFOTYPE '6' /* FIFO special */
+#define CONTTYPE '7' /* reserved */
+#define SOKTYPE '8' /* socket -- reserved */
+#define VERTYPE 'V' /* version -- reserved */
+#define EXTTYPE 'x' /* extended header -- reserved */
+
+/*
+ * bits used in mode field
+ */
+
+#define TSUID 04000 /* set uid on exec */
+#define TSGID 02000 /* set gid on exec */
+#define TSVTX 01000 /* sticky bit -- reserved */
+
+/*
+ * file permissions
+ */
+
+#define TUREAD 00400 /* read by owner */
+#define TUWRITE 00200 /* write by owner */
+#define TUEXEC 00100 /* execute by owner */
+#define TGREAD 00040 /* read by group */
+#define TGWRITE 00020 /* execute by group */
+#define TGEXEC 00010 /* write by group */
+#define TOREAD 00004 /* read by other */
+#define TOWRITE 00002 /* write by other */
+#define TOEXEC 00001 /* execute by other */
+
+#define TAR_SUMASK ((1L<<(TCKSLEN-1)*3)-1)
+
+typedef struct
+{
+ char name[NAMSIZ];
+ char mode[TMODLEN];
+ char uid[TUIDLEN];
+ char gid[TGIDLEN];
+ char size[TSIZLEN];
+ char mtime[TMTMLEN];
+ char chksum[TCKSLEN];
+ char typeflag;
+ char linkname[NAMSIZ];
+ char magic[TMAGLEN];
+ char version[TVERSLEN];
+ char uname[TUNMLEN];
+ char gname[TGNMLEN];
+ char devmajor[TDEVLEN];
+ char devminor[TDEVLEN];
+ char prefix[PFXSIZ];
+ char pad[TPADLEN];
+} Header_t;
+
+static struct
+{
+ char* id;
+ unsigned long blocks;
+ unsigned long files;
+} state;
+
+#if !_PACKAGE_ast
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: %s [-clmntvV] < input.tgz\n", state.id);
+ exit(2);
+}
+
+#endif
+
+/*
+ * the X/Open dd EBCDIC table
+ */
+
+static const unsigned char a2e[] =
+{
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0045,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0132,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0255,0340,0275,0232,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0117,0320,0137,0007,
+ 0040,0041,0042,0043,0044,0025,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0341,
+ 0101,0102,0103,0104,0105,0106,0107,0110,
+ 0111,0121,0122,0123,0124,0125,0126,0127,
+ 0130,0131,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0160,0161,0162,0163,0164,0165,
+ 0166,0167,0170,0200,0212,0213,0214,0215,
+ 0216,0217,0220,0152,0233,0234,0235,0236,
+ 0237,0240,0252,0253,0254,0112,0256,0257,
+ 0260,0261,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0272,0273,0274,0241,0276,0277,
+ 0312,0313,0314,0315,0316,0317,0332,0333,
+ 0334,0335,0336,0337,0352,0353,0354,0355,
+ 0356,0357,0372,0373,0374,0375,0376,0377,
+};
+
+/*
+ * the X/Open dd IBM table
+ */
+
+static const unsigned char a2i[] =
+{
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0045,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0132,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0255,0340,0275,0137,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0117,0320,0241,0007,
+ 0040,0041,0042,0043,0044,0025,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0341,
+ 0101,0102,0103,0104,0105,0106,0107,0110,
+ 0111,0121,0122,0123,0124,0125,0126,0127,
+ 0130,0131,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0160,0161,0162,0163,0164,0165,
+ 0166,0167,0170,0200,0212,0213,0214,0215,
+ 0216,0217,0220,0232,0233,0234,0235,0236,
+ 0237,0240,0252,0253,0254,0255,0256,0257,
+ 0260,0261,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0272,0273,0274,0275,0276,0277,
+ 0312,0313,0314,0315,0316,0317,0332,0333,
+ 0334,0335,0336,0337,0352,0353,0354,0355,
+ 0356,0357,0372,0373,0374,0375,0376,0377,
+};
+
+/*
+ * the mvs OpenEdition EBCDIC table
+ */
+
+static const unsigned char a2o[] =
+{
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0025,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0132,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0255,0340,0275,0137,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0117,0320,0241,0007,
+ 0040,0041,0042,0043,0044,0045,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0377,
+ 0101,0252,0112,0261,0237,0262,0152,0265,
+ 0273,0264,0232,0212,0260,0312,0257,0274,
+ 0220,0217,0352,0372,0276,0240,0266,0263,
+ 0235,0332,0233,0213,0267,0270,0271,0253,
+ 0144,0145,0142,0146,0143,0147,0236,0150,
+ 0164,0161,0162,0163,0170,0165,0166,0167,
+ 0254,0151,0355,0356,0353,0357,0354,0277,
+ 0200,0375,0376,0373,0374,0272,0256,0131,
+ 0104,0105,0102,0106,0103,0107,0234,0110,
+ 0124,0121,0122,0123,0130,0125,0126,0127,
+ 0214,0111,0315,0316,0313,0317,0314,0341,
+ 0160,0335,0336,0333,0334,0215,0216,0337,
+};
+
+/*
+ * ascii text vs. control
+ */
+
+static const unsigned char ascii_text[] =
+{
+ 0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+static int
+block(fp, gz, buf)
+FILE* fp;
+gzFile gz;
+char* buf;
+{
+ int r;
+
+ if (gz)
+ r = gzread(gz, buf, sizeof(Header_t)) == sizeof(Header_t);
+ else
+ r = fread(buf, sizeof(Header_t), 1, fp) == 1;
+ if (r)
+ state.blocks++;
+ return r;
+}
+
+static int
+skip(fp, gz, buf, n)
+FILE* fp;
+gzFile gz;
+char* buf;
+unsigned long n;
+{
+ while (n > 0)
+ {
+ if (!block(fp, gz, buf))
+ {
+ fprintf(stderr, "%s: unexpected EOF\n", state.id);
+ return 1;
+ }
+ if (n <= sizeof(Header_t))
+ break;
+ n -= sizeof(Header_t);
+ }
+ return 0;
+}
+
+static unsigned long
+number(s)
+register char* s;
+{
+ unsigned long n = 0;
+
+ while (*s == ' ')
+ s++;
+ while (*s >= '0' && *s <= '7')
+ n = (n << 3) + (*s++ - '0');
+ return n;
+}
+
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
+#define EXIT(n) return(sear_exec((char*)0,(char**)0,(char*)0),(n))
+
+static int sear_stdin;
+static char* sear_tmp;
+static char sear_buf[PATH_MAX];
+
+static int
+sear_seek(off_t offset, int tmp)
+{
+ int n;
+ char cmd[PATH_MAX];
+
+ GetModuleFileName(NULL, cmd, sizeof(cmd));
+ sear_stdin = dup(0);
+ close(0);
+ if (open(cmd, O_BINARY|O_RDONLY) || lseek(0, offset, 0) != offset)
+ {
+ fprintf(stderr, "%s: %s: cannot seek to data offset\n", state.id, cmd);
+ return -1;
+ }
+ if (tmp)
+ {
+ if ((n = GetTempPath(sizeof(cmd), cmd)) <= 0 || n > sizeof(cmd))
+ {
+ fprintf(stderr, "%s: cannot determine temporary directory path\n", state.id);
+ return -1;
+ }
+ if (!GetTempFileName(cmd, "SEA", 0, sear_buf))
+ {
+ fprintf(stderr, "%s: cannot determine temporary file path\n", state.id);
+ return -1;
+ }
+ sear_tmp = sear_buf;
+ if (!DeleteFile(sear_tmp))
+ {
+ fprintf(stderr, "%s: %s: cannot initialize temporary directory\n", state.id, sear_tmp);
+ return -1;
+ }
+ if (!CreateDirectory(sear_tmp, NULL))
+ {
+ fprintf(stderr, "%s: %s: cannot create temporary directory\n", state.id, sear_tmp);
+ return -1;
+ }
+ if (!SetCurrentDirectory(sear_tmp))
+ {
+ fprintf(stderr, "%s: %s: cannot cd to temporary directory\n", state.id, sear_tmp);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * remove dir and its subdirs
+ */
+
+static void
+sear_rm_r(char* dir)
+{
+ WIN32_FIND_DATA info;
+ HANDLE hp;
+
+ if (!SetCurrentDirectory(dir))
+ return;
+ if ((hp = FindFirstFile("*.*", &info)) != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ SetFileAttributes(info.cFileName, info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
+ DeleteFile(info.cFileName);
+ }
+ else if (info.cFileName[0] != '.' || info.cFileName[1] != 0 && (info.cFileName[1] != '.' || info.cFileName[2] != 0))
+ sear_rm_r(info.cFileName);
+ } while(FindNextFile(hp, &info));
+ FindClose(hp);
+ }
+ if (SetCurrentDirectory(".."))
+ RemoveDirectory(dir);
+}
+
+/*
+ * system(3) without PATH search that should work on all windows variants
+ */
+
+static int
+sear_system(const char* command, int nowindow)
+{
+ PROCESS_INFORMATION pinfo;
+ STARTUPINFO sinfo;
+ char* cp;
+ char path[PATH_MAX];
+ int n = *command == '"';
+ DWORD flags = NORMAL_PRIORITY_CLASS;
+
+ strncpy(path, &command[n], PATH_MAX - 4);
+ n = n ? '"' : ' ';
+ for (cp = path; *cp; *cp++)
+ if (*cp == n)
+ break;
+ *cp = 0;
+ if (GetFileAttributes(path) == 0xffffffff && GetLastError() == ERROR_FILE_NOT_FOUND)
+ strcpy(cp, ".exe");
+ ZeroMemory(&sinfo, sizeof(sinfo));
+ if (nowindow)
+ flags |= CREATE_NO_WINDOW;
+ if (!CreateProcess(path, (char*)command, 0, 0, TRUE, flags, NULL, NULL, &sinfo, &pinfo))
+ n = GetLastError() == ERROR_FILE_NOT_FOUND ? 127 : 126;
+ else
+ {
+ CloseHandle(pinfo.hThread);
+ WaitForSingleObject(pinfo.hProcess, INFINITE);
+ if (!GetExitCodeProcess(pinfo.hProcess, &n))
+ n = 1;
+ CloseHandle(pinfo.hProcess);
+ Sleep(2 * 1000);
+ }
+ return n;
+}
+
+/*
+ * copy t to f but no farther than e
+ * next t returned
+ */
+
+static char*
+copy(char* t, const char* f, char* e)
+{
+ while (t < e && *f)
+ *t++ = *f++;
+ return t;
+}
+
+/*
+ * execute cmd, chdir .., and remove sear_tmp
+ */
+
+static int
+sear_exec(const char* cmd, char* const* arg, char* operands)
+{
+ const char* a;
+ char* b;
+ char* e;
+ int r;
+ int sh;
+ int nowindow;
+ char buf[1024];
+
+ fflush(stdout);
+ fflush(stderr);
+ if (sear_tmp)
+ {
+ close(0);
+ dup(sear_stdin);
+ close(sear_stdin);
+ nowindow = 0;
+ if (cmd)
+ {
+ if (arg)
+ for (r = 0; arg[r]; r++)
+ if (!strcmp(arg[r], "remote"))
+ {
+ nowindow = 1;
+ break;
+ }
+ sh = 0;
+ for (a = cmd; *a && *a != ' '; a++)
+ if (a[0] == '.' && a[1] == 's' && a[2] == 'h' && (!a[3] || a[3] == ' '))
+ {
+ sh = 1;
+ break;
+ }
+ b = buf;
+ e = buf + sizeof(buf) - 1;
+ if (sh || arg)
+ {
+ if (sh)
+ {
+ b = copy(b, "ksh.exe ", e);
+ if (*cmd && *cmd != '/')
+ b = copy(b, "./", e);
+ }
+ b = copy(b, cmd, e);
+ while (a = *arg++)
+ {
+ if ((e - b) < 3)
+ break;
+ b = copy(b, " \"", e);
+ b = copy(b, a, e);
+ b = copy(b, "\"", e);
+ }
+ }
+ if (operands)
+ {
+ if (b == buf)
+ b = copy(b, cmd, e);
+ b = copy(b, " -- ", e);
+ b = copy(b, operands, e);
+ }
+ if (b > buf)
+ {
+ *b = 0;
+ cmd = (const char*)buf;
+ }
+ }
+ r = cmd ? sear_system(cmd, nowindow) : 1;
+ sear_rm_r(sear_tmp);
+ }
+ else
+ r = cmd ? 0 : 1;
+ return r;
+}
+
+#else
+
+#define EXIT(n) return(n)
+
+#endif
+
+int
+main(argc, argv)
+int argc;
+char** argv;
+{
+ register int c;
+ register char* s;
+ register char* t;
+ register char* e;
+ unsigned long n;
+ unsigned long m;
+ const unsigned char* a2x;
+ int clear;
+ int list;
+ int local;
+ int meter;
+ int unzip;
+ int verbose;
+ unsigned int mode;
+ unsigned long total;
+ off_t pos;
+ gzFile gz;
+ FILE* fp;
+ Header_t header;
+ unsigned char num[4];
+ char path[sizeof(header.prefix) + sizeof(header.name) + 4];
+ char buf[sizeof(header)];
+#if defined(_SEAR_OPTS)
+ char* opts[4];
+#endif
+
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+ int install = 1;
+#endif
+
+ setmode(0, O_BINARY);
+ setmode(1, O_BINARY);
+ clear = 0;
+ list = 0;
+ local = 0;
+ meter = 0;
+ unzip = 0;
+ verbose = 0;
+ if (s = *argv)
+ {
+ t = s;
+ while (*s)
+ if (*s++ == '/')
+ t = s;
+ if (!strcmp(t, "gunzip"))
+ unzip = 1;
+ state.id = t;
+ }
+ else
+ state.id = "ratz";
+ switch ('~')
+ {
+ case 0241:
+ switch ('\n')
+ {
+ case 0025:
+ a2x = a2o;
+ break;
+ default:
+ a2x = a2e;
+ break;
+ }
+ break;
+ case 0137:
+ a2x = a2i;
+ break;
+ default:
+ a2x = 0;
+ break;
+ }
+#if defined(_SEAR_OPTS)
+ opts[0] = argv[0];
+ opts[1] = _SEAR_OPTS;
+ opts[2] = argv[1];
+ opts[3] = 0;
+ argv = opts;
+#endif
+#if _PACKAGE_ast
+ error_info.id = state.id;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'c':
+ unzip = 1;
+ continue;
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+ case 'i':
+ install = 0;
+ continue;
+#endif
+ case 'l':
+ local = 1;
+ continue;
+ case 'm':
+ meter = 1;
+ continue;
+ case 'n':
+ a2x = 0;
+ continue;
+ case 't':
+ list = 1;
+ continue;
+ case 'v':
+ verbose = 1;
+ continue;
+ case 'V':
+ sfprintf(sfstdout, "%s\n", id + 10);
+ return 0;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ argv += opt_info.index;
+#else
+ while ((s = *++argv) && *s == '-' && *(s + 1))
+ {
+ if (*(s + 1) == '-')
+ {
+ if (!*(s + 2))
+ {
+ argv++;
+ break;
+ }
+ usage();
+ break;
+ }
+ for (;;)
+ {
+ switch (c = *++s)
+ {
+ case 0:
+ break;
+ case 'c':
+ unzip = 1;
+ continue;
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+ case 'i':
+ install = 0;
+ continue;
+#endif
+ case 'l':
+ local = 1;
+ continue;
+ case 'm':
+ meter = 1;
+ continue;
+ case 'n':
+ a2x = 0;
+ continue;
+ case 't':
+ list = 1;
+ continue;
+ case 'v':
+ verbose = 1;
+ continue;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ return 0;
+ default:
+ fprintf(stderr, "%s: -%c: unknown option\n", state.id, c);
+ /*FALLTHROUGH*/
+ case '?':
+ usage();
+ break;
+ }
+ break;
+ }
+ }
+#endif
+
+#if defined(_SEAR_SEEK)
+ if (sear_seek((off_t)_SEAR_SEEK, install && !list))
+ {
+ Sleep(2 * 1000);
+ return 1;
+ }
+#endif
+
+ /*
+ * commit on the first gzip magic char
+ */
+
+ if ((c = getchar()) == EOF)
+ EXIT(0);
+ ungetc(c, stdin);
+ if (c != gz_magic[0])
+ gz = 0;
+ else if (!(gz = gzfopen(stdin, FOPEN_READ)))
+ {
+ fprintf(stderr, "%s: gunzip open error\n", state.id);
+ EXIT(1);
+ }
+ if (unzip)
+ {
+ if (!gz)
+ {
+ fprintf(stderr, "%s: not a gzip file\n", state.id);
+ EXIT(1);
+ }
+ while ((c = gzread(gz, buf, sizeof(buf))) > 0)
+ if (fwrite(buf, c, 1, stdout) != 1)
+ {
+ fprintf(stderr, "%s: write error\n", state.id);
+ EXIT(1);
+ }
+ if (c < 0)
+ {
+ fprintf(stderr, "%s: read error\n", state.id);
+ EXIT(1);
+ }
+ if (fflush(stdout))
+ {
+ fprintf(stderr, "%s: flush error\n", state.id);
+ EXIT(1);
+ }
+ EXIT(0);
+ }
+ if (meter)
+ {
+ if ((pos = lseek(0, (off_t)0, SEEK_CUR)) < 0)
+ meter = 0;
+ else
+ {
+ if (lseek(0, (off_t)(-4), SEEK_END) < 0 || read(0, num, 4) != 4)
+ meter = 0;
+ else if (!(total = ((num[0]|(num[1]<<8)|(num[2]<<16)|(num[3]<<24)) + sizeof(Header_t) - 1) / sizeof(Header_t)))
+ total = 1;
+ lseek(0, pos, SEEK_SET);
+ }
+ }
+
+ /*
+ * loop on all the header blocks
+ */
+
+ while (block(stdin, gz, (char*)&header))
+ {
+ /*
+ * last 2 blocks are NUL
+ */
+
+ if (!*header.name)
+ break;
+
+ /*
+ * verify the checksum
+ */
+
+ s = header.chksum;
+ e = header.chksum + sizeof(header.chksum);
+ if (a2x)
+ {
+ for (; s < e; s++)
+ *s = a2x[*(unsigned char*)s];
+ s = header.chksum;
+ }
+ n = number(s) & TAR_SUMASK;
+ while (s < e)
+ *s++ = 040;
+ m = 0;
+ s = (char*)&header;
+ e = (char*)&header + sizeof(header);
+ while (s < e)
+ m += *(unsigned char*)s++;
+ m &= TAR_SUMASK;
+ if (m != n)
+ {
+ if (state.files)
+ fprintf(stderr, "%s: archive corrupted\n", state.id);
+ else
+ fprintf(stderr, "%s: not a tar archive\n", state.id);
+ fprintf(stderr, "check sum %lu != %lu\n", m, n);
+ EXIT(1);
+ }
+
+ /*
+ * convert to the native charset
+ */
+
+ if (a2x)
+ for (e = (s = (char*)&header) + sizeof(header); s < e; s++)
+ *s = a2x[*(unsigned char*)s];
+
+ /*
+ * get the pathname, type and size
+ */
+
+ state.files++;
+ t = path;
+ if (!strncmp(header.magic, TMAGIC, sizeof(header.magic)) && *header.prefix)
+ {
+ s = header.prefix;
+ e = header.prefix + sizeof(header.prefix);
+ while (s < e && (c = *s++))
+ *t++ = c;
+ *t++ = '/';
+ }
+ s = header.name;
+ e = header.name + sizeof(header.name);
+ while (s < e && (c = *s++))
+ *t++ = c;
+ *t = 0;
+
+ /*
+ * verify the dir prefix
+ */
+
+ t = 0;
+ s = path;
+ while (*s)
+ if (*s++ == '/')
+ t = s;
+ if (t)
+ {
+ *--t = 0;
+ if (!list && access(path, 0))
+ {
+ s = path;
+ do
+ {
+ if (!(c = *s) || c == '/')
+ {
+ *s = 0;
+ if (access(path, 0) && mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH))
+ {
+ fprintf(stderr, "%s: %s: cannot create directory\n", state.id, path);
+ EXIT(1);
+ }
+ *s = c;
+ }
+ } while (*s++);
+ }
+ if (*(t + 1))
+ *t = '/';
+ else
+ header.typeflag = DIRTYPE;
+ }
+
+ /*
+ * check for non-local paths
+ */
+
+ if (local && (path[0] == '/' || path[0] == '.' && path[1] == '.' && (!path[2] || path[2] == '/')))
+ {
+ fprintf(stderr, "%s: %s: non-local path rejected", state.id, path);
+ if ((header.typeflag == REGTYPE || header.typeflag == AREGTYPE) && (n = number(header.size)))
+ while (n > 0)
+ {
+ if (!block(stdin, gz, buf))
+ {
+ fprintf(stderr, "%s: unexpected EOF\n", state.id);
+ EXIT(1);
+ }
+ if (n <= sizeof(header))
+ break;
+ n -= sizeof(header);
+ }
+ continue;
+ }
+
+ /*
+ * create and grab the data
+ */
+
+ n = number(header.mode);
+ mode = 0;
+ if (n & TUREAD)
+ mode |= S_IRUSR;
+ if (n & TUWRITE)
+ mode |= S_IWUSR;
+ if (n & TUEXEC)
+ mode |= S_IXUSR;
+ if (n & TGREAD)
+ mode |= S_IRGRP;
+ if (n & TGWRITE)
+ mode |= S_IWGRP;
+ if (n & TGEXEC)
+ mode |= S_IXGRP;
+ if (n & TOREAD)
+ mode |= S_IROTH;
+ if (n & TOWRITE)
+ mode |= S_IWOTH;
+ if (n & TOEXEC)
+ mode |= S_IXOTH;
+ if (list || meter)
+ {
+ if (meter)
+ {
+ int i;
+ int j;
+ int k;
+ int n;
+ int p;
+ char bar[METER_parts + 1];
+
+ for (s = path; *s; s++)
+ if (s[0] == ' ' && s[1] == '-' && s[2] == '-' && s[3] == ' ')
+ break;
+ if (*s)
+ {
+ if (clear)
+ {
+ fprintf(stderr, "%*s", clear, "\r");
+ clear = 0;
+ }
+ fprintf(stderr, "\n%s\n\n", path);
+ }
+ else
+ {
+ n = (int)strlen(s = path);
+ p = (state.blocks * 100) / total;
+ if (n > (METER_width - METER_parts - 1))
+ {
+ s += n - (METER_width - METER_parts - 1);
+ n = METER_width - METER_parts - 1;
+ }
+ j = n + METER_parts + 2;
+ if (!clear)
+ clear = j + 5;
+ if ((k = clear - j - 5) < 0)
+ k = 0;
+ if ((i = (p / (100 / METER_parts))) >= sizeof(bar))
+ i = sizeof(bar) - 1;
+ n = 0;
+ while (n < i)
+ bar[n++] = '*';
+ while (n < sizeof(bar) - 1)
+ bar[n++] = ' ';
+ bar[n] = 0;
+ clear = fprintf(stderr, "%02d%% |%s| %s%*s", p, bar, s, k, "\r");
+ }
+ }
+ else
+ {
+ if (verbose)
+ {
+ switch (header.typeflag)
+ {
+ case REGTYPE:
+ case AREGTYPE:
+ c = '-';
+ break;
+ case DIRTYPE:
+ c = 'd';
+ break;
+ case LNKTYPE:
+ c = 'h';
+ break;
+ case SYMTYPE:
+ c = 'l';
+ break;
+ default:
+ c = '?';
+ break;
+ }
+ printf("%c", c);
+ m = 0400;
+ while (m)
+ {
+ printf("%c", (n & m) ? 'r' : '-');
+ m >>= 1;
+ printf("%c", (n & m) ? 'w' : '-');
+ m >>= 1;
+ printf("%c", (n & m) ? 'x' : '-');
+ m >>= 1;
+ }
+ printf(" %10lu ", number(header.size));
+ }
+ switch (header.typeflag)
+ {
+ case LNKTYPE:
+ printf("%s == %s\n", path, header.linkname);
+ break;
+ case SYMTYPE:
+ printf("%s => %s\n", path, header.linkname);
+ break;
+ default:
+ printf("%s\n", path);
+ break;
+ }
+ }
+ if (list)
+ {
+ if (skip(stdin, gz, buf, number(header.size)))
+ EXIT(1);
+ continue;
+ }
+ }
+ else if (verbose)
+ printf("%s\n", path);
+ switch (header.typeflag)
+ {
+ case REGTYPE:
+ case AREGTYPE:
+ while (!(fp = fopen(path, FOPEN_WRITE)))
+ if (unlink(path))
+ {
+ fprintf(stderr, "%s: warning: %s: cannot create file\n", state.id, path);
+ break;
+ }
+ n = number(header.size);
+ c = a2x ? 0 : -1;
+ while (n > 0)
+ {
+ if (!block(stdin, gz, buf))
+ {
+ fprintf(stderr, "%s: unexpected EOF\n", state.id);
+ EXIT(1);
+ }
+ switch (c)
+ {
+ case 0:
+ if ((m = n) < 4)
+ {
+ for (e = (s = buf) + m; s < e; s++)
+ if (a2x[*(unsigned char*)s] != '\n')
+ break;
+ }
+ else
+ {
+ if (m > 256)
+ m = 256;
+ for (e = (s = buf) + m; s < e; s++)
+ if (!ascii_text[*(unsigned char*)s])
+ break;
+ }
+ if (s < e)
+ {
+ c = -1;
+ break;
+ }
+ c = 1;
+ /*FALLTHROUGH*/
+ case 1:
+ for (e = (s = buf) + sizeof(header); s < e; s++)
+ *s = a2x[*(unsigned char*)s];
+ break;
+ }
+ if (fp && fwrite(buf, n > sizeof(header) ? sizeof(header) : n, 1, fp) != 1)
+ {
+ fprintf(stderr, "%s: %s: write error\n", state.id, path);
+ EXIT(1);
+ }
+ if (n <= sizeof(header))
+ break;
+ n -= sizeof(header);
+ }
+ if (fp && fclose(fp))
+ {
+ fprintf(stderr, "%s: %s: write error\n", state.id, path);
+ EXIT(1);
+ }
+ break;
+ case DIRTYPE:
+ if (access(path, 0) && mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH))
+ {
+ fprintf(stderr, "%s: %s: cannot create directory\n", state.id, path);
+ EXIT(1);
+ }
+ break;
+ case SYMTYPE:
+#if defined(S_IFLNK) || defined(S_ISLNK)
+ while (symlink(header.linkname, path))
+ if (unlink(path))
+ {
+ fprintf(stderr, "%s: %s: cannot symlink to %s\n", state.id, path, header.linkname);
+ EXIT(1);
+ }
+ continue;
+#endif
+#if !_WIN32 || _WINIX
+ case LNKTYPE:
+ while (link(header.linkname, path))
+ if (unlink(path))
+ {
+ fprintf(stderr, "%s: %s: cannot link to %s\n", state.id, path, header.linkname);
+ EXIT(1);
+ }
+ continue;
+#endif
+ default:
+ fprintf(stderr, "%s: %s: file type %c ignored\n", state.id, path, header.typeflag);
+ if (skip(stdin, gz, buf, number(header.size)))
+ EXIT(1);
+ continue;
+ }
+ if (chmod(path, mode))
+ fprintf(stderr, "%s: %s: cannot change mode to %03o\n", state.id, path, mode);
+ }
+ if (clear)
+ fprintf(stderr, "%*s", clear, "\r");
+ if (!state.files)
+ fprintf(stderr, "%s: warning: empty archive\n", state.id);
+ else if (verbose)
+ fprintf(stderr, "%lu file%s, %lu block%s\n", state.files, state.files == 1 ? "" : "s", state.blocks, state.blocks == 1 ? "" : "s");
+#if defined(_SEAR_EXEC)
+#if !defined(_SEAR_ARGS)
+#define _SEAR_ARGS 0
+#endif
+ if (install && sear_exec(_SEAR_EXEC, argv, _SEAR_ARGS))
+ {
+ Sleep(2 * 1000);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+#endif /* _RATZ_C */
diff --git a/src/cmd/INIT/regress.sh b/src/cmd/INIT/regress.sh
new file mode 100644
index 0000000..a4417c4
--- /dev/null
+++ b/src/cmd/INIT/regress.sh
@@ -0,0 +1,1463 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: regress - run regression tests in command.tst
+
+command=regress
+case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in
+0123) USAGE=$'
+[-?
+@(#)$Id: regress (AT&T Research) 2012-02-02 $
+]
+'$USAGE_LICENSE$'
+[+NAME?regress - run regression tests]
+[+DESCRIPTION?\bregress\b runs the tests in \aunit\a, or
+ \aunit\a\b.tst\b if \aunit\a does not exist. If \acommand\a is omitted
+ then it is assumed to be the base name of \aunit\a. All testing is done
+ in the temporary directory \aunit\a\b.tmp\b.]
+[+?Default test output lists the \anumber\a and \adescription\a for
+ each active \bTEST\b group and the \anumber\a:\aline\a for each
+ individual \bEXEC\b test. Each test that fails results in a diagnostic
+ that contains the word \bFAILED\b; no other diagnostics contain this
+ word.]
+[b:ignore-space?Ignore space differences when comparing expected
+ output.]
+[i:pipe-input?Repeat each test with the standard input redirected through a
+ pipe.]
+[k:keep?Enable \bcore\b dumps, exit after the first test that fails,
+ and do not remove the temporary directory \aunit\a\b.tmp\b.]
+[l:local-fs?Force \aunit\a\b.tmp\b to be in a local filesystem.]
+[o:pipe-output?Repeat each test with the standard output redirected through
+ a pipe.]
+[p:pipe-io?Repeat each test with the standard input and standard output
+ redirected through pipes.]
+[q:quiet?Output information on \bFAILED\b tests only.]
+[r!:regular?Run each test with the standard input and standard output
+ redirected through regular files.]
+[t:test?Run only tests matching \apattern\a. Tests are numbered and
+ consist of at least two digits (0 filled if necessary.) Tests matching
+ \b+(0)\b are always run.]:[pattern]
+[x:trace?Enable debug tracing.]
+[v:verbose?List differences between actual (<) and expected (>) output,
+ errors and exit codes. Also disable long output line truncation.]
+
+unit [ command [ arg ... ] ]
+
+[+INPUT FILES?The regression test file \aunit\a\b.tst\b is a \bksh\b(1)
+ script that is executed in an environment with the following functions
+ defined:]
+ {
+ [+BODY \b{ ... }?Defines the test body; used for complex tests.]
+ [+CD \b\adirectory\a?Create and change to working directory for
+ one test.]
+ [+CLEANUP \b\astatus\a?Called at exit time to remove the
+ temporary directory \aunit\a\b.tmp\b, list the tests totals via
+ \bTALLY\b, and exit with status \astatus\a.]
+ [+COMMAND \b\aarg\a ...?Runs the current command under test with
+ \aarg\a ... appended to the default args.]
+ [+CONTINUE?The background job must be running.]
+ [+COPY \b\afrom to\a?Copy file \afrom\a to \ato\a. \afrom\a may
+ be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post
+ test comparisons are still done for \afrom\a.]
+ [+DIAGNOSTICS \b[ \b1\b | \b0\b | \apattern\a ]]?No argument or an
+ argument of \b1\b declares that diagnostics are to expected for
+ the remainder of the current \bTEST\b; \b0\b reverts to the default
+ state that diagnostics are not expected; otherwise the argument
+ is a \bksh\b(1) pattern that must match the non-empty contents
+ of the standard error.]
+ [+DO \b\astatement\a?Defines additional statements to be executed
+ for the current test. \astatement\a may be a { ... } group.]
+ [+EMPTY \bINPUT|OUTPUT|ERROR|SAME?The corresponding file is
+ expected to be empty.]
+ [+ERROR \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ standard error is expected to match either the contents
+ of \afile\a or the line \adata\a. \bERROR -n\b does not
+ append a newline to \adata\a. \afilter\a is a shell command
+ or pipeline that reads standard input and writes standard
+ output that is applied to ERROR before comparison with the
+ expected contents.]
+ [+EXEC \b[ \aarg\a ... ]]?Runs the command under test with
+ optional arguments. \bINPUT\b, \bOUTPUT\b, \bERROR\b, \bEXIT\b
+ and \bSAME\b calls following this \bEXEC\b up until the next
+ \bEXEC\b or the end of the script provide details for the
+ expected results. If no arguments are specified then the
+ arguments from the previious \bEXEC\b in the current \bTEST\b
+ group are used, or no arguments if this is the first \bEXEC\b
+ in the group.]
+ [+EXIT \b\astatus\a?The command exit status is expected to match
+ the pattern \astatus\a.]
+ [+EXITED?The background job must have exited.]
+ [+EXPORT \b[-]] \aname\a=\avalue\a ...?Export environment
+ variables for one test.]
+ [+FATAL \b\amessage\a ...?\amessage\a is printed on the standard
+ error and \bregress\b exits with status \b1\b.]
+ [+FIFO \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ \bIO\B file is a fifo.]
+ [+IF \b\acommand\a [\anote\a]]?If the \bsh\b(1) \acommand\a exits
+ 0 then tests until the next \bELIF\b, \bELSE\b or \bFI\b are
+ enabled. Otherwise those tests are skipped. \bIF\b ... \bFI\b
+ may be nested, but must not cross \bTEST\b boundaries. \anote\a
+ is listed on the standard error if the correspoding test block
+ is enabled; \bIF\b, \bELIF\b, \bELSE\b may nave a \anote\a
+ operand.]
+ [+IGNORE \b\afile\a ...?\afile\a is ignored for subsequent result
+ comparisons. \afile\a may be \bOUTPUT\b or \bERROR\b.]
+ [+IGNORESPACE?Ignore space differences when comparing expected
+ output.]
+ [+INCLUDE \b\afile\a ...?One or more \afile\a operands are read
+ via the \bksh\b(1) \b.\b(1) command. \bVIEW\b is used to locate
+ the files.]
+ [+INFO \b\adescription\a?\adescription\a is printed on the
+ standard error.]
+ [+INITIALIZE?Called by \bregress\b to initialize a each
+ \bTEST\b group.]
+ [+INPUT \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ standard input is set to either the contents of \afile\a
+ or the line \adata\a. \bINPUT -n\b does not append a newline
+ to \adata\a. \afilter\a is a shell command or pipeline that
+ reads standard input and writes standard output that is
+ applied to OUTPUT before comparison with the expected contents.]
+ [+INTRO?Called by \bregress\b to introduce all \bTEST\b
+ groups.]
+ [+IO \b[ \bFIFO\b | \bPIPE\b ]] \bINPUT|OUTPUT|ERROR\b [ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?Internal
+ support for the \bINPUT\b, \bOUTPUT\b and \bERROR\b functions.]
+ [+JOB \b\aop\a [ ... ]]?Like \bEXEC\b except the command is run
+ as a background job for the duration of the group or until it
+ is killed via \bKILL\b.]
+ [+KEEP \b\apattern\a ...?The temporary directory is cleared for
+ each test. Files matching \apattern\a are retained between
+ tests.]
+ [+KILL \b[ \asignal\a ]]?Kill the background job with \asignal\a
+ [ \bSIGKILL\b ]].]
+ [+MOVE \b\afrom to\a?Rename file \afrom\a to \ato\a. \afrom\a may
+ be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post
+ test comparisons are ignored for \afrom\a.]
+ [+NOTE \b\acomment\a?\acomment\a is added to the current test
+ trace output.]
+ [+OUTPUT \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ standard output is expected to match either the contents
+ of \afile\a or the line \adata\a. \bOUTPUT -n\b does not
+ append a newline to \adata\a. \afilter\a is a shell command
+ or pipeline that reads standard input and writes standard
+ output that is applied to ERROR before comparison with the
+ expected contents.]
+ [+PIPE \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ \bIO\B file is a pipe.]
+ [+PROG \b\acommand\a [ \aarg\a ... ]]?\acommand\a is run with
+ optional arguments.]
+ [+REMOVE \b\afile\a ...?\afile\a ... are removed after the
+ current test is done.]
+ [+RUN?Called by \bregress\b to run the current test.]
+ [+SAME \b\anew old\a?\anew\a is expected to be the same as
+ \aold\a after the current test completes.]
+ [+SET \b[\bno\b]]\aname\a[=\avalue\a]]?Set the command line
+ option --\aname\a. The setting is in effect for all tests until
+ the next explicit \bSET\b.]
+ [+TALLY?Called by \bregress\b display the \bTEST\b results.]
+ [+TEST \b\anumber\a [ \adescription\a ... ]]?Define a new test
+ group labelled \anumber\a with optional \adescripion\a.]
+ [+TITLE \b[+]] \atext\a?Set the \bTEST\b output title to
+ \atext\a. If \b+\b is specified then \atext\a is appended to
+ the default title. The default title is the test file base
+ name, and, if different from the test file base name, the test
+ unit base name.]
+ [+TWD \b[ \adir\a ... ]]?Set the temporary test dir to \adir\a.
+ The default is \aunit\a\b.tmp\b, where \aunit\a is the test
+ input file sans directory and suffix. If \adir\a matches \b/*\b
+ then it is the directory name; if \adir\a is non-null then the
+ prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is
+ omitted then
+ \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a is
+ used.]
+ [+UMASK \b[ \amask\a ]]?Run subsequent tests with \bumask\b(1)
+ \amask\a. If \amask\a is omitted then the original \bumask\b is
+ used.]
+ [+UNIT \b\acommand\a [ \aarg\a ... ]]?Define the command and
+ optional default arguments to be tested. \bUNIT\b explicitly
+ overrides the default command name derived from the test script
+ file name. A \acommand\a operand with optional arguments
+ overrides the \bUNIT\b \acommand\a and arguments, with the
+ exception that if the \bUNIT\b \acommand\a is \b-\b or \b+\b
+ the \bUNIT\b arguments are appended to the operand or default
+ unit command and arguments.]
+ [+VIEW \b\avar\a [ \afile\a ]]?\avar\a is set to the full
+ pathname of \avar\a [ \afile\a ]] in the current \b$VPATH\b
+ view if defined.]
+ }
+[+SEE ALSO?\bnmake\b(1), \bksh\b(1)]
+'
+ ;;
+*) USAGE='ko:[[no]name[=value]]t:[test]v unit [path [arg ...]]'
+ ;;
+esac
+
+function FATAL # message
+{
+ print -r -u2 "$command: $*"
+ GROUP=FINI
+ exit 1
+}
+
+function EMPTY
+{
+ typeset i
+ typeset -n ARRAY=$1
+ for i in ${!ARRAY[@]}
+ do unset ARRAY[$i]
+ done
+}
+
+function INITIALIZE # void
+{
+ typeset i j
+ cd "$TWD"
+ case $KEEP in
+ "") RM *
+ ;;
+ *) for i in *
+ do case $i in
+ !($KEEP)) j="$j $i" ;;
+ esac
+ done
+ case $j in
+ ?*) RM $j ;;
+ esac
+ ;;
+ esac
+ : >INPUT >OUTPUT.ex >ERROR.ex
+ BODY=""
+ COPY=""
+ DIAGNOSTICS=""
+ DONE=""
+ ERROR=""
+ EXIT=0
+ IGNORE=""
+ INIT=""
+ INPUT=""
+ MOVE=""
+ OUTPUT=""
+ EMPTY FILE
+ EMPTY FILTER
+ EMPTY SAME
+ EMPTY TYPE
+}
+
+function INTRO
+{
+ typeset base command
+
+ if [[ ! $TEST_quiet ]]
+ then base=${REGRESS##*/}
+ base=${base%.tst}
+ command=${COMMAND##*/}
+ command=${command%' '*}
+ set -- $TITLE
+ TITLE=
+ case $1 in
+ ''|+) if [[ $command == $base ]]
+ then TITLE=$COMMAND
+ else TITLE="$COMMAND, $base"
+ fi
+ if (( $# ))
+ then shift
+ fi
+ ;;
+ esac
+ while (( $# ))
+ do if [[ $TITLE ]]
+ then TITLE="$TITLE, $1"
+ else TITLE="$1"
+ fi
+ shift
+ done
+ print -u2 "TEST $TITLE"
+ fi
+}
+
+function TALLY # extra message text
+{
+ typeset msg
+ case $GROUP in
+ INIT) ;;
+ *) msg="TEST $TITLE, $TESTS test"
+ case $TESTS in
+ 1) ;;
+ *) msg=${msg}s ;;
+ esac
+ msg="$msg, $ERRORS error"
+ case $ERRORS in
+ 1) ;;
+ *) msg=${msg}s ;;
+ esac
+ if (( $# ))
+ then msg="$msg, $*"
+ fi
+ print -u2 "$msg"
+ GROUP=INIT
+ TESTS=0
+ ERRORS=0
+ ;;
+ esac
+}
+
+function TITLE # text
+{
+ TITLE=$@
+}
+
+function UNWIND
+{
+ while (( COND > 1 ))
+ do print -r -u2 "$command: line $LINE: no matching FI for IF on line ${COND_LINE[COND]}"
+ (( COND-- ))
+ done
+ if (( COND > 0 ))
+ then (( COND = 0 ))
+ FATAL "line $LINE: no matching FI for IF on line ${COND_LINE[COND+1]}"
+ fi
+ if [[ $JOBPID ]]
+ then if [[ $JOBPID != 0 ]]
+ then kill -KILL $JOBPID 2>/dev/null
+ wait
+ fi
+ JOBPID=
+ fi
+ JOBSTATUS=
+ JOBOP=
+ wait
+}
+
+function CLEANUP # status
+{
+ typeset note
+
+ if [[ $GROUP != INIT ]]
+ then if [[ ! $TEST_keep ]]
+ then cd $SOURCE
+ if [[ $TEST_local ]]
+ then RM ${TEST_local}
+ fi
+ RM "$TWD"
+ fi
+ if (( $1 )) && [[ $GROUP != FINI ]]
+ then note=terminated
+ fi
+ fi
+ TALLY $note
+ [[ $TEST_keep ]] || UNWIND
+ exit $1
+}
+
+function RUN # [ op ]
+{
+ typeset i r=1
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+#print -u2 AHA#$LINENO $0 GROUP=$GROUP ITEM=$ITEM FLUSHED=$FLUSHED JOBOP=$JOBOP
+ case $GROUP in
+ INIT) RM "$TWD"
+ if [[ $TEST_local ]]
+ then TEST_local=${TMPDIR:-/tmp}/rt-$$/${TWD##*/}
+ mkdir -p "$TEST_local" && ln -s "$TEST_local" "$TWD" || FATAL "$TWD": cannot create directory
+ TEST_local=${TEST_local%/*}
+ else mkdir "$TWD" || FATAL "$TWD": cannot create directory
+ fi
+ cd "$TWD"
+ TWD=$PWD
+ : > rmu
+ if rm -u rmu >/dev/null 2>&1
+ then TEST_rmu=-u
+ else rm rmu
+ fi
+ if [[ $UNIT ]]
+ then set -- "${ARGV[@]}"
+ case $1 in
+ ""|[-+]*)
+ UNIT $UNIT "${ARGV[@]}"
+ ;;
+ *) UNIT "${ARGV[@]}"
+ ;;
+ esac
+ fi
+ INTRO
+ ;;
+ FINI) ;;
+ $TEST_select)
+ if [[ $ITEM == $FLUSHED ]]
+ then return 0
+ fi
+ FLUSHED=$ITEM
+ if (( COND_SKIP[COND] ))
+ then return 1
+ fi
+ ((COUNT++))
+ if (( $ITEM <= $LASTITEM ))
+ then LABEL=$TEST#$COUNT
+ else LASTITEM=$ITEM
+ LABEL=$TEST:$ITEM
+ fi
+ TEST_file=""
+ exec >/dev/null
+ for i in $INPUT
+ do case " $OUTPUT " in
+ *" $i "*)
+ if [[ -f $i.sav ]]
+ then cp $i.sav $i
+ COMPARE="$COMPARE $i"
+ elif [[ -f $i ]]
+ then cp $i $i.sav
+ COMPARE="$COMPARE $i"
+ fi
+ ;;
+ esac
+ done
+ for i in $OUTPUT
+ do case " $COMPARE " in
+ *" $i "*)
+ ;;
+ *) COMPARE="$COMPARE $i"
+ ;;
+ esac
+ done
+ for i in $INIT
+ do $i $TEST INIT
+ done
+#print -u2 AHA#$LINENO $0 GROUP=$GROUP ITEM=$ITEM JOBOP=$JOBOP JOBPID=$JOBPID JOBSTATUS=$JOBSTATUS
+ if [[ $JOBPID != 0 && ( $JOBPID || $JOBSTATUS ) ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ RESULTS
+ elif [[ $BODY ]]
+ then SHOW=$NOTE
+ if [[ ! $TEST_quiet ]]
+ then print -r -u2 " $SHOW"
+ fi
+ for i in $BODY
+ do $i $TEST BODY
+ done
+ else SHOW=
+ if [[ ${TYPE[INPUT]} == PIPE ]]
+ then if [[ ${TYPE[OUTPUT]} == PIPE ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ cat <$TWD/INPUT | COMMAND "${ARGS[@]}" | cat >$TWD/OUTPUT
+ RESULTS 'pipe input'
+ else if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ cat <$TWD/INPUT | COMMAND "${ARGS[@]}" >$TWD/OUTPUT
+ RESULTS 'pipe io'
+ fi
+ elif [[ ${TYPE[OUTPUT]} == PIPE ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ COMMAND "${ARGS[@]}" <$TWD/INPUT | cat >$TWD/OUTPUT
+ RESULTS 'pipe output'
+ else if [[ $TEST_regular ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ if [[ ${TYPE[INPUT]} == FIFO ]]
+ then COMMAND "${ARGS[@]}" >$TWD/OUTPUT
+ else COMMAND "${ARGS[@]}" <$TWD/INPUT >$TWD/OUTPUT
+ fi
+ RESULTS
+ fi
+ if [[ $TEST_pipe_input ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ (trap '' PIPE; cat <$TWD/INPUT 2>/dev/null; exit 0) | COMMAND "${ARGS[@]}" >$TWD/OUTPUT
+ STATUS=$?
+ RESULTS 'pipe input'
+ fi
+ if [[ $TEST_pipe_output ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ COMMAND "${ARGS[@]}" <$TWD/INPUT | cat >$TWD/OUTPUT
+ STATUS=$?
+ RESULTS 'pipe output'
+ fi
+ if [[ $TEST_pipe_io ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ (trap '' PIPE; cat <$TWD/INPUT 2>/dev/null; exit 0) | COMMAND "${ARGS[@]}" | cat >$TWD/OUTPUT
+ STATUS=$?
+ RESULTS 'pipe io'
+ fi
+ fi
+ set -- $COPY
+ COPY=""
+ while :
+ do case $# in
+ 0|1) break ;;
+ *) cp $1 $2 ;;
+ esac
+ shift 2
+ done
+ set -- $MOVE
+ MOVE=""
+ while (( $# > 1 ))
+ do mv $1 $2
+ shift 2
+ done
+ fi
+ for i in $DONE
+ do $i $TEST DONE $STATUS
+ done
+ COMPARE=""
+ r=0
+ ;;
+ esac
+ if [[ $COMMAND_ORIG ]]
+ then COMMAND=$COMMAND_ORIG
+ COMMAND_ORIG=
+ ARGS=(${ARGS_ORIG[@]})
+ fi
+ return $r
+}
+
+function DO # cmd ...
+{
+ [[ $GROUP == $TEST_select ]] || return 1
+ (( COND_SKIP[COND] )) && return 1
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK
+ return 0
+}
+
+function UNIT # cmd arg ...
+{
+ typeset cmd=$1
+ case $cmd in
+ [-+]) shift
+ if (( UNIT_READONLY ))
+ then COMMAND="$COMMAND $*"
+ else #BUG# ARGV=("${ARGV[@]}" "$@")
+ set -- "${ARGV[@]}" "$@"
+ ARGV=("$@")
+ fi
+ return
+ ;;
+ esac
+ (( UNIT_READONLY )) && return
+ if [[ $UNIT ]] && (( $# <= 1 ))
+ then set -- "${ARGV[@]}"
+ case $1 in
+ "") set -- "$cmd" ;;
+ [-+]*) set -- "$cmd" "${ARGV[@]}" ;;
+ *) cmd=$1 ;;
+ esac
+ fi
+ UNIT=
+ COMMAND=$cmd
+ shift
+ typeset cmd=$(whence $COMMAND)
+ if [[ ! $cmd ]]
+ then FATAL $COMMAND: not found
+ elif [[ ! $cmd ]]
+ then FATAL $cmd: not found
+ fi
+ case $# in
+ 0) ;;
+ *) COMMAND="$COMMAND $*" ;;
+ esac
+}
+
+function TWD # [ dir ]
+{
+ case $1 in
+ '') TWD=${TWD##*/}; TWD=${TMPDIR:-/tmp}/tst-${TWD%.*}-$$-$RANDOM ;;
+ /*) TWD=$1 ;;
+ *) TWD=${TMPDIR:-/tmp}/$1 ;;
+ esac
+}
+
+function TEST # number description arg ...
+{
+ RUN
+ LINE=$TESTLINE
+ UNWIND
+ COUNT=0
+ LASTITEM=0
+ case $1 in
+ -) ((LAST++)); TEST=$LAST ;;
+ +([0123456789])) LAST=$1 TEST=$1 ;;
+ *) LAST=0${1/[!0123456789]/} TEST=$1 ;;
+ esac
+ NOTE=
+ if [[ ! $TEST_quiet && $TEST == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+ then print -r -u2 "$TEST $2"
+ fi
+ unset ARGS
+ unset EXPORT
+ EXPORTS=0
+ TEST_file=""
+ if [[ $TEST != ${GROUP}* ]]
+ then GROUP=${TEST%%+([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ])}
+ if [[ $GROUP == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+ then INITIALIZE
+ fi
+ fi
+ ((SUBTESTS=0))
+ [[ $TEST == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+}
+
+function EXEC # arg ...
+{
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ if ((SUBTESTS++))
+ then RUN
+ fi
+ case $# in
+ 0) set -- "${ARGS[@]}" ;;
+ esac
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $COMMAND_ORIG "$@")${JOBPID:+&}"
+ ARGS=("$@")
+}
+
+function JOB # arg ...
+{
+ JOBPID=0
+ EXEC "$@"
+}
+
+function CONTINUE
+{
+ RUN || return
+ JOBOP=CONTINUE
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $JOBOP)"
+#print -u2 AHA#$LINENO JOBOP=$JOBOP ITEM=$ITEM NOTE=$NOTE
+}
+
+function EXITED
+{
+ RUN || return
+ JOBOP=EXITED
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $JOBOP)"
+#print -u2 AHA#$LINENO JOBOP=$JOBOP ITEM=$ITEM NOTE=$NOTE
+}
+
+function KILL # [ signal ]
+{
+ RUN || return
+ JOBOP=$2
+ [[ $JOBOP ]] || JOBOP=KILL
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $JOBOP)"
+}
+
+function CD
+{
+ RUN
+ if [[ $GROUP == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+ then mkdir -p "$@" && cd "$@" || FATAL cannot initialize working directory "$@"
+ fi
+}
+
+function EXPORT
+{
+ typeset x n v
+ if [[ $GROUP == INIT ]]
+ then for x
+ do n=${x%%=*}
+ v=${x#*=}
+ ENVIRON[ENVIRONS++]=$n="'$v'"
+ done
+ else RUN
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ for x
+ do n=${x%%=*}
+ v=${x#*=}
+ EXPORT[EXPORTS++]=$n="'$v'"
+ done
+ fi
+}
+
+function FLUSH
+{
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ if ((SUBTESTS++))
+ then RUN
+ fi
+}
+
+function PROG # cmd arg ...
+{
+ typeset command args
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- "$@")"
+ COMMAND_ORIG=$COMMAND
+ COMMAND=$1
+ shift
+ ARGS_ORIG=(${ARGS[@]})
+ ARGS=("$@")
+}
+
+function NOTE # description
+{
+ NOTE=$*
+}
+
+function IO # [ PIPE ] INPUT|OUTPUT|ERROR [-f*|-n] file|- data ...
+{
+ typeset op i v f file type x
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+ while :
+ do case $1 in
+ FIFO|PIPE) type=$1; shift ;;
+ *) break ;;
+ esac
+ done
+ op=$1
+ shift
+ [[ $type ]] && TYPE[$op]=$type
+ FILTER[$op]=
+ file=$TWD/$op
+ while :
+ do case $1 in
+ -x) x=1
+ shift
+ ;;
+ -e) (( $# > 1 )) && shift
+ FILTER[$op]=$1
+ shift
+ ;;
+ -e*) FILTER[$op]=${1#-e}
+ shift
+ ;;
+ -f*|-n) f=$1
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -) ;;
+ *) file=$1
+ eval i='$'$op
+ case " $i " in
+ *" $file "*)
+ ;;
+ *) eval $op='"$'$op' $file"'
+ ;;
+ esac
+ ;;
+ esac
+ shift
+ ;;
+ esac
+ case " $IGNORE " in
+ *" $file "*)
+ for i in $IGNORE
+ do case $i in
+ $file) ;;
+ *) v="$v $i" ;;
+ esac
+ done
+ IGNORE=$v
+ ;;
+ esac
+ FILE[$op]=$file
+ case $op in
+ OUTPUT|ERROR)
+ file=$file.ex
+ if [[ $file != /* ]]
+ then file=$TWD/$file
+ fi
+ ;;
+ esac
+ #unset SAME[$op]
+ SAME[$op]=
+ if [[ $file == /* ]]
+ then RM $file.sav
+ else RM $TWD/$file.sav
+ fi
+ if [[ $file == */* ]]
+ then mkdir -p ${file%/*}
+ fi
+ if [[ $file != */ ]]
+ then if [[ $type == FIFO ]]
+ then rm -f $file
+ mkfifo $file
+ fi
+ if [[ ${TYPE[$op]} != FIFO ]]
+ then if [[ $JOBOP ]]
+ then case $#:$f in
+ 0:) ;;
+ *:-f) printf -- "$@" ;;
+ *:-f*) printf -- "${f#-f}""$@" ;;
+ *) print $f -r -- "$@" ;;
+ esac >> $file
+ else case $#:$f in
+ 0:) ;;
+ *:-f) printf -- "$@" ;;
+ *:-f*) printf -- "${f#-f}""$@" ;;
+ *) print $f -r -- "$@" ;;
+ esac > $file
+ fi
+ elif [[ $#:$f != 0: ]]
+ then case $#:$f in
+ *:-f) printf -- "$@" ;;
+ *:-f*) printf -- "${f#-f}""$@" ;;
+ *) print $f -r -- "$@" ;;
+ esac >> $file &
+ fi
+ if [[ $x ]]
+ then chmod +x $file
+ fi
+ fi
+}
+
+function INPUT # file|- data ...
+{
+ IO $0 "$@"
+}
+
+function COPY # from to
+{
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ COPY="$COPY $@"
+}
+
+function MOVE # from to
+{
+ typeset f
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ for f
+ do case $f in
+ INPUT|OUTPUT|ERROR)
+ f=$TWD/$f
+ ;;
+ /*) ;;
+ *) f=$PWD/$f
+ ;;
+ esac
+ MOVE="$MOVE $f"
+ done
+}
+
+function SAME # new old
+{
+ typeset i file v
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ case $# in
+ 2) case $1 in
+ INPUT) cat $2 > $1; return ;;
+ esac
+ SAME[$1]=$2
+ file=$1
+ COMPARE="$COMPARE $1"
+ ;;
+ 3) SAME[$2]=$3
+ file=$2
+ eval i='$'$1
+ case " $i " in
+ *" $2 "*)
+ ;;
+ *) eval $1='"$'$1' $2"'
+ ;;
+ esac
+ COMPARE="$COMPARE $2"
+ ;;
+ esac
+ case " $IGNORE " in
+ *" $file "*)
+ for i in $IGNORE
+ do case $i in
+ $file) ;;
+ *) v="$v $i" ;;
+ esac
+ done
+ IGNORE=$v
+ ;;
+ esac
+}
+
+function OUTPUT # file|- data ...
+{
+ IO $0 "$@"
+}
+
+function ERROR # file|- data ...
+{
+ IO $0 "$@"
+}
+
+function RM # rm(1) args
+{
+ if [[ ! $TEST_rmu ]]
+ then chmod -R u+rwx "$@" >/dev/null 2>&1
+ fi
+ rm $TEST_rmu $TEST_rmflags "$@"
+}
+
+function REMOVE # file ...
+{
+ typeset i
+ for i
+ do RM $i $i.sav
+ done
+}
+
+function IGNORE # file ...
+{
+ typeset i
+ for i
+ do case $i in
+ INPUT|OUTPUT|ERROR)
+ i=$TWD/$i
+ ;;
+ esac
+ case " $IGNORE " in
+ *" $i "*)
+ ;;
+ *) IGNORE="$IGNORE $i"
+ ;;
+ esac
+ done
+}
+
+function KEEP # pattern ...
+{
+ typeset i
+ for i
+ do case $KEEP in
+ "") KEEP="$i" ;;
+ *) KEEP="$KEEP|$i" ;;
+ esac
+ done
+}
+
+function DIAGNOSTICS # [ 1 | 0 ]
+{
+ case $#:$1 in
+ 0:|1:1) DIAGNOSTICS=1
+ EXIT='*'
+ ;;
+ 1:|1:0) DIAGNOSTICS=""
+ EXIT=0
+ ;;
+ *) DIAGNOSTICS=$1
+ EXIT='*'
+ ;;
+ esac
+}
+
+function IGNORESPACE
+{
+ : ${IGNORESPACE=-b}
+}
+
+function EXIT # status
+{
+ EXIT=$1
+}
+
+function INFO # info description
+{
+ typeset -R15 info=$1
+ if [[ ! $1 ]]
+ then info=no
+ fi
+ shift
+ if [[ ! $TEST_quiet ]]
+ then print -r -u2 "$info " "$@"
+ fi
+}
+
+function COMMAND # arg ...
+{
+ typeset input
+ ((TESTS++))
+ case " ${ENVIRON[*]} ${EXPORT[*]}" in
+ *' 'LC_ALL=*)
+ ;;
+ *' 'LC_+([A-Z])=*)
+ EXPORT[EXPORTS++]="LC_ALL="
+ ;;
+ esac
+ if [[ $TEST_keep ]]
+ then (
+ PS4=''
+ set -x
+ print -r -- "${ENVIRON[@]}" "${EXPORT[@]}" "PATH=$PATH" $COMMAND "$@"
+ ) 2>&1 >/dev/null |
+ sed -e 's,^print -r -- ,,' -e 's,$, "$@",' >$TWD/COMMAND
+ chmod +x $TWD/COMMAND
+ fi
+ if [[ $UMASK != $UMASK_ORIG ]]
+ then : >$TWD/ERROR
+ umask $UMASK
+ fi
+ if [[ ${TYPE[INPUT]} == FIFO && ${FILE[INPUT]} == */INPUT ]]
+ then input="< ${FILE[INPUT]}"
+ fi
+ if [[ $TEST_trace ]]
+ then set +x
+ eval print -u2 "$PS4" "${ENVIRON[@]}" "${EXPORT[@]}" PATH='$PATH' '$'COMMAND '"$@"' '$input' '"2>$TWD/ERROR"' '"${JOBPID:+&}"'
+ fi
+ eval "${ENVIRON[@]}" "${EXPORT[@]}" PATH='$PATH' '$'COMMAND '"$@"' $input "2>$TWD/ERROR" "${JOBPID:+&}"
+ STATUS=$?
+ [[ $TEST_trace ]] && set -x
+ if [[ $JOBPID ]]
+ then JOBPID=$!
+ fi
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+ return $STATUS
+}
+
+function RESULTS # pipe*
+{
+ typeset i j k s failed ignore io op
+ if [[ $1 ]]
+ then io="$1 "
+ fi
+ [[ $JOBOP || $JOBPID || $JOBSTATUS ]] && sleep 1
+ for i in $COMPARE $TWD/OUTPUT $TWD/ERROR
+ do case " $IGNORE $ignore $MOVE " in
+ *" $i "*) continue ;;
+ esac
+ ignore="$ignore $i"
+ op=${i##*/}
+ if [[ ${FILTER[$op]} ]]
+ then eval "{ ${FILTER[$op]} ;} < $i > $i.fi"
+ mv $i.fi $i
+ fi
+ j=${SAME[$op]}
+ if [[ ! $j ]]
+ then if [[ $i == /* ]]
+ then k=$i
+ else k=$TWD/$i
+ fi
+ for s in ex sav err
+ do [[ -f $k.$s ]] && break
+ done
+ j=$k.$s
+ fi
+ if [[ "$DIAGNOSTICS" && $i == */ERROR ]]
+ then if [[ $STATUS == 0 && ! -s $TWD/ERROR || $DIAGNOSTICS != 1 && $(<$i) != $DIAGNOSTICS ]]
+ then failed=$failed${failed:+,}DIAGNOSTICS
+ if [[ $TEST_verbose && $DIAGNOSTICS != 1 ]]
+ then print -u2 " ===" "diagnostic pattern '$DIAGNOSTICS' did not match" ${i#$TWD/} "==="
+ cat $i >&2
+ fi
+ fi
+ continue
+ fi
+ diff $IGNORESPACE $i $j >$i.diff 2>&1
+ if [[ -s $i.diff ]]
+ then failed=$failed${failed:+,}${i#$TWD/}
+ if [[ $TEST_verbose ]]
+ then print -u2 " ===" diff $IGNORESPACE ${i#$TWD/} "<actual >expected ==="
+ cat $i.diff >&2
+ fi
+ fi
+ done
+ if [[ $JOBOP ]]
+ then if [[ $JOBPID ]] && ! kill -0 $JOBPID 2>/dev/null
+ then wait $JOBPID
+ JOBSTATUS=$?
+ JOBPID=
+ fi
+#print -u2 AHA#$LINENO JOBOP=$JOBOP JOBPID=$JOBPID JOBSTATUS=$JOBSTATUS
+ case $JOBOP in
+ CONTINUE)
+ if [[ ! $JOBPID ]]
+ then failed=$failed${failed:+,}EXITED
+ fi
+ ;;
+ EXITED) if [[ $JOBPID ]]
+ then failed=$failed${failed:+,}RUNNING
+ fi
+ ;;
+ *) if [[ ! $JOBPID ]]
+ then failed=$failed${failed:+,}EXITED
+ fi
+ if ! kill -$JOBOP $JOBPID 2>/dev/null
+ then failed=$failed${failed:+,}KILL-$JOBOP
+ fi
+ ;;
+ esac
+ JOBOP=
+ fi
+ if [[ ! $failed && $STATUS != $EXIT ]]
+ then failed="exit code $EXIT expected -- got $STATUS"
+ fi
+ if [[ $failed ]]
+ then ((ERRORS++))
+ if [[ ! $TEST_quiet ]]
+ then SHOW="FAILED ${io}[ $failed ] $NOTE"
+ print -r -u2 " $SHOW"
+ fi
+ if [[ $TEST_keep ]]
+ then GROUP=FINI
+ exit
+ fi
+ elif [[ ! $TEST_quiet ]]
+ then SHOW=$NOTE
+ print -r -u2 " $SHOW"
+ fi
+}
+
+function SET # [no]name[=value]
+{
+ typeset i r
+ if [[ $TEST ]]
+ then RUN
+ fi
+ for i
+ do if [[ $i == - ]]
+ then r=1
+ elif [[ $i == + ]]
+ then r=
+ else if [[ $i == no?* ]]
+ then i=${i#no}
+ v=
+ elif [[ $i == *=* ]]
+ then v=${i#*=}
+ if [[ $v == 0 ]]
+ then v=
+ fi
+ i=${i%%=*}
+ else v=1
+ fi
+ i=${i//-/_}
+ if [[ $r ]]
+ then READONLY[$i]=1
+ elif [[ ${READONLY[$i]} ]]
+ then continue
+ fi
+ eval TEST_$i=$v
+ fi
+ done
+}
+
+function VIEW # var [ file ]
+{
+ nameref var=$1
+ typeset i bwd file pwd view root offset
+ if [[ $var ]]
+ then return 0
+ fi
+ case $# in
+ 1) file=$1 ;;
+ *) file=$2 ;;
+ esac
+ pwd=${TWD%/*}
+ bwd=${PMP%/*}
+ if [[ -r $file ]]
+ then if [[ ! -d $file ]]
+ then var=$PWD/$file
+ return 0
+ fi
+ for i in $file/*
+ do if [[ -r $i ]]
+ then var=$PWD/$file
+ return 0
+ fi
+ break
+ done
+ fi
+ for view in ${VIEWS[@]}
+ do case $view in
+ /*) ;;
+ *) view=$pwd/$view ;;
+ esac
+ case $offset in
+ '') case $pwd in
+ $view/*) offset=${pwd#$view} ;;
+ *) offset=${bwd#$view} ;;
+ esac
+ ;;
+ esac
+ if [[ -r $view$offset/$file ]]
+ then if [[ ! -d $view$offset/$file ]]
+ then var=$view$offset/$file
+ return 0
+ fi
+ for i in $view$offset/$file/*
+ do if [[ -f $i ]]
+ then var=$view$offset/$file
+ return 0
+ fi
+ break
+ done
+ fi
+ done
+ var=
+ return 1
+}
+
+function INCLUDE # file ...
+{
+ typeset f v x
+ for f
+ do if VIEW v $f || [[ $PREFIX && $f != /* ]] && VIEW v $PREFIX$f
+ then x=$x$'\n'". $v"
+ else FATAL $f: not found
+ fi
+ done
+ [[ $x ]] && trap "$x" 0
+}
+
+function UMASK # [ mask ]
+{
+ if (( $# ))
+ then UMASK=$1
+ else UMASK=$UMASK_ORIG
+ fi
+}
+
+function PIPE # INPUT|OUTPUT|ERROR file|- data ...
+{
+ IO $0 "$@"
+}
+
+function FIFO # INPUT|OUTPUT|ERROR file|- data ...
+{
+ IO $0 "$@"
+}
+
+function IF # command(s) [note]
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ (( COND++ ))
+ COND_LINE[COND]=$LINE
+ if (( COND > 1 && COND_SKIP[COND-1] ))
+ then (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 1 ))
+ elif eval "{ $1 ;} >/dev/null 2>&1"
+ then (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 0 ))
+ [[ $2 && ! $TEST_quiet ]] && print -u2 "NOTE $2"
+ else (( COND_KEPT[COND] = 0 ))
+ (( COND_SKIP[COND] = 1 ))
+ fi
+}
+
+function ELIF # command(s) [note]
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ if (( COND <= 0 ))
+ then FATAL line $LINE: no matching IF for ELIF
+ fi
+ if (( COND_KEPT[COND] ))
+ then (( COND_SKIP[COND] = 0 ))
+ elif eval "$* > /dev/null 2>&1"
+ then (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 0 ))
+ [[ $2 && ! $TEST_quiet ]] && print -u2 "NOTE $2"
+ else (( COND_SKIP[COND] = 1 ))
+ fi
+}
+
+function ELSE # [note]
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ if (( COND <= 0 ))
+ then FATAL line $LINE: no matching IF for ELSE
+ fi
+ if (( COND_KEPT[COND] ))
+ then (( COND_SKIP[COND] = 1 ))
+ else (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 0 ))
+ [[ $1 && ! $TEST_quiet ]] && print -u2 "NOTE $1"
+ fi
+}
+
+function FI
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ if (( COND <= 0 ))
+ then FATAL line $LINE: no matching IF for FI on line $LINE
+ fi
+ (( ! COND_KEPT[COND] )) && [[ $1 && ! $TEST_quiet ]] && print -u2 "NOTE $1"
+ (( COND-- ))
+}
+
+# main
+
+integer ERRORS=0 ENVIRONS=0 EXPORTS=0 TESTS=0 SUBTESTS=0 LINE=0 TESTLINE=0
+integer ITEM=0 LASTITEM=0 COND=0 UNIT_READONLY=0 COUNT
+typeset ARGS COMMAND COPY DIAGNOSTICS ERROR EXEC FLUSHED=0 GROUP=INIT
+typeset IGNORE INPUT KEEP OUTPUT TEST SOURCE MOVE NOTE UMASK UMASK_ORIG
+typeset ARGS_ORIG COMMAND_ORIG TITLE UNIT ARGV PREFIX OFFSET IGNORESPACE
+typeset COMPARE MAIN JOBPID='' JOBSTATUS=''
+typeset TEST_file TEST_keep TEST_pipe_input TEST_pipe_io TEST_pipe_output TEST_local
+typeset TEST_quiet TEST_regular=1 TEST_rmflags='-rf --' TEST_rmu TEST_select
+
+typeset -A SAME VIEWS FILE TYPE READONLY FILTER
+typeset -a COND_LINE COND_SKIP COND_KEPT ENVIRON EXPORT
+typeset -Z LAST=00
+
+unset FIGNORE
+
+while getopts -a $command "$USAGE" OPT
+do case $OPT in
+ b) (( $OPTARG )) && IGNORESPACE=-b
+ ;;
+ i) SET - pipe-input=$OPTARG
+ ;;
+ k) SET - keep=$OPTARG
+ ;;
+ l) SET - local
+ ;;
+ o) SET - pipe-output=$OPTARG
+ ;;
+ p) SET - pipe-io=$OPTARG
+ ;;
+ q) SET - quiet=$OPTARG
+ ;;
+ r) SET - regular=$OPTARG
+ ;;
+ t) if [[ $TEST_select ]]
+ then TEST_select="$TEST_select|${OPTARG//,/\|}"
+ else TEST_select="${OPTARG//,/\|}"
+ fi
+ ;;
+ x) SET - trace=$OPTARG
+ ;;
+ v) SET - verbose=$OPTARG
+ ;;
+ *) GROUP=FINI
+ exit 2
+ ;;
+ esac
+done
+shift $OPTIND-1
+case $# in
+0) FATAL test unit name omitted ;;
+esac
+export COLUMNS=80
+SOURCE=$PWD
+PATH=$SOURCE:${PATH#?(.):}
+PATH=${PATH%%:?(.)}:/usr/5bin:/bin:/usr/bin
+UNIT=$1
+shift
+if [[ -f $UNIT && ! -x $UNIT ]]
+then REGRESS=$UNIT
+else REGRESS=${UNIT%.tst}
+ REGRESS=$REGRESS.tst
+ [[ -f $REGRESS ]] || FATAL $REGRESS: regression tests not found
+fi
+UNIT=${UNIT##*/}
+UNIT=${UNIT%.tst}
+MAIN=$UNIT
+if [[ $VPATH ]]
+then set -A VIEWS ${VPATH//:/' '}
+ OFFSET=${SOURCE#${VIEWS[0]}}
+ if [[ $OFFSET ]]
+ then OFFSET=${OFFSET#/}/
+ fi
+fi
+if [[ $REGRESS == */* ]]
+then PREFIX=${REGRESS%/*}
+ if [[ ${#VIEWS[@]} ]]
+ then for i in ${VIEWS[@]}
+ do PREFIX=${PREFIX#$i/}
+ done
+ fi
+ PREFIX=${PREFIX#$OFFSET}
+ if [[ $PREFIX ]]
+ then PREFIX=$PREFIX/
+ fi
+fi
+TWD=$PWD/$UNIT.tmp
+PMP=$(pwd -P)/$UNIT.tmp
+UMASK_ORIG=$(umask)
+UMASK=$UMASK_ORIG
+ARGV=("$@")
+if [[ ${ARGV[0]} && ${ARGV[0]} != [-+]* ]]
+then UNIT "${ARGV[@]}"
+ UNIT_READONLY=1
+fi
+trap 'code=$?; CLEANUP $code' EXIT
+if [[ ! $TEST_select ]]
+then TEST_select="[0123456789]*"
+fi
+TEST_select="@($TEST_select|+(0))"
+if [[ $TEST_trace ]]
+then export PS4=':$LINENO: '
+ typeset -ft $(typeset +f)
+ set -x
+fi
+if [[ $TEST_verbose ]]
+then typeset SHOW
+else typeset -L70 SHOW
+fi
+if [[ ! $TEST_keep ]] && (ulimit -c 0) >/dev/null 2>&1
+then ulimit -c 0
+fi
+set --pipefail
+
+# some last minute shenanigans
+
+alias BODY='BODY=BODY; function BODY'
+alias CONTINUE='LINE=$LINENO; CONTINUE'
+alias DO='(( $ITEM != $FLUSHED )) && RUN DO; DO &&'
+alias DONE='DONE=DONE; function DONE'
+alias EXEC='LINE=$LINENO; EXEC'
+alias EXITED='LINE=$LINENO; EXITED'
+alias INIT='INIT=INIT; function INIT'
+alias JOB='LINE=$LINENO; JOB'
+alias KILL='LINE=$LINENO; KILL'
+alias PROG='LINE=$LINENO; FLUSH; PROG'
+alias TEST='TESTLINE=$LINENO; TEST'
+alias IF='LINE=$LINENO; FLUSH; IF'
+alias ELIF='LINE=$LINENO; FLUSH; ELIF'
+alias ELSE='LINE=$LINENO; FLUSH; ELSE'
+alias FI='LINE=$LINENO; FLUSH; FI'
+
+# do the tests
+
+. $REGRESS
+RUN
+GROUP=FINI
diff --git a/src/cmd/INIT/release.c b/src/cmd/INIT/release.c
new file mode 100644
index 0000000..7b4b1b0
--- /dev/null
+++ b/src/cmd/INIT/release.c
@@ -0,0 +1,366 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * release -- list recent release changes
+ *
+ * coded for portability
+ */
+
+static char id[] = "\n@(#)$Id: release (AT&T Research) 2000-01-28 $\0\n";
+
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <error.h>
+
+static const char usage[] =
+"[-?\n@(#)$Id: release (AT&T Research) 2000-01-28 $\n]"
+USAGE_LICENSE
+"[+NAME?release - list recent changes]"
+"[+DESCRIPTION?\brelease\b lists the changes within the date range specified"
+" by the \b--from\b and \b--to\b options. The input files are assumed to"
+" contain date tag lines of the form [\acc\a]]\ayy-mm-dd\a [ \atext\a ]]"
+" (or \bdate\b(1) default format), where \acc\a is determined by a Y2K"
+" window year of 69 (we can produce an example coding dated 1991 - this"
+" can be patented?, how about 1+1=2?.) The date tag lines are followed by"
+" \areadme\a text in reverse chronological order (newer entries at the"
+" top of the file.) If no selection options are spcified then all"
+" changes are listed. If no \afile\a operands are specified then the"
+" standard input is read.]"
+"[+?The entries for each \afile\a are annotated with the file directory name.]"
+"[f:from?Entries older than \adate\a are omitted.]:[date]"
+"[r:release?List all changes that include the first \acount\a release marks."
+" A release mark has a date tag followed by optional space and at least"
+" three \b-\b characters. Changes from release mark \acount\a+1 are not"
+" listed. If there are no release marks then the date range is used;"
+" if there is at least one release mark then the date range is ignored"
+" and at most \acount\a release marks will be listed.]#[count]"
+"[t:to?Entries newer than \adate\a are omitted.]:[date]"
+"[V?Print the program version and exit.]"
+
+"\n"
+"\n[ file ... ]\n"
+"\n"
+
+"[+SEE ALSO?\bpackage\b(1)]"
+;
+
+#else
+
+#define elementsof(x) ((int)(sizeof(x)/sizeof(x[0])))
+
+#define NiL ((char*)0)
+
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#if !_PACKAGE_ast && defined(__STDC__)
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+static char mon[] = "janfebmaraprmayjunjulaugsepoctnovdec";
+static char day[] = "sunmontuewedthufrisat";
+
+#if !_PACKAGE_ast
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: release [-V] [-h hi-date] [-l lo-date] [-r count] [ file ...]\n");
+ exit(2);
+}
+
+#endif
+
+static unsigned long
+number(register char* s, char** e)
+{
+ unsigned long q = 0;
+
+ while (isspace(*s))
+ s++;
+ while (isdigit(*s))
+ q = q * 10 + *s++ - '0';
+ if (e)
+ *e = s;
+ return q;
+}
+
+unsigned long
+string(register char* s, char* tab, int num, int siz, char** e)
+{
+ register int i;
+ register int j;
+ char buf[16];
+
+ while (isspace(*s))
+ s++;
+ for (i = 0; i < siz; i++)
+ buf[i] = isupper(s[i]) ? tolower(s[i]) : s[i];
+ for (i = 0; i < num; i += siz)
+ for (j = 0; j < siz && buf[j] == tab[j+i]; j++)
+ if (j == (siz - 1))
+ {
+ *e = s + siz;
+ return i / siz + 1;
+ }
+ return 0;
+}
+
+static unsigned long
+date(char* s, char** e)
+{
+ char* t;
+ unsigned long y;
+ unsigned long m;
+ unsigned long d;
+
+ if (isdigit(*s))
+ {
+ y = number(s, &t);
+ if (*t != '-')
+ return 0;
+ switch (t - s)
+ {
+ case 2:
+ y += 1900;
+ if (y <= 1969)
+ y += 100;
+ break;
+ case 4:
+ if (y < 1969)
+ return 0;
+ break;
+ }
+ if (!(m = number(++t, &s)))
+ return 0;
+ if ((s - t) != 2 || *s != '-' || m < 1 || m > 12)
+ return 0;
+ if (!(d = number(++s, &t)))
+ return 0;
+ if ((t - s) != 2 || d < 1 || d > 31)
+ return 0;
+ }
+ else
+ {
+ if (string(s, day, elementsof(day), 3, &t))
+ s = t;
+ if (!(m = string(s, mon, elementsof(mon), 3, &t)))
+ return 0;
+ if (!(d = number(t, &s)))
+ return 0;
+ for (y = 1969; *s; s++)
+ if ((y = number(s, &t)) && (t - s) == 4)
+ {
+ if (y < 1969)
+ return 0;
+ break;
+ }
+ }
+ if (e)
+ {
+ while (isspace(*t))
+ t++;
+ *e = t;
+ }
+ return ((y - 1969) * 13 + m) * 32 + d;
+}
+
+int
+main(int argc, char** argv)
+{
+ register char* s;
+ register char* u;
+ register char* v;
+ char* p;
+ char* e;
+ int i;
+ unsigned long t;
+ unsigned long lo;
+ unsigned long hi;
+ int mk;
+ FILE* f;
+ char buf[1024];
+
+ mk = 0;
+ lo = hi = 0;
+#if _PACKAGE_ast
+ error_info.id = "release";
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'f':
+ if (!(lo = date(opt_info.arg, &e)) || *e)
+ {
+ error(2, "%s: invalid from date [%s]", opt_info.arg, e);
+ return 1;
+ }
+ continue;
+ case 'r':
+ mk = opt_info.num + 1;
+ continue;
+ case 't':
+ if (!(hi = date(opt_info.arg, &e)) || *e)
+ {
+ error(2, "%s: invalid to date [%s]", opt_info.arg, e);
+ return 1;
+ }
+ continue;
+ case 'V':
+ sfprintf(sfstdout, "%s\n", id + 10);
+ return 0;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ argv += opt_info.index;
+#else
+ while ((s = *++argv) && *s == '-' && *(s + 1))
+ {
+ if (*(s + 1) == '-')
+ {
+ if (!*(s + 2))
+ {
+ argv++;
+ break;
+ }
+ usage();
+ break;
+ }
+ for (;;)
+ {
+ switch (i = *++s)
+ {
+ case 0:
+ break;
+ case 'f':
+ case 't':
+ if (!*(v = ++s) && !(v = *++argv))
+ {
+ s = "??";
+ continue;
+ }
+ if (!(t = date(v, &e)) || *e)
+ {
+ fprintf(stderr, "release: -%c%s: invalid date [%s]\n", i, s, e);
+ return 1;
+ }
+ switch (i)
+ {
+ case 'f':
+ lo = t;
+ break;
+ case 't':
+ hi = t;
+ break;
+ }
+ break;
+ case 'r':
+ if (!*(v = ++s) && !(v = *++argv))
+ {
+ s = "??";
+ continue;
+ }
+ mk = number(v, &e) + 1;
+ if (*e)
+ {
+ fprintf(stderr, "release: -%c%s: invalid count\n", i, s);
+ return 1;
+ }
+ break;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ return 0;
+ default:
+ fprintf(stderr, "release: -%c: unknown option\n", i);
+ /*FALLTHROUGH*/
+ case '?':
+ usage();
+ break;
+ }
+ break;
+ }
+ }
+#endif
+ do
+ {
+ if (!(p = *argv++) || !*p || *p == '-' && !*(p + 1))
+ {
+ argv--;
+ p = "";
+ f = stdin;
+ }
+ else if (!(f = fopen(p, "r")))
+ {
+ fprintf(stderr, "release: %s: cannot read", p);
+ return 1;
+ }
+ while (s = fgets(buf, sizeof(buf), f))
+ {
+ if (t = date(s, &e))
+ {
+ if (mk && e[0] == '-' && e[1] == '-' && e[2] == '-' && !--mk)
+ break;
+ if (t < lo)
+ break;
+ if (hi && t > hi)
+ continue;
+ if (p)
+ {
+ if (*p)
+ {
+ for (u = v = p; *p; p++)
+ if (*p == '/')
+ {
+ v = u;
+ u = p + 1;
+ }
+ printf("\n:::::::: ");
+ while ((i = *v++) && i != '/')
+ fputc(i, stdout);
+ printf(" ::::::::\n\n");
+ }
+ p = 0;
+ }
+ }
+ if (!p)
+ fputs(s, stdout);
+ }
+ if (f == stdin)
+ break;
+ fclose(f);
+ } while (*argv);
+ return 0;
+}
diff --git a/src/cmd/INIT/rt.sh b/src/cmd/INIT/rt.sh
new file mode 100644
index 0000000..2b8b840
--- /dev/null
+++ b/src/cmd/INIT/rt.sh
@@ -0,0 +1,479 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: rt - nmake test output filter
+
+command=rt
+flags='--silent --keepgoing'
+failed=0
+heading=1
+verbose=0
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: rt (AT&T Research) 2010-07-27 $
+]
+'$USAGE_LICENSE$'
+[+NAME?rt - run "nmake test" and filter output]
+[+DESCRIPTION?\brt\b runs \vnmake test\v and filters the regression
+ test output to contain only test summary lines. If no \atest\a
+ operands are specified then \btest\b is assumed. If \b-\b is
+ specified then the \afile\a operands, or the standard input
+ if no \afile\a operands are specified, are filtered instead
+ of the output from \bnmake\b.]
+[f:failed?Only list failed test results.]
+[h!:heading?Enable per-file heading when more than one \afile\a operand
+ follows \b-\b.]
+[v:verbose?Run with \vREGRESSFLAGS=-v\v.]
+
+[ test ... | - [ file ... ] ]
+
+[+SEE ALSO?\bnmake\b(1), \bregress\b(1)]
+[+CAVEATS?\brt\b guesses the regression test output style. Garbled
+ output indicates a bad guess.]
+'
+ ;;
+*) ARGV0=""
+ USAGE="fhv"
+ ;;
+esac
+
+function usage
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ f) failed=1 ;;
+ h) heading=0 ;;
+ v) (( verbose=$OPTARG )) && flags="$flags REGRESSFLAGS=-v" ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+ifs=${IFS:-$' \t\n'}
+set -o noglob
+component=
+dots='............................................'
+bad=' ***'
+style=unknown
+integer tests errors signals lineno=0 skip=0
+typeset -l lower
+
+function results # tests errors signals
+{
+ integer t=$1 e=$2 s=$3
+ typeset label note
+ if [[ $style != unknown ]] && (( errors >= 0 ))
+ then style=unknown
+ if (( !failed || errors ))
+ then if (( failed ))
+ then print -r -n -- "$unit"
+ fi
+ if (( t >= 0 ))
+ then if (( t == 1))
+ then label="test "
+ else label=tests
+ fi
+ printf $'%s%5d %s' "$prefix" "$t" "$label"
+ prefix=
+ else prefix="$prefix..........."
+ fi
+ if (( s ))
+ then label=signal
+ (( e=s ))
+ else label=error
+ fi
+ if (( e != 1))
+ then label=${label}s
+ fi
+ if (( e == 1 ))
+ then note=" $bad"
+ elif (( e > 1 ))
+ then note=$bad
+ fi
+ printf $'%s%5d %s%s\n' "$prefix" "$e" "$label" "$note"
+ fi
+ fi
+}
+
+function unit
+{
+ typeset x
+ if [[ $component ]]
+ then x=${component##*/}
+ if [[ " $x " != *' '$unit' '* && " $unit " != *' '$x' '* ]]
+ then if [[ $component == cmd/?*lib/* ]]
+ then unit="$unit $x"
+ else unit="$x $unit"
+ fi
+ fi
+ fi
+ unit="$unit ${dots:1:${#dots}-${#unit}}"
+ if [[ $1 ]]
+ then unit="$unit..........."
+ fi
+ if (( ! failed ))
+ then print -r -n -- "$unit"
+ fi
+}
+
+if [[ $1 == - ]]
+then shift
+ if (( $# <= 1 ))
+ then heading=0
+ fi
+ if (( heading ))
+ then for i
+ do print test heading $i
+ cat -- "$i"
+ done
+ else cat "$@"
+ fi
+else if [[ $1 == *=* ]]
+ then set test "$@"
+ elif (( ! $# ))
+ then set test
+ fi
+ nmake "$@" $flags 2>&1
+fi |
+while read -r line
+do set '' $line
+ shift
+ case $line in
+ TEST[' ']*', '*' error'*)
+ IFS=${IFS}","
+ set '' $line
+ IFS=$ifs
+ set '' $*
+ while :
+ do case $2 in
+ '') break
+ ;;
+ error|errors)
+ errors=$1
+ break
+ ;;
+ test|tests)
+ tests=$1
+ ;;
+ esac
+ shift
+ done
+ results $tests $errors
+ continue
+ ;;
+ TEST[' ']*)
+ results $tests $errors
+ IFS=${IFS}","
+ set '' $line
+ IFS=$ifs
+ set '' $*
+ unit=${3##*/}
+ case $4 in
+ [a-zA-Z]*) unit="$unit $4" ;;
+ esac
+ unit
+ prefix=
+ errors=0
+ signals=0
+ style=regress
+ continue
+ ;;
+ 'pathname and options of item under test')
+ read -r line || break
+ results $tests $errors $signals
+ set '' $line
+ unit=${2##*/}
+ unit
+ tests=0
+ errors=0
+ signals=0
+ style=script
+ continue
+ ;;
+ 'test heading '*)
+ if (( heading ))
+ then if (( heading > 1 ))
+ then print
+ else heading=2
+ fi
+ set '' $line
+ shift 3
+ print -r -- "==> $* <=="
+ fi
+ continue
+ ;;
+ 'test '*' begins at '????-??-??+??:??:??|'test '*' begins at '*' '*' '*' '*' '*)
+ results $tests $errors $signals
+ unit=${2##*/}
+ unit=${unit%.sh}
+ unit
+ prefix=
+ tests=-1
+ errors=0
+ signals=0
+ style=shell
+ continue
+ ;;
+ 'test '*' at '????-??-??+??:??:??' [ '*' ]'|'test '*' at '*' '*' '*' '*' '*)
+ case $line in
+ *' [ '*test*error*' ]')
+ while :
+ do case $1 in
+ '[') tests=$2
+ errors=$4
+ if (( errors > 256 ))
+ then (( signals++ ))
+ fi
+ break
+ ;;
+ esac
+ shift
+ done
+ ;;
+ *' [ '*test*signal*' ]')
+ while :
+ do case $1 in
+ '[') tests=$2
+ signals=$4
+ if (( signals ))
+ then (( errors++ ))
+ fi
+ break
+ ;;
+ esac
+ shift
+ done
+ ;;
+ *) if [[ $3 != passed ]]
+ then (( errors )) || (( errors++ ))
+ fi
+ ;;
+ esac
+ results $tests $errors $signals
+ continue
+ ;;
+ '## ---'*(-)'--- ##')
+ (( ++lineno > skip )) || continue
+ read -r line || break
+ lower=$line
+ set '' $lower
+ case $lower in
+ '##'*'test suite:'*'##')
+ results $tests $errors $signals
+ set -- ${lower//*suite:}
+ set -- ${*//[.#]/}
+ unit=$*
+ if [[ $unit == *' tests' ]]
+ then unit=${unit/' tests'/}
+ fi
+ main=$unit
+ prefix=
+ tests=0
+ errors=0
+ signals=0
+ category=
+ style=autotest
+ (( skip = lineno + 1 ))
+ unit
+ continue
+ ;;
+ esac
+ ;;
+ +(-)) case $style in
+ regress) continue ;;
+ esac
+ (( ++lineno > skip )) || continue
+ read -r line || break
+ set '' $line
+ case $line in
+ 'Running tests for '*)
+ results $tests $errors $signals
+ shift 4
+ unit=
+ while (( $# ))
+ do if [[ $1 == on ]]
+ then break
+ fi
+ if [[ $unit ]]
+ then unit="$unit "
+ fi
+ unit=$unit${1##*/}
+ shift
+ done
+ main=$unit
+ prefix=
+ tests=-1
+ errors=-1
+ category=
+ style=perl
+ (( skip = lineno + 1 ))
+ continue
+ ;;
+ *' : '*)results $tests $errors $signals
+ unit=${2##*/}
+ unit=${unit%.sh}
+ unit
+ prefix=
+ tests=0
+ errors=0
+ signals=0
+ style=timing
+ (( skip = lineno + 1 ))
+ continue
+ ;;
+ esac
+ ;;
+ +([0-9])*([a-zA-Z0-9])' '*)
+ case $style in
+ script) case $line in
+ *FAILED*|*failed*)
+ (( errors++ ))
+ ;;
+ *) (( tests++ ))
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ make:*|'make ['*']:'*)
+ case $line in
+ *': warning:'*|*'making test'*|*'action'?(s)' failed'*|*': *** '*)
+ ;;
+ *) results $tests $errors $signals
+ print -r -u2 -- "$line"
+ ;;
+ esac
+ continue
+ ;;
+ +([/a-zA-Z_0-9]):)
+ component=${line%:}
+ ;;
+ '') continue
+ ;;
+ esac
+ case $style in
+ autotest)
+ case $line in
+ +([0-9]):*ok)
+ (( tests++ ))
+ ;;
+ +([0-9]):*FAILED*)
+ (( tests++ ))
+ (( errors++ ))
+ if (( $verbose ))
+ then if [[ ! $prefix ]]
+ then prefix=$unit
+ print
+ fi
+ print -r -- " ${line//*'FAILED '/}"
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ perl) case $line in
+ *'........ '*)
+ if [[ $1 == */* ]]
+ then cat=${1%%/*}
+ if [[ $cat != $category ]]
+ then results $tests $errors $signals
+ category=$cat
+ unit="$main $category"
+ unit
+ prefix=
+ tests=0
+ errors=0
+ signals=0
+ fi
+ (( tests++ ))
+ case $line in
+ *' ok') ;;
+ *) (( errors++ ))
+ if (( $verbose ))
+ then if [[ ! $prefix ]]
+ then prefix=$unit
+ print
+ fi
+ print -r -- "$line"
+ fi
+ ;;
+ esac
+ else results $tests $errors $signals
+ case $line in
+ *' ok') errors=0 ;;
+ *) errors=1 ;;
+ esac
+ unit="$main $1"
+ unit
+ if (( $verbose && errors ))
+ then prefix=$unit
+ print
+ shift 2
+ print -r -- "$@"
+ else prefix=
+ fi
+ results $tests $errors $signals
+ tests=-1
+ errors=-1
+ category=
+ fi
+ style=perl
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ case $line in
+ *FAILED*|*failed*)
+ (( errors++ ))
+ ;;
+ *) case $style in
+ regress)case $line in
+ ['<>']*);;
+ *) continue ;;
+ esac
+ ;;
+ script) continue
+ ;;
+ shell) ((errors++ ))
+ ;;
+ timing) (( tests++ ))
+ continue
+ ;;
+ unknown)continue
+ ;;
+ esac
+ ;;
+ esac
+ if (( $verbose ))
+ then if [[ ! $prefix ]]
+ then prefix=$unit
+ print
+ fi
+ print -r -- "$line"
+ fi
+done
+results $tests $errors $signals
diff --git a/src/cmd/INIT/silent.sh b/src/cmd/INIT/silent.sh
new file mode 100644
index 0000000..be99aa6
--- /dev/null
+++ b/src/cmd/INIT/silent.sh
@@ -0,0 +1,42 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+# non-ksh stub for the nmake silent prefix
+# @(#)silent (AT&T Research) 1992-08-11
+
+case $-:$BASH_VERSION in
+*x*:[01234567899]*) : bash set -x is broken :; set +ex ;;
+esac
+
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
diff --git a/src/cmd/INIT/socket.c b/src/cmd/INIT/socket.c
new file mode 100644
index 0000000..51d74eb
--- /dev/null
+++ b/src/cmd/INIT/socket.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lnsl
+ */
+
+#ifndef socket
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+int
+main()
+{
+ return socket(0, 0, 0) < 0;
+}
diff --git a/src/cmd/INIT/w.c b/src/cmd/INIT/w.c
new file mode 100644
index 0000000..0f6bc7d
--- /dev/null
+++ b/src/cmd/INIT/w.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef DONTCARE
+#include <wchar.h>
+#include <wctype.h>
+#endif
+
+int
+main()
+{
+ wchar_t w = ' ';
+ return iswspace(w) == 0;
+}
diff --git a/src/cmd/INIT/w2.c b/src/cmd/INIT/w2.c
new file mode 100644
index 0000000..00efd25
--- /dev/null
+++ b/src/cmd/INIT/w2.c
@@ -0,0 +1,27 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#include <wchar.h>
+
+int
+main()
+{
+ wchar_t w = ' ';
+ return iswspace(w) == 0;
+}
diff --git a/src/cmd/Makefile b/src/cmd/Makefile
new file mode 100644
index 0000000..a046f68
--- /dev/null
+++ b/src/cmd/Makefile
@@ -0,0 +1 @@
+:MAKE:
diff --git a/src/cmd/Mamfile b/src/cmd/Mamfile
new file mode 100644
index 0000000..7b439a5
--- /dev/null
+++ b/src/cmd/Mamfile
@@ -0,0 +1,7 @@
+info mam static
+note component level :MAKE: equivalent
+make install
+make all
+exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+done all virtual
+done install virtual
diff --git a/src/cmd/ksh93/COMPATIBILITY b/src/cmd/ksh93/COMPATIBILITY
new file mode 100644
index 0000000..cf26076
--- /dev/null
+++ b/src/cmd/ksh93/COMPATIBILITY
@@ -0,0 +1,136 @@
+
+ KSH-93 VS. KSH-88
+
+
+The following is a list of known incompatibilities between ksh-93 and ksh-88.
+I have not include cases that are clearly bugs in ksh-88. I also have
+omitted features that are completely upward compatible.
+
+1. Functions, defined with name() with ksh-93 are compatible with
+ the POSIX standard, not with ksh-88. No local variables are
+ permitted, and there is no separate scope. Functions defined
+ with the function name syntax, maintain compatibility.
+ This also affects function traces.
+
+2. ! is now a reserved word. As a result, any command by that
+ name will no longer work with ksh-93.
+
+3. The -x attribute of alias and typeset -f is no longer
+ effective and the ENV file is only read for interactive
+ shells. You need to use FPATH to make function definitions
+ visible to scripts.
+
+4. A built-in command named command has been added which is
+ always found before the PATH search. Any script which uses
+ this name as the name of a command (or function) will not
+ be compatible.
+
+5. The output format for some built-ins has changed. In particular
+ the output format for set, typeset and alias now have single
+ quotes around values that have special characters. The output
+ for trap without arguments has a format that can be used as input.
+
+6. With ksh-88, a dollar sign ($') followed by a single quote was
+ interpreted literally. Now it is an ANSI-C string. You
+ must quote the dollar sign to get the previous behavior.
+ Also, a $ in front of a " indicates that the string needs
+ to be translated for locales other than C or POSIX. The $
+ is ignored in the C and POSIX locale.
+
+7. With ksh-88, tilde expansion did not take place inside ${...}.
+ with ksh-93, ${foo-~} will cause tilde expansion if foo is
+ not set. You need to escape the ~ for the previous behavior.
+
+8. Some changes in the tokenizing rules where made that might
+ cause some scripts with previously ambiguous use of quoting
+ to produce syntax errors.
+
+9. Programs that rely on specific exit values for the shell,
+ (rather than 0 or non-zero) may not be compatible. The
+ exit status for many shell failures has been changed.
+
+10. Built-ins in ksh-88 were always executed before looking for
+ the command in the PATH variable. This is no longer true.
+ Thus, with ksh-93, if you have the current directory first
+ in your PATH, and you have a program named test in your
+ directory, it will be executed when you type test; the
+ built-in version will be run at the point /bin is found
+ in your PATH.
+
+11. Some undocumented combinations of argument passing to ksh
+ builtins no longer works since ksh-93 is getopts conforming
+ with respect to its built-ins. For example, typeset -8i
+ previously would work as a synonym for typeset -i8.
+
+12. Command substitution and arithmetic expansion are now performed
+ on PS1, PS3, and ENV when they are expanded. Thus, ` and $(
+ as part of the value of these variables must be preceded by a \
+ to preserve their previous behavior.
+
+13. The ERRNO variable has been dropped.
+
+14. If the file name following a redirection symbol contain pattern
+ characters they will only be expanded for interactive shells.
+
+15. The arguments to a dot script will be restored when it completes.
+
+16. The list of tracked aliases is not displayed with alias unless
+ the -t option is specified.
+
+17. The POSIX standard requires that test "$arg" have exit status
+ of 0, if and only if $arg is null. However, since this breaks
+ programs that use test -t, ksh-93 treats an explicit test -t
+ as if the user had entered test -t 1.
+
+18. The ^T directive of emacs mode has been changed to work the
+ way it does in gnu-emacs.
+
+19. ksh-88 allowed unbalanced parenthes within ${name op val} whereas
+ ksh-93 does not. Thus, ${foo-(} needs to be written as ${foo-\(}
+ which works with both versions.
+
+20. kill -l in ksh-93 lists only the signal names, not their numerical
+ values.
+
+21. Local variables defined by typeset are statically scoped in
+ ksh-93. In ksh-88 they were dynamically scoped although this
+ behavior was never documented.
+
+22. The value of the variable given to getopts is set to ? when
+ the end-of-options is reached to conform to the POSIX standard.
+
+23. Since the POSIX standard requires that octal constants be
+ recongnized, doing arithmetic on typeset -Z variables can
+ yield different results that with ksh-88. Most of these
+ differences were eliminated in ksh-93o. Starting in ksh-93u+, the
+ let command no longer recognizes octal constants starting with 0
+ for compatibility with ksh-88 unless the option letoctal is on.
+
+24. Starting after ksh-93l, If you run ksh name, where name does
+ not contain a /, the current directory will be searched
+ before doing a path search on name as required by the POSIX
+ shell standard.
+
+25. In ksh-93, cd - will output the directory that it changes
+ to on standard output as required by X/Open. With ksh-88,
+ this only happened for interactive shells.
+
+26. As an undocumented feature of ksh-88, a leading 0 to an
+ assignment of an integer variable caused that variable
+ to be treated as unsigned. This behavior was removed
+ starting in ksh-93p.
+
+27. The getopts builtin in ksh-93 requires that optstring contain
+ a leading + to allow options to begin with a +.
+
+28. In emacs/gmacs mode, control-v will not display the version when
+ the stty lnext character is set to control-v or is unset.
+ The sequence escape control-v will display the shell version.
+
+29. In ksh-88, DEBUG traps were executed. after each command. In ksh-93
+ DEBUG traps are exeucted before each command.
+
+30. In ksh-88, a redirection to a file name given by an empty string was
+ ignored. In ksh-93, this is an error.
+I am interested in expanding this list so please let me know if you
+uncover any others.
diff --git a/src/cmd/ksh93/DESIGN b/src/cmd/ksh93/DESIGN
new file mode 100644
index 0000000..c11c0af
--- /dev/null
+++ b/src/cmd/ksh93/DESIGN
@@ -0,0 +1,170 @@
+Here is an overview of the source code organization for ksh93.
+
+Directory layout:
+
+ The directory include contains header files for ksh93.
+ The files nval.h and shell.h are intended to be public
+ headers and can be used to add runtime builtin command.
+ The remainder are private.
+
+ The directory data contains readonly data files for ksh93.
+ The man pages for built-ins are in builtins.c rather
+ than included as statics with the implementations in the
+ bltins directory because some systems don't make static const
+ data readonly and we want these to be shared by all running
+ shells.
+
+ The directory edit contains the code for command line
+ editing and history.
+
+ The fun directory contains some shell function such as
+ pushd, popd, and dirs.
+
+ The directory features contains files that are used to generate
+ header files in the FEATURE directory. Most of these files
+ are in a format that is processed by iffe.
+
+ The directory bltins contains code for most of the built-in
+ commands. Additional built-in commands are part of libcmd.
+
+ The directory sh contains most of the code for ksh93.
+
+ The directory tests contains a number of regression tests.
+ In most cases, when a bug gets fixed, a test is added to
+ one of these files. The regression tests can be run by
+ going to this directory and running
+ SHELL=shell_path shell_path shtests
+ where shell_path is an absolute pathname for the shell to
+ be tested.
+
+ The top level directory contains the nmake Makefile, a README,
+ and several documentation files. The RELEASE file contains
+ the list of bug fixes and new features since the original
+ ksh93 release. The file COMPATIBILITY is a list of all
+ known incompatibilities with ksh88.
+
+ The bash_pre_rc.sh is a startup script used when emulating
+ bash if the shell is compiled with SHOPT_BASH and the shell
+ is invoked as bash. The bash emulation is not complete.
+
+Include directory:
+ 1. argnod.h contains the type definitions for command
+ nodes, io nodes, argument nodes, and for positional
+ parameters.a It defines the prototypes for
+ all the positional parameters functions.
+ 2. builtins.h contains prototypes for builtins as well
+ as symbolic constants that refer to the name-pairs
+ that are associated with some of the built-ins.
+ It also contains prototypes for many of the strings.
+ 3. defs.h is the catch all for all definitions that
+ don't fit elsewhere and it includes several other
+ headers. It defines a strucuture that contains ksh
+ global data, sh, and a structure that contains per
+ function data, sh.st.
+ 4. edit.h contains definitions that are common to both
+ vi and emacs edit modes.
+ 5. env.h contains interfaces for creating and modifying
+ environment variables.
+ 6. fault.h contains prototypes for signal related
+ functions and trap and fault handling.
+ 7. fcin.h contains macro and function definitions for
+ reading from a file or string.
+ 8. history.h contains macros and functions definitions
+ related to history file processing.
+ 9. jobs.h contains the definitions relating to job
+ processing and control.
+ 10. lexstates.h contains the states associated with
+ lexical processing.
+ 11. name.h contains the internal definitions related
+ to name-value pair processing.
+ 12. national.h contains a few I18N definitions, mostly
+ obsolete.
+ 13. nval.h is the public interface to the name-value
+ pair library that is documented with nval.3.
+ 14. path.h contains the interface for pathname processing
+ and pathname searching.
+ 15. shell.h is the public interface for shell functions
+ that are documented int shell.3.
+ 16. shlex.h contains the lexical token definitions and
+ interfaces for lexical analysis.
+ 17. shnodes.h contains the definition of the structures
+ for each of the parse nodes and flags for the attributes.
+ 18. shtable.h contains some interfaces and functions for
+ table lookup.
+ 19. streval.h contains the interface to the arithmetic
+ functions.
+ 20. terminal.h is a header file that includes the appropriate
+ terminal include.
+ 21. test.h contains the definitions for the test and [[...]]
+ commands.
+ 22. timeout.h contains the define constant for the maximum
+ shell timeout.
+ 23. ulimit.h includes the appropriate resource header.
+ 24. variables.h contains symbolic constants for the built-in
+ shell variables.
+
+sh directory:
+ 1. args.c contains functions for parsing shell options
+ and for processing positional parameters.
+ 2. arith.c contains callback functions for the streval.c
+ library and the interface to shell arithmetic.
+ 3. array.c contains the code for indexed and associative
+ arrays.
+ 4. bash.h contains code used when compiling with SHOPT_BASH
+ to add bash specific features such as shopt.
+ 5. defs.c contains the data definitions for global symbols.
+ 6. deparse.c contains code to generate shell script from
+ a parse tree.
+ 7. env.c contains code to add and delete environment variables
+ to an environment list.
+ 8. expand.c contains code for file name expansion and
+ file name generation.
+ 9. fault.c contains code for signal processing, trap
+ handling and termination.
+ 10. fcin.c contains code for reading and writing a character
+ at a time from a file or string.
+ 11. init.c contains initialization code and callbacks
+ for get and set functions for built-in variables.
+ 12. io.o contains code for redirections and managing file
+ descriptors and file streams.
+ 13. jobs.c contains the code for job management.
+ 14. lex.c contains the code for the lexical analyzer.
+ 15. macro.c contains code for the $ macro expansions, including
+ here-documents.
+ 16. main.c contains the calls to initialization, profile
+ processing and the main evaluation loop as well as
+ mail processing.
+ 17. name.c contains the name-value pair routines that are
+ built on the hash library in libast.
+ 18. nvdisc.c contains code related to name-value pair disciplines.
+ 19. nvtree.c contains code for compound variables and for
+ walking the namespace.
+ 20. nvtype.c contains most of the code related to types that
+ are created with typeset -T.
+ 21. parse.c contains the code for the shell parser.
+ 22. path.c contains the code for pathname lookup and
+ some path functions. It also contains the code
+ that executes commands and scripts.
+ 23. pmain.c is just a calls sh_main() so that all of the
+ rest of the shell can be in a shared library.
+ 24. shcomp.c contains the main program to the shell
+ compiler. This program parses a script and creates
+ a file that the shell can read containing the parse tree.
+ 25. streval.c is an C arithmetic evaluator.
+ 26. string.c contains some string related functions.
+ 27. subshell.c contains the code to save and restore
+ environments so that subshells can run without creating
+ a new process.
+ 28. suid_exec.c contains the program from running execute
+ only and/or setuid/setgid scripts.
+ 29. tdump.c contains the code to dump a parse tree into
+ a file.
+ 30. timers.c contains code for multiple event timeouts.
+ 31. trestore contians the code for restoring the parse
+ tree from the file created by tdump.
+ 32. userinit.c contains a dummy userinit() function.
+ This is now obsolete with the new version of sh_main().
+ 33. waitevent.c contains the sh_waitnotify function so
+ that builtins can handle processing events when the
+ shell is waiting for input or for process completion.
+ 34. xec.c is the main shell executuion loop.
diff --git a/src/cmd/ksh93/Makefile b/src/cmd/ksh93/Makefile
new file mode 100644
index 0000000..3ad44c6
--- /dev/null
+++ b/src/cmd/ksh93/Makefile
@@ -0,0 +1,248 @@
+/*
+ * ksh makefile
+ */
+
+SH := $(PWD:B:/[0-9]*$//:N=ksh*:-ksh) /* name of the shell program */
+VERSION = 1.1
+LICENSE = since=1982,author=dgk
+CATALOG = libshell
+ERROR_CONTEXT_T == Error_context_t /* workaround until switch from errorpush()/errorpop() => errorctx() */
+RELEASE := $(SH:/.*sh//)
+SHCOMP := shcomp$(RELEASE)
+
+/*
+ * set these variables to 1 to enable, 0 to disable, null to probe
+ * override SHOPT_foo=1 can be placed one per line in the build dir Makeargs
+ */
+
+SHOPT_2DMATCH == 1 /* two dimensional .sh.match for ${var//pat/str} */
+SHOPT_ACCT == /* accounting */
+SHOPT_ACCTFILE == /* per user accounting info */
+SHOPT_AUDIT ==
+SHOPT_AUDITFILE == "/etc/ksh_audit" /* auditing file */
+SHOPT_BASH == /* bash compatibility code */
+SHOPT_BGX == 1 /* one SIGCHLD trap per completed job */
+SHOPT_BRACEPAT == 1 /* C-shell {...,...} expansions (, required) */
+SHOPT_CMDLIB_HDR == /* -lcmd builtin list: <cmdlist.h> */
+SHOPT_CMDLIB_DIR == /* SHOPT_CMDLIB_HDR prefix SH_CMDLIB_DIR + <cmdlist.h> */
+SHOPT_COSHELL == 1 /* build with connection to coshell */
+SHOPT_CRNL == /* accept <cr><nl> for <nl> */
+SHOPT_DYNAMIC == 1 /* dynamic loading for builtins */
+SHOPT_ECHOPRINT == /* make echo equivalent to print */
+SHOPT_EDPREDICT == 1 /* predictive editing */
+SHOPT_ESH == 1 /* emacs/gmacs edit mode */
+SHOPT_FILESCAN == 1 /* fast file scan */
+SHOPT_FIXEDARRAY == 1 /* fixed dimension indexed array */
+SHOPT_FS_3D == /* 3d file system */
+SHOPT_HISTEXPAND == 1 /* csh-style history file expansions */
+SHOPT_KIA == 1 /* shell information database generation */
+SHOPT_MULTIBYTE == 1 /* multibyte character handling */
+SHOPT_NAMESPACE == 1 /* allow namespaces */
+SHOPT_OLDTERMIO == /* support both TCGETA and TCGETS */
+SHOPT_OPTIMIZE == 1 /* optimize loop invariants */
+SHOPT_PFSH == 1 /* solaris exec_attr(4) profile execution */
+SHOPT_P_SUID == /* real uid's that require -p for set[ug]id */
+SHOPT_RAWONLY == 1 /* make viraw the only vi mode */
+SHOPT_REGRESS == /* enable __regress__ builtin and instrumented intercepts for testing */
+SHOPT_REMOTE == /* enable --rc if running as a remote shell */
+SHOPT_SEVENBIT == /* strip the eigth bit from characters */
+SHOPT_SPAWN == /* use spawnveg for fork/exec */
+SHOPT_STATS == 1 /* add .sh.stats variable */
+SHOPT_SUID_EXEC == 1 /* allow (safe) suid/sgid shell scripts */
+SHOPT_SYSRC == /* attempt . /etc/ksh.kshrc if interactive */
+SHOPT_TIMEOUT == /* number of seconds for shell timeout */
+SHOPT_TYPEDEF == 1 /* enable typeset type definitions */
+SHOPT_VSH == 1 /* vi edit mode */
+
+if CC.HOSTTYPE == "linux.alpha"
+ /* workaround for "BUG IN DYNAMIC LINKER ld.so" */
+ :PACKAGE: - m:static:noinclude /*noCC.EXPORT.DYNAMIC*/
+end
+
+if CC.HOSTTYPE == "*.s390-64"
+ CC.DLL = $(CC.DLLBIG)
+end
+
+if SHOPT_DYNAMIC && ( "$(CC.DIALECT:N=EXPORT=DLL)" || "$(PACKAGE_OPTIONS:N=optimize-space)" )
+ CCFLAGS += $$(CC.DLL) $$(CC.SUFFIX.DEBUG:+$$(CC.DEBUG))
+ LIBS_req = -lshell$(RELEASE)
+else
+ if VARIANT
+ SHOPT_DYNAMIC = 1
+ else
+ libtype = :static
+ end
+ if SHOPT_DYNAMIC
+ CCLDFLAGS += $$(CC.EXPORT.DYNAMIC)
+ end
+ LIBS_req = +lshell$(RELEASE)
+end
+
+:PACKAGE: ast$(libtype):20100309 coshell:order --clobber=!($(SH))
+
+.SOURCE : edit sh bltins data tests fun
+.SOURCE.h : include
+
+/* documentation files */
+DOCFILES = sh.memo builtins.mm README RELEASE TYPES PROMO.mm COMPATIBILITY \
+ DESIGN OBSOLETE RELEASE93 RELEASE88
+
+KSHELL == 1 /* this is ksh */
+
+SH_CMDLIB_DIR == /* SHOPT_CMDLIB_DIR dir prefix */
+SH_DICT == /* message catalog */
+DEBUG == /* debugging purposes only */
+
+if CC.HOSTTYPE == "win32*"
+ SHOPT_CRNL == 1 /* <cr><nl> is eqivalent to <nl> */
+end
+
+if SHOPT_BASH
+ BASH_HOSTTYPE == "$(CC.HOSTTYPE:S:/\.//)"
+ BASH_MACHTYPE == "$(BASH_HOSTTYPE)-unknown-$(CC.HOSTTYPE:B)"
+end
+
+/* use the following libraries only if they exist */
+LIBS_opt := +ljobs +li
+
+if CC.HOSTTYPE == "sol([89]|[1-9][0-9]).*"
+ LDFLAGS += $(CC.LD.LAZY) $(CC.LD.NORECORD)
+end
+
+if "$(-mam:N=static*)"
+ LIBS_opt += -lsocket -lnsl
+elif CC.HOSTTYPE == "sol?([789]|[1-9][0-9]).*"
+ LIBS_opt += +lsocket -lnsl
+elif CC.HOSTTYPE != "sgi.mips*"
+ LIBS_opt += +lsocket +lnsl
+end
+if CC.HOSTTYPE == "linux.sparc*"
+ /* the linux.sparc linker still has some problems */
+ LIBS_opt += -ldll
+end
+LIBS_opt += -lsecdb
+if CC.HOSTTYPE == "sol.*"
+ LIBS_opt += +lw
+end
+$(LIBS_opt) : .DONTCARE
+
+LDLIBRARIES = $(LIBS_opt)
+
+FILES_opt = /* optional file list enabled by vars above */
+if SHOPT_ESH
+ FILES_opt += emacs.c
+end
+if SHOPT_VSH
+ FILES_opt += vi.c
+end
+if SHOPT_BASH
+ FILES_opt += bash.c bash_pre_rc.c
+ SHOPT_HISTEXPAND == 1
+end
+if SHOPT_HISTEXPAND
+ FILES_opt += hexpand.c
+end
+if SHOPT_DYNAMIC
+ FILES_opt += -ldll
+end
+if SHOPT_X
+ LDFLAGS += -u _XtAppInitialize -L/usr/add-on/X11/lib
+end
+
+:ALL: $(SH) $(SHCOMP) $(SHOPT_SUID_EXEC:+suid_exec) $(SHOPT_BASH:+bash$(RELEASE))
+
+$(SH) :: sh.1 pmain.c $(LIBS_req)
+
+DATAFILES = limits.c msg.c strdata.c testops.c keywords.c options.c \
+ signals.c aliases.c builtins.c variables.c lexstates.c
+
+shell$(RELEASE) $(VERSION) id=shell :LIBRARY: shell.3 nval.3 alarm.c cd_pwd.c cflow.c deparse.c \
+ enum.c getopts.c hist.c misc.c print.c read.c sleep.c trap.c test.c \
+ typeset.c ulimit.c umask.c whence.c main.c nvdisc.c nvtype.c \
+ arith.c args.c array.c completion.c defs.c edit.c expand.c regress.c \
+ fault.c fcin.c history.c init.c io.c jobs.c lex.c macro.c name.c \
+ nvtree.c parse.c path.c string.c streval.c subshell.c tdump.c timers.c \
+ trestore.c waitevent.c xec.c env.c $(DATAFILES) $(FILES_opt) \
+ $(SHOPT_COSHELL:+-lcoshell) -lcmd -last -lm
+
+"sol*.i386*" :NOOPTIMIZE: main.c
+"win32*" :NOOPTIMIZE: strdata.c trestore.c
+
+if CC.HOSTTYPE == "win32*"
+:DLL: $(CC.DEBUG)
+else
+:DLL: $(CC.OPTIMIZE)
+end
+
+:READONLY: $(DATAFILES)
+
+$(INCLUDEDIR) :INSTALLPROTO: nval.h shell.h history.h
+
+LIBCMD = $(.LIB.NAME. cmd:T=F)
+
+if SHOPT_SUID_EXEC && ! "$(RELEASE)"
+suid_exec :: CC.DLL= suid_exec.c +last
+end
+
+$(SHCOMP) :: CC.DLL= SH_DICT='"libshell"' shcomp.c $(LIBS_req)
+
+$(FUNDIR) :INSTALLDIR: mode=+x dirs popd pushd
+
+shcomp.o : _BLD_DLL= $(CC.HOSTTYPE:N=cygwin.*:??_BLD_shell=?)
+
+if SHOPT_BASH
+
+bash$(RELEASE) :LINK: $(SH)
+
+bash_pre_rc.c : bash_pre_rc.sh
+ echo "const char bash_pre_rc[] = " > $(<)
+ sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/'"'"'/\\'"'"'/g' -e 's/^[[:space:]]*\(.*\)$/\"\1\\n\"/' $(*) >> $(<)
+ echo ";" >> $(<)
+
+end
+
+:: math.tab syscall.s mamexec mamstate.c $(DOCFILES) \
+ bash.c bash_pre_rc.sh hexpand.c mkservice.c \
+ shopen.mk shopen.c
+
+:: shtests \
+ alias.sh append.sh arith.sh arrays.sh arrays2.sh \
+ attributes.sh basic.sh bracket.sh builtins.sh case.sh \
+ comvar.sh comvario.sh coprocess.sh cubetype.sh enum.sh exit.sh \
+ expand.sh functions.sh glob.sh grep.sh heredoc.sh io.sh \
+ leaks.sh locale.sh math.sh nameref.sh options.sh path.sh \
+ pointtype.sh pty.sh quoting.sh quoting2.sh readcsv.sh recttype.sh \
+ restricted.sh return.sh select.sh shtests sigchld.sh \
+ signal.sh statics.sh subshell.sh substring.sh tilde.sh \
+ timetype.sh treemove.sh types.sh variables.sh \
+ vartree1.sh vartree2.sh
+
+:: ksh-regress.rt ksh-regress.tst
+
+if "$(PWD:B:N=cc-*)"
+
+test : .NULL
+
+else
+
+test : test.ksh
+
+test.ksh : $(BINDIR)/$(SH) $(SH) shtests
+ $(SILENT) $(CMP) $(CMPFLAGS) $(*:O=1) $(*:O=2) 2>/dev/null ||
+ echo "make install to run the tests on the latest $(SH)" >&2
+ cd $(*:O=3:P=L!:D)
+ SHELL=$(*:O=1:P=A) $(*:O=1:P=A) $(*:O=3:B) $(SHTESTSFLAGS)
+
+test.% : %.sh COSHELL_OPTIONS=separate $(BINDIR)/$(SH) $(SH) shtests
+ $(SILENT) $(CMP) $(CMPFLAGS) $(*:O=2) $(*:O=3) 2>/dev/null ||
+ echo "make install to run the tests on the latest $(SH)" >&2
+ cd $(*:O=4:P=L!:D)
+ SHELL=$(*:O=2:P=A) $(*:O=2:P=A) $(*:O=4:B) $(SHTESTSFLAGS) $(*:O=1:P=A)
+
+if RELEASE
+
+.INSTALL : .CLEAR $(*.INSTALL:N=*$(RELEASE)*([!/]))
+
+end
+
+end
diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile
new file mode 100644
index 0000000..5a55040
--- /dev/null
+++ b/src/cmd/ksh93/Mamfile
@@ -0,0 +1,1527 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGE_ast_INCLUDE ${INSTALLROOT}/include/ast
+setv PACKAGE_ast_LIB ${INSTALLROOT}/lib
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make ksh
+make pmain.o
+make sh/pmain.c
+make FEATURE/externs implicit
+meta FEATURE/externs features/%>FEATURE/% features/externs externs
+make features/externs
+done features/externs
+exec - set -
+exec - echo 'int main(){return 0;}' > 1.${COTEMP}.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c 1.${COTEMP}.c &&
+exec - x=`${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l'*' 2>&1 | sed -e 's/[][()+@?]/#/g' || :` &&
+exec - {
+exec - case "" in
+exec - *?) echo " " ;;
+exec - esac
+exec - for i in shell dll coshell cmd ast m jobs i socket nsl secdb
+exec - do case $i in
+exec - "shell"|shell)
+exec - ;;
+exec - *) if test -f ${INSTALLROOT}/lib/lib/$i
+exec - then y=`cat ${INSTALLROOT}/lib/lib/$i`
+exec - case $y in
+exec - *-?*) echo "" $y ;;
+exec - esac
+exec - continue
+exec - elif test ! -f ${INSTALLROOT}/lib/lib$i.a
+exec - then case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -L${INSTALLROOT}/lib ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) continue ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - echo " -l$i"
+exec - done
+exec - } > shell.req
+exec - rm -f 1.${COTEMP}.*
+bind -ldll
+bind -lcoshell
+bind -lcmd
+bind -last
+bind -lm dontcare
+bind -lnsl dontcare
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/externs
+done FEATURE/externs generated
+make include/shell.h implicit
+make ${PACKAGE_ast_INCLUDE}/cmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/dlldefs.h implicit
+done ${PACKAGE_ast_INCLUDE}/dlldefs.h dontcare
+make ${PACKAGE_ast_INCLUDE}/cmdext.h implicit
+make ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+make ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/shcmd.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/cmdext.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/stak.h implicit
+make ${PACKAGE_ast_INCLUDE}/stk.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio_s.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
+make ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/bytesex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/bytesex.h dontcare
+done ${PACKAGE_ast_INCLUDE}/endian.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_common.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+make ${PACKAGE_ast_INCLUDE}/regex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wctype.h dontcare
+done ${PACKAGE_ast_INCLUDE}/wctype.h dontcare
+make ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_stdio.h dontcare
+done ${PACKAGE_ast_INCLUDE}/stdio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wchar.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/regex.h dontcare
+make ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_botch.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_botch.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_limits.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_limits.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_fcntl.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_fs.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_fcntl.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_sys.h implicit
+prev ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_sys.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_lib.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_std.h dontcare
+done ${PACKAGE_ast_INCLUDE}/sfio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/stk.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/stak.h dontcare
+make ${PACKAGE_ast_INCLUDE}/error.h implicit
+make ${PACKAGE_ast_INCLUDE}/option.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_api.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_api.h dontcare
+make ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/vmalloc.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/option.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/error.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/cmd.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/option.h implicit
+make ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/cdt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/nval.h dontcare
+make include/name.h implicit
+prev include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/name.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/shell.h
+done sh/pmain.c
+meta pmain.o %.c>%.o sh/pmain.c pmain
+prev sh/pmain.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -c sh/pmain.c
+done pmain.o generated
+make libshell.a archive
+prev shell.req
+make alarm.o
+make bltins/alarm.c
+make FEATURE/time implicit
+meta FEATURE/time features/%>FEATURE/% features/time time
+make features/time
+done features/time
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time
+make ${PACKAGE_ast_INCLUDE}/times.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_time.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_time.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/times.h dontcare
+done FEATURE/time generated
+make include/builtins.h implicit
+make include/shtable.h implicit
+done include/shtable.h dontcare
+make FEATURE/dynamic implicit
+meta FEATURE/dynamic features/%>FEATURE/% features/dynamic dynamic
+make features/dynamic
+done features/dynamic
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/dynamic
+make ${PACKAGE_ast_INCLUDE}/fs3d.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fs3d.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/dlldefs.h implicit
+done FEATURE/dynamic dontcare generated
+make FEATURE/options implicit
+meta FEATURE/options features/%>FEATURE/% features/options options
+make features/options
+done features/options
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/options
+done FEATURE/options dontcare generated
+prev ${PACKAGE_ast_INCLUDE}/option.h implicit
+done include/builtins.h
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+make include/defs.h implicit
+make include/regress.h implicit
+done include/regress.h dontcare
+prev include/shtable.h implicit
+prev include/shell.h implicit
+make include/env.h implicit
+done include/env.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev include/name.h implicit
+make include/argnod.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+done include/argnod.h dontcare
+make include/fault.h implicit
+make FEATURE/sigfeatures implicit
+meta FEATURE/sigfeatures features/%>FEATURE/% features/sigfeatures sigfeatures
+make features/sigfeatures
+done features/sigfeatures
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/sigfeatures
+done FEATURE/sigfeatures dontcare generated
+make FEATURE/setjmp implicit
+meta FEATURE/setjmp features/%>FEATURE/% features/setjmp setjmp
+make features/setjmp
+done features/setjmp
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/setjmp
+done FEATURE/setjmp dontcare generated
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+make ${PACKAGE_ast_INCLUDE}/sig.h implicit
+done ${PACKAGE_ast_INCLUDE}/sig.h dontcare
+done include/fault.h dontcare
+make include/history.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/history.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev FEATURE/options implicit
+prev FEATURE/externs implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/defs.h
+done bltins/alarm.c
+meta alarm.o %.c>%.o bltins/alarm.c alarm
+prev bltins/alarm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/alarm.c
+done alarm.o generated
+make cd_pwd.o
+make bltins/cd_pwd.c
+make ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_mode.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ls.h
+prev include/builtins.h implicit
+prev include/name.h implicit
+make include/path.h implicit
+make FEATURE/acct implicit
+meta FEATURE/acct >FEATURE/% acct
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : def acct
+done FEATURE/acct dontcare generated
+prev include/defs.h implicit
+prev include/nval.h implicit
+prev FEATURE/options implicit
+done include/path.h
+make include/variables.h implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/option.h implicit
+done include/variables.h
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done bltins/cd_pwd.c
+meta cd_pwd.o %.c>%.o bltins/cd_pwd.c cd_pwd
+prev bltins/cd_pwd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c bltins/cd_pwd.c
+done cd_pwd.o generated
+make cflow.o
+make bltins/cflow.c
+prev include/builtins.h implicit
+make include/shnodes.h implicit
+prev include/argnod.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/shnodes.h
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev include/defs.h implicit
+done bltins/cflow.c
+meta cflow.o %.c>%.o bltins/cflow.c cflow
+prev bltins/cflow.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/cflow.c
+done cflow.o generated
+make deparse.o
+make sh/deparse.c
+make include/test.h implicit
+prev include/shtable.h implicit
+prev include/defs.h implicit
+prev FEATURE/options implicit
+done include/test.h
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+done sh/deparse.c
+meta deparse.o %.c>%.o sh/deparse.c deparse
+prev sh/deparse.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/deparse.c
+done deparse.o generated
+make enum.o
+make bltins/enum.c
+prev include/shell.h implicit
+done bltins/enum.c
+meta enum.o %.c>%.o bltins/enum.c enum
+prev bltins/enum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -Iinclude -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libshell"\" -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -c bltins/enum.c
+done enum.o generated
+make getopts.o
+make bltins/getopts.c
+prev include/builtins.h implicit
+prev include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done bltins/getopts.c
+meta getopts.o %.c>%.o bltins/getopts.c getopts
+prev bltins/getopts.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/getopts.c
+done getopts.o generated
+make hist.o
+make bltins/hist.c
+make include/edit.h implicit
+make include/national.h implicit
+done include/national.h dontcare
+make include/terminal.h implicit
+make FEATURE/ttys implicit
+meta FEATURE/ttys features/%>FEATURE/% features/ttys ttys
+make features/ttys
+done features/ttys
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/ttys
+done FEATURE/ttys dontcare generated
+done include/terminal.h dontcare
+prev FEATURE/setjmp implicit
+prev ${PACKAGE_ast_INCLUDE}/sig.h implicit
+make FEATURE/locale implicit
+meta FEATURE/locale features/%>FEATURE/% features/locale locale
+make features/locale
+done features/locale
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale
+done FEATURE/locale dontcare generated
+prev FEATURE/options implicit
+done include/edit.h dontcare
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+make include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/io.h
+prev include/variables.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done bltins/hist.c
+meta hist.o %.c>%.o bltins/hist.c hist
+prev bltins/hist.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -D_BLD_shell -DSHOPT_DYNAMIC -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -c bltins/hist.c
+done hist.o generated
+make misc.o
+make bltins/misc.c
+make include/jobs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev include/terminal.h implicit
+make ${PACKAGE_ast_INCLUDE}/coshell.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/coshell.h dontcare
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/jobs.h
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done bltins/misc.c
+meta misc.o %.c>%.o bltins/misc.c misc
+prev bltins/misc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -DSHOPT_BGX -D_API_ast=20100309 -DSHOPT_COSHELL -DSHOPT_MULTIBYTE -DSHOPT_PFSH -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_ESH -DSHOPT_FIXEDARRAY -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -c bltins/misc.c
+done misc.o generated
+make print.o
+make bltins/print.c
+make ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_ccode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_ccode.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ccode.h
+make ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+make ${PACKAGE_ast_INCLUDE}/tv.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done ${PACKAGE_ast_INCLUDE}/tv.h dontcare
+make ${PACKAGE_ast_INCLUDE}/tm.h implicit
+prev ${PACKAGE_ast_INCLUDE}/times.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/tm.h dontcare
+done ${PACKAGE_ast_INCLUDE}/tmx.h
+make include/streval.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_float.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_float.h dontcare
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/streval.h
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/print.c
+meta print.o %.c>%.o bltins/print.c print
+prev bltins/print.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DKSHELL -c bltins/print.c
+done print.o generated
+make read.o
+make bltins/read.c
+prev include/edit.h implicit
+prev include/terminal.h implicit
+prev include/history.h implicit
+prev include/builtins.h implicit
+prev include/name.h implicit
+prev include/io.h implicit
+make include/lexstates.h implicit
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/wchar.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+done ${PACKAGE_ast_INCLUDE}/wchar.h dontcare
+prev FEATURE/locale implicit
+done include/lexstates.h
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done bltins/read.c
+meta read.o %.c>%.o bltins/read.c read
+prev bltins/read.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_FIXEDARRAY -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DERROR_CONTEXT_T=Error_context_t -c bltins/read.c
+done read.o generated
+make sleep.o
+make bltins/sleep.c
+make FEATURE/poll implicit
+meta FEATURE/poll features/%>FEATURE/% features/poll poll
+make features/poll
+done features/poll
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/poll
+done FEATURE/poll generated
+prev FEATURE/time implicit
+prev include/builtins.h implicit
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/sleep.c
+meta sleep.o %.c>%.o bltins/sleep.c sleep
+prev bltins/sleep.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/sleep.c
+done sleep.o generated
+make trap.o
+make bltins/trap.c
+prev include/builtins.h implicit
+prev include/jobs.h implicit
+prev include/defs.h implicit
+done bltins/trap.c
+meta trap.o %.c>%.o bltins/trap.c trap
+prev bltins/trap.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_BGX -DSHOPT_COSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/trap.c
+done trap.o generated
+make test.o
+make bltins/test.c
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev FEATURE/poll implicit
+prev FEATURE/externs implicit
+prev include/builtins.h implicit
+prev include/test.h implicit
+prev include/terminal.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/test.c
+meta test.o %.c>%.o bltins/test.c test
+prev bltins/test.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DKSHELL -c bltins/test.c
+done test.o generated
+make typeset.o
+make bltins/typeset.c
+prev FEATURE/dynamic implicit
+prev include/variables.h implicit
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+prev include/path.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/typeset.c
+meta typeset.o %.c>%.o bltins/typeset.c typeset
+prev bltins/typeset.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FIXEDARRAY -DSHOPT_DYNAMIC -DSHOPT_NAMESPACE -DSHOPT_TYPEDEF -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_ESH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -c bltins/typeset.c
+done typeset.o generated
+make ulimit.o
+make bltins/ulimit.c
+make include/ulimit.h implicit
+make FEATURE/rlimits implicit
+meta FEATURE/rlimits features/%>FEATURE/% features/rlimits rlimits
+make features/rlimits
+done features/rlimits
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/rlimits
+done FEATURE/rlimits dontcare generated
+prev FEATURE/time implicit
+done include/ulimit.h
+prev include/name.h implicit
+prev include/builtins.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done bltins/ulimit.c
+meta ulimit.o %.c>%.o bltins/ulimit.c ulimit
+prev bltins/ulimit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_FIXEDARRAY -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c bltins/ulimit.c
+done ulimit.o generated
+make umask.o
+make bltins/umask.c
+prev include/builtins.h implicit
+prev include/shell.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done bltins/umask.c
+meta umask.o %.c>%.o bltins/umask.c umask
+prev bltins/umask.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c bltins/umask.c
+done umask.o generated
+make whence.o
+make bltins/whence.c
+prev include/builtins.h implicit
+make include/shlex.h implicit
+prev include/lexstates.h implicit
+prev include/shtable.h implicit
+prev include/shnodes.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+done include/shlex.h
+prev include/path.h implicit
+prev include/name.h implicit
+prev include/shtable.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/whence.c
+meta whence.o %.c>%.o bltins/whence.c whence
+prev bltins/whence.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_KIA -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/whence.c
+done whence.o generated
+make main.o
+make sh/main.c
+make execargs.h implicit
+done execargs.h dontcare virtual
+make ${PACKAGE_ast_INCLUDE}/fts.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fts.h dontcare
+make nc.h implicit
+done nc.h dontcare virtual
+prev FEATURE/externs implicit
+make FEATURE/execargs implicit
+meta FEATURE/execargs >FEATURE/% execargs
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : def execargs
+done FEATURE/execargs generated
+make FEATURE/pstat implicit
+meta FEATURE/pstat >FEATURE/% pstat
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : def pstat
+done FEATURE/pstat generated
+prev FEATURE/time implicit
+make include/timeout.h implicit
+done include/timeout.h
+prev include/history.h implicit
+prev include/shnodes.h implicit
+prev include/shlex.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+make include/fcin.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+done include/fcin.h
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/main.c
+meta main.o %.c>%.o sh/main.c main
+prev sh/main.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${DEBUG+-DDEBUG=${DEBUG}} ${SHOPT_TIMEOUT+-DSHOPT_TIMEOUT=${SHOPT_TIMEOUT}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SHOPT_REMOTE+-DSHOPT_REMOTE=${SHOPT_REMOTE}} ${SHOPT_OLDTERMIO+-DSHOPT_OLDTERMIO=${SHOPT_OLDTERMIO}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} ${SHOPT_FS_3D+-DSHOPT_FS_3D=${SHOPT_FS_3D}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_ESH -D_BLD_shell -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_BGX -DSHOPT_COSHELL -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/main.c
+done main.o generated
+make nvdisc.o
+make sh/nvdisc.c
+prev include/path.h implicit
+prev include/builtins.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done sh/nvdisc.c
+meta nvdisc.o %.c>%.o sh/nvdisc.c nvdisc
+prev sh/nvdisc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_TYPEDEF -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -D_BLD_shell -DSHOPT_STATS -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/nvdisc.c
+done nvdisc.o generated
+make nvtype.o
+make sh/nvtype.c
+prev include/variables.h implicit
+prev include/io.h implicit
+prev include/defs.h implicit
+done sh/nvtype.c
+meta nvtype.o %.c>%.o sh/nvtype.c nvtype
+prev sh/nvtype.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_FIXEDARRAY -DSHOPT_NAMESPACE -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DKSHELL -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c sh/nvtype.c
+done nvtype.o generated
+make arith.o
+make sh/arith.c
+prev include/builtins.h implicit
+prev include/variables.h implicit
+prev include/streval.h implicit
+prev include/name.h implicit
+prev include/lexstates.h implicit
+prev include/defs.h implicit
+done sh/arith.c
+meta arith.o %.c>%.o sh/arith.c arith
+prev sh/arith.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FIXEDARRAY -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c sh/arith.c
+done arith.o generated
+make args.o
+make sh/args.c
+prev include/io.h implicit
+prev include/shlex.h implicit
+prev FEATURE/poll implicit
+prev include/edit.h implicit
+prev include/terminal.h implicit
+prev include/builtins.h implicit
+prev include/path.h implicit
+prev include/defs.h implicit
+done sh/args.c
+meta args.o %.c>%.o sh/args.c args
+prev sh/args.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_RAWONLY -DSHOPT_HISTEXPAND -DSHOPT_PFSH -D_BLD_shell -DKSHELL -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_EDPREDICT -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_DYNAMIC -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/args.c
+done args.o generated
+make array.o
+make sh/array.c
+prev include/name.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done sh/array.c
+meta array.o %.c>%.o sh/array.c array
+prev sh/array.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_FIXEDARRAY -D_BLD_shell -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/array.c
+done array.o generated
+make completion.o
+make edit/completion.c
+prev include/history.h implicit
+prev include/edit.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/lexstates.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+prev include/defs.h implicit
+done edit/completion.c
+meta completion.o %.c>%.o edit/completion.c completion
+prev edit/completion.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -DSHOPT_ESH -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DKSHELL -DSHOPT_VSH -DSHOPT_PFSH -D_BLD_shell -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/completion.c
+done completion.o generated
+make defs.o
+make sh/defs.c
+prev include/timeout.h implicit
+prev include/edit.h implicit
+prev include/shlex.h implicit
+prev include/jobs.h implicit
+prev include/defs.h implicit
+done sh/defs.c
+meta defs.o %.c>%.o sh/defs.c defs
+prev sh/defs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_KIA -D_BLD_shell -D_API_ast=20100309 -DSHOPT_BGX -DSHOPT_COSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/defs.c
+done defs.o generated
+make edit.o
+make edit/edit.c
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/terminal.h implicit
+prev include/io.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make FEATURE/cmds implicit
+meta FEATURE/cmds features/%>FEATURE/% features/cmds cmds
+make features/cmds
+done features/cmds
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/cmds
+done FEATURE/cmds generated
+prev FEATURE/time implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done edit/edit.c
+meta edit.o %.c>%.o edit/edit.c edit
+prev edit/edit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_EDPREDICT -DSHOPT_RAWONLY -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_MULTIBYTE -DSHOPT_HISTEXPAND -DKSHELL -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/edit.c
+done edit.o generated
+make expand.o
+make sh/expand.c
+prev include/path.h implicit
+prev include/io.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_dir.h implicit
+make ${PACKAGE_ast_INCLUDE}/dirent.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_dirent.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_dirent.h dontcare
+done ${PACKAGE_ast_INCLUDE}/dirent.h dontcare
+make dirlib.h implicit
+done dirlib.h dontcare virtual
+prev ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_dir.h
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make ${PACKAGE_ast_INCLUDE}/glob.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/glob.h
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev include/test.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done sh/expand.c
+meta expand.o %.c>%.o sh/expand.c expand
+prev sh/expand.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DSHOPT_SUID_EXEC -DSHOPT_PFSH -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DKSHELL -c sh/expand.c
+done expand.o generated
+make regress.o
+make bltins/regress.c
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev include/builtins.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/regress.c
+meta regress.o %.c>%.o bltins/regress.c regress
+prev bltins/regress.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DKSHELL -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/regress.c
+done regress.o generated
+make fault.o
+make sh/fault.c
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev include/ulimit.h implicit
+prev include/builtins.h implicit
+prev include/path.h implicit
+prev include/jobs.h implicit
+prev include/variables.h implicit
+prev include/shlex.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/fault.c
+meta fault.o %.c>%.o sh/fault.c fault
+prev sh/fault.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_KIA -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_TYPEDEF -DSHOPT_BGX -D_PACKAGE_ast -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DKSHELL -c sh/fault.c
+done fault.o generated
+make fcin.o
+make sh/fcin.c
+prev include/fcin.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/fcin.c
+meta fcin.o %.c>%.o sh/fcin.c fcin
+prev sh/fcin.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -c sh/fcin.c
+done fcin.o generated
+make history.o
+make edit/history.c
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev include/builtins.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev FEATURE/time implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done edit/history.c
+meta history.o %.c>%.o edit/history.c history
+prev edit/history.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_VSH -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_AUDITFILE=\""/etc/ksh_audit"\" -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DKSHELL -DSHOPT_DYNAMIC -DSHOPT_PFSH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/history.c
+done history.o generated
+make init.o
+make sh/init.c
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make include/version.h implicit
+done include/version.h
+prev include/lexstates.h implicit
+prev FEATURE/externs implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/time implicit
+prev include/builtins.h implicit
+prev include/shlex.h implicit
+prev include/io.h implicit
+prev include/jobs.h implicit
+prev include/edit.h implicit
+prev include/name.h implicit
+prev include/fault.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done sh/init.c
+meta init.o %.c>%.o sh/init.c init
+prev sh/init.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_2DMATCH -DSHOPT_PFSH -DSHOPT_MULTIBYTE -DSHOPT_BGX -DSHOPT_COSHELL -D_PACKAGE_ast -DSHOPT_DYNAMIC -D_API_ast=20100309 -D_BLD_shell -DSHOPT_KIA -DKSHELL -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_FIXEDARRAY -DERROR_CONTEXT_T=Error_context_t -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -c sh/init.c
+done init.o generated
+make io.o
+make sh/io.c
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev FEATURE/poll implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/externs implicit
+prev include/timeout.h implicit
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/shnodes.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev ${PACKAGE_ast_INCLUDE}/regex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/io.c
+meta io.o %.c>%.o sh/io.c io
+prev sh/io.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_RAWONLY -DSHOPT_VSH -DSHOPT_ESH -DSHOPT_HISTEXPAND -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_BGX -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/io.c
+done io.o generated
+make jobs.o
+make sh/jobs.c
+prev include/history.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+make ${PACKAGE_ast_INCLUDE}/wait.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wait.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wait.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/wait.h
+prev include/defs.h implicit
+done sh/jobs.c
+meta jobs.o %.c>%.o sh/jobs.c jobs
+prev sh/jobs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_VSH -DSHOPT_COSHELL -DSHOPT_BGX -DSHOPT_ESH -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_MULTIBYTE -DSHOPT_PFSH -D_BLD_shell -DKSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/jobs.c
+done jobs.o generated
+make lex.o
+make sh/lex.c
+prev include/shlex.h implicit
+prev include/io.h implicit
+prev include/lexstates.h implicit
+prev include/test.h implicit
+prev include/argnod.h implicit
+prev include/shell.h implicit
+prev include/defs.h implicit
+prev FEATURE/options implicit
+prev include/nval.h implicit
+prev include/fcin.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/lex.c
+meta lex.o %.c>%.o sh/lex.c lex
+prev sh/lex.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_MULTIBYTE -DSHOPT_KIA -D_PACKAGE_ast -D_BLD_shell -D_API_ast=20100309 -DSHOPT_PFSH -DKSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c sh/lex.c
+done lex.o generated
+make macro.o
+make sh/macro.c
+prev include/streval.h implicit
+prev include/national.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/shlex.h implicit
+prev include/variables.h implicit
+prev include/name.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/macro.c
+meta macro.o %.c>%.o sh/macro.c macro
+prev sh/macro.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DKSHELL -DSHOPT_COSHELL -DSHOPT_OPTIMIZE -DSHOPT_FIXEDARRAY -DSHOPT_TYPEDEF -DSHOPT_FILESCAN -DSHOPT_MULTIBYTE -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_ESH -DSHOPT_SUID_EXEC -DSHOPT_BGX -DSHOPT_KIA -c sh/macro.c
+done macro.o generated
+make name.o
+make sh/name.c
+prev include/builtins.h implicit
+prev include/shnodes.h implicit
+prev include/streval.h implicit
+prev FEATURE/externs implicit
+prev include/timeout.h implicit
+prev include/lexstates.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done sh/name.c
+meta name.o %.c>%.o sh/name.c name
+prev sh/name.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_FIXEDARRAY -DSHOPT_NAMESPACE -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_TYPEDEF -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -c sh/name.c
+done name.o generated
+make nvtree.o
+make sh/nvtree.c
+prev include/lexstates.h implicit
+prev include/argnod.h implicit
+prev include/name.h implicit
+prev include/defs.h implicit
+done sh/nvtree.c
+meta nvtree.o %.c>%.o sh/nvtree.c nvtree
+prev sh/nvtree.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FIXEDARRAY -DSHOPT_MULTIBYTE -D_PACKAGE_ast -D_BLD_shell -D_API_ast=20100309 -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c sh/nvtree.c
+done nvtree.o generated
+make parse.o
+make sh/parse.c
+prev include/path.h implicit
+prev include/test.h implicit
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/shlex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/fcin.h implicit
+prev include/shell.h implicit
+prev include/defs.h implicit
+done sh/parse.c
+meta parse.o %.c>%.o sh/parse.c parse
+prev sh/parse.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -D_BLD_shell -DSHOPT_STATS -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_KIA -DKSHELL -c sh/parse.c
+done parse.o generated
+make path.o
+make sh/path.c
+prev FEATURE/time implicit
+make ${PACKAGE_ast_INCLUDE}/ast_vfork.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_vfork.h dontcare
+make exec_attr.h implicit
+done exec_attr.h dontcare virtual
+prev FEATURE/externs implicit
+prev FEATURE/dynamic implicit
+prev include/test.h implicit
+prev include/history.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/path.c
+meta path.o %.c>%.o sh/path.c path
+prev sh/path.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_SUID_EXEC -DSHOPT_NAMESPACE -DSHOPT_DYNAMIC -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_BGX -DKSHELL -DSHOPT_BRACEPAT -c sh/path.c
+done path.o generated
+make string.o
+make sh/string.c
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+prev include/national.h implicit
+prev include/lexstates.h implicit
+prev include/shtable.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/string.c
+meta string.o %.c>%.o sh/string.c string
+prev sh/string.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c sh/string.c
+done string.o generated
+make streval.o
+make sh/streval.c
+prev include/defs.h implicit
+prev FEATURE/externs implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/streval.h implicit
+done sh/streval.c
+meta streval.o %.c>%.o sh/streval.c streval
+prev sh/streval.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/streval.c
+done streval.o generated
+make subshell.o
+make sh/subshell.c
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/jobs.h implicit
+prev include/shlex.h implicit
+prev include/shnodes.h implicit
+prev include/fault.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev include/defs.h implicit
+done sh/subshell.c
+meta subshell.o %.c>%.o sh/subshell.c subshell
+prev sh/subshell.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_COSHELL -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_BGX -DSHOPT_KIA -DKSHELL -c sh/subshell.c
+done subshell.o generated
+make tdump.o
+make sh/tdump.c
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+done sh/tdump.c
+meta tdump.o %.c>%.o sh/tdump.c tdump
+prev sh/tdump.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DKSHELL -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/tdump.c
+done tdump.o generated
+make timers.o
+make sh/timers.c
+prev FEATURE/time implicit
+prev FEATURE/sigfeatures implicit
+prev include/defs.h implicit
+prev include/fault.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sig.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/timers.c
+meta timers.o %.c>%.o sh/timers.c timers
+prev sh/timers.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/timers.c
+done timers.o generated
+make trestore.o
+make sh/trestore.c
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+done sh/trestore.c
+meta trestore.o %.c>%.o sh/trestore.c trestore
+prev sh/trestore.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DKSHELL -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/trestore.c
+done trestore.o generated
+make waitevent.o
+make sh/waitevent.c
+prev include/defs.h implicit
+done sh/waitevent.c
+meta waitevent.o %.c>%.o sh/waitevent.c waitevent
+prev sh/waitevent.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/waitevent.c
+done waitevent.o generated
+make xec.o
+make sh/xec.c
+prev ${PACKAGE_ast_INCLUDE}/ast_vfork.h implicit
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev include/streval.h implicit
+prev FEATURE/locale implicit
+prev FEATURE/externs implicit
+prev FEATURE/time implicit
+prev include/builtins.h implicit
+prev include/test.h implicit
+prev include/jobs.h implicit
+prev include/shnodes.h implicit
+prev include/io.h implicit
+prev include/name.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/xec.c
+meta xec.o %.c>%.o sh/xec.c xec
+prev sh/xec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FILESCAN -DSHOPT_BGX -DSHOPT_TYPEDEF -DSHOPT_PFSH -DSHOPT_COSHELL -DSHOPT_NAMESPACE -DSHOPT_OPTIMIZE -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -c sh/xec.c
+done xec.o generated
+make env.o
+make sh/env.c
+prev include/env.h implicit
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/env.c
+meta env.o %.c>%.o sh/env.c env
+prev sh/env.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -Iinclude -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_API_ast=20100309 -c sh/env.c
+done env.o generated
+make limits.o
+make data/limits.c
+prev include/ulimit.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/limits.c
+meta limits.o %.c>%.o data/limits.c limits
+prev data/limits.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -c data/limits.c
+done limits.o generated
+make msg.o
+make data/msg.c
+prev FEATURE/cmds implicit
+prev include/edit.h implicit
+prev include/jobs.h implicit
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/timeout.h implicit
+prev include/shlex.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/msg.c
+meta msg.o %.c>%.o data/msg.c msg
+prev data/msg.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_SUID_EXEC -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_BGX -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_KIA -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c data/msg.c
+done msg.o generated
+make strdata.o
+make data/strdata.c
+make FEATURE/math implicit
+meta FEATURE/math features/%.sh>FEATURE/% features/math.sh math
+make features/math.sh
+make data/math.tab implicit
+done data/math.tab
+done features/math.sh dontcare
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/math.sh data/math.tab
+make ${PACKAGE_ast_INCLUDE}/ast_standards.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_standards.h dontcare
+done FEATURE/math generated
+prev include/streval.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_standards.h implicit
+done data/strdata.c
+meta strdata.o %.c>%.o data/strdata.c strdata
+prev data/strdata.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/strdata.c
+done strdata.o generated
+make testops.o
+make data/testops.c
+prev include/test.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/testops.c
+meta testops.o %.c>%.o data/testops.c testops
+prev data/testops.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/testops.c
+done testops.o generated
+make keywords.o
+make data/keywords.c
+prev FEATURE/options implicit
+prev include/shlex.h implicit
+prev include/shell.h implicit
+done data/keywords.c
+meta keywords.o %.c>%.o data/keywords.c keywords
+prev data/keywords.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_KIA -D_BLD_shell -D_API_ast=20100309 -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c data/keywords.c
+done keywords.o generated
+make options.o
+make data/options.c
+prev include/shtable.h implicit
+prev include/name.h implicit
+prev include/defs.h implicit
+done data/options.c
+meta options.o %.c>%.o data/options.c options
+prev data/options.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -D_BLD_shell -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/options.c
+done options.o generated
+make signals.o
+make data/signals.c
+prev include/defs.h implicit
+done data/signals.c
+meta signals.o %.c>%.o data/signals.c signals
+prev data/signals.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/signals.c
+done signals.o generated
+make aliases.o
+make data/aliases.c
+prev FEATURE/dynamic implicit
+prev FEATURE/options implicit
+prev include/defs.h implicit
+done data/aliases.c
+meta aliases.o %.c>%.o data/aliases.c aliases
+prev data/aliases.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c data/aliases.c
+done aliases.o generated
+make builtins.o
+make data/builtins.c
+prev FEATURE/cmds implicit
+prev include/jobs.h implicit
+prev include/builtins.h implicit
+prev include/version.h implicit
+prev include/name.h implicit
+prev include/ulimit.h implicit
+prev include/shtable.h implicit
+prev include/defs.h implicit
+done data/builtins.c
+meta builtins.o %.c>%.o data/builtins.c builtins
+prev data/builtins.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_KIA -DSHOPT_PFSH -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_BRACEPAT -DSHOPT_HISTEXPAND -DSHOPT_COSHELL -D_PACKAGE_ast -DSHOPT_BGX -D_API_ast=20100309 -DSHOPT_MULTIBYTE -D_BLD_shell -DSHOPT_DYNAMIC -DKSHELL -DSHOPT_FIXEDARRAY -DSHOPT_STATS -DSHOPT_NAMESPACE -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c data/builtins.c
+done builtins.o generated
+make variables.o
+make data/variables.c
+prev include/builtins.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev include/name.h implicit
+prev include/shtable.h implicit
+prev include/shell.h implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/variables.c
+meta variables.o %.c>%.o data/variables.c variables
+prev data/variables.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_MULTIBYTE -D_BLD_shell -DSHOPT_DYNAMIC -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c data/variables.c
+done variables.o generated
+make lexstates.o
+make data/lexstates.c
+prev include/lexstates.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/lexstates.c
+meta lexstates.o %.c>%.o data/lexstates.c lexstates
+prev data/lexstates.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DSHOPT_TYPEDEF -DSHOPT_NAMESPACE -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -c data/lexstates.c
+done lexstates.o generated
+make emacs.o
+make edit/emacs.c
+prev include/terminal.h implicit
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev include/defs.h implicit
+prev FEATURE/cmds implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done edit/emacs.c
+meta emacs.o %.c>%.o edit/emacs.c emacs
+prev edit/emacs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DSHOPT_HISTEXPAND -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/emacs.c
+done emacs.o generated
+make vi.o
+make edit/vi.c
+prev include/lexstates.h implicit
+prev FEATURE/time implicit
+prev include/terminal.h implicit
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev include/defs.h implicit
+done edit/vi.c
+meta vi.o %.c>%.o edit/vi.c vi
+prev edit/vi.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_EDPREDICT -DSHOPT_RAWONLY -DSHOPT_MULTIBYTE -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_HISTEXPAND -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_PFSH -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/vi.c
+done vi.o generated
+make hexpand.o
+make edit/hexpand.c
+prev include/edit.h implicit
+prev include/defs.h implicit
+done edit/hexpand.c
+meta hexpand.o %.c>%.o edit/hexpand.c hexpand
+prev edit/hexpand.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -c edit/hexpand.c
+done hexpand.o generated
+exec - ${AR} rc libshell.a alarm.o cd_pwd.o cflow.o deparse.o enum.o getopts.o hist.o misc.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o
+exec - ${AR} rc libshell.a history.o init.o io.o jobs.o lex.o macro.o name.o nvtree.o parse.o path.o string.o streval.o subshell.o tdump.o timers.o trestore.o waitevent.o xec.o env.o limits.o msg.o strdata.o testops.o keywords.o options.o signals.o aliases.o builtins.o variables.o lexstates.o emacs.o vi.o hexpand.o
+exec - (ranlib libshell.a) >/dev/null 2>&1 || true
+done libshell.a generated
+bind -lshell
+prev +ljobs
+prev +li
+prev ${mam_libsocket}
+prev ${mam_libsecdb}
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -o ksh pmain.o ${mam_libshell} ${mam_libnsl} ${mam_libast}
+done ksh generated
+make shcomp
+make shcomp.o
+make sh/shcomp.c
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+prev include/shell.h implicit
+done sh/shcomp.c
+meta shcomp.o %.c>%.o sh/shcomp.c shcomp
+prev sh/shcomp.c
+setv CC.DLL -UCC.DLL
+setv SH_DICT -DSH_DICT="\"libshell\""
+setv _BLD_shell -U_BLD_shell
+setv _BLD_DLL -U_BLD_DLL
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DSH_DICT=\""libshell"\" -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -c sh/shcomp.c
+done shcomp.o generated
+prev libshell.a archive
+prev +ljobs
+prev +li
+prev ${mam_libsocket}
+prev ${mam_libsecdb}
+setv CC.DLL -UCC.DLL
+setv SH_DICT -DSH_DICT="\"libshell\""
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -o shcomp shcomp.o ${mam_libshell} ${mam_libnsl} ${mam_libast}
+done shcomp generated
+make suid_exec
+make suid_exec.o
+make sh/suid_exec.c
+prev include/version.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sig.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev FEATURE/externs implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/suid_exec.c
+meta suid_exec.o %.c>%.o sh/suid_exec.c suid_exec
+prev sh/suid_exec.c
+setv CC.DLL -UCC.DLL
+setv _BLD_shell -U_BLD_shell
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -D_PACKAGE_ast -c sh/suid_exec.c
+done suid_exec.o generated
+prev +ljobs
+prev +li
+prev ${mam_libsocket}
+prev ${mam_libsecdb}
+setv CC.DLL -UCC.DLL
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -o suid_exec suid_exec.o ${mam_libast} ${mam_libnsl} ${mam_libast}
+done suid_exec generated
+make shell
+prev libshell.a archive
+done shell virtual
+prev libshell.a archive
+make ${INSTALLROOT}/bin
+exec - if silent test ! -d ${INSTALLROOT}/bin
+exec - then mkdir -p ${INSTALLROOT}/bin
+exec - fi
+done ${INSTALLROOT}/bin generated
+make ${INSTALLROOT}/bin/ksh
+prev ${INSTALLROOT}/bin
+prev ksh
+exec - test '' = 'ksh' || ${STDCMP} 2>/dev/null -s ksh ${INSTALLROOT}/bin/ksh || { ${STDMV} ${INSTALLROOT}/bin/ksh ${INSTALLROOT}/bin/ksh.old 2>/dev/null || true; ${STDCP} ksh ${INSTALLROOT}/bin/ksh ;}
+done ${INSTALLROOT}/bin/ksh generated
+make ${INSTALLROOT}/man/man1
+exec - if silent test ! -d ${INSTALLROOT}/man/man1
+exec - then mkdir -p ${INSTALLROOT}/man/man1
+exec - fi
+done ${INSTALLROOT}/man/man1 generated
+make ${INSTALLROOT}/man/man1/sh.1
+prev ${INSTALLROOT}/man/man1
+make sh.1
+done sh.1
+exec - test '' = 'sh.1' || ${STDCMP} 2>/dev/null -s sh.1 ${INSTALLROOT}/man/man1/sh.1 || { ${STDMV} ${INSTALLROOT}/man/man1/sh.1 ${INSTALLROOT}/man/man1/sh.1.old 2>/dev/null || true; ${STDCP} sh.1 ${INSTALLROOT}/man/man1/sh.1 ;}
+done ${INSTALLROOT}/man/man1/sh.1 generated
+make ${INSTALLROOT}/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib
+exec - then mkdir -p ${INSTALLROOT}/lib
+exec - fi
+done ${INSTALLROOT}/lib generated
+make ${INSTALLROOT}/lib/libshell.a archive
+prev ${INSTALLROOT}/lib
+prev libshell.a archive
+exec - test '' = 'libshell.a' || ${STDCMP} 2>/dev/null -s libshell.a ${INSTALLROOT}/lib/libshell.a || { ${STDMV} ${INSTALLROOT}/lib/libshell.a ${INSTALLROOT}/lib/libshell.a.old 2>/dev/null || true; ${STDCP} libshell.a ${INSTALLROOT}/lib/libshell.a ;}
+exec - (ranlib ${INSTALLROOT}/lib/libshell.a) >/dev/null 2>&1 || true
+done ${INSTALLROOT}/lib/libshell.a generated
+make ${INSTALLROOT}/man/man3
+exec - if silent test ! -d ${INSTALLROOT}/man/man3
+exec - then mkdir -p ${INSTALLROOT}/man/man3
+exec - fi
+done ${INSTALLROOT}/man/man3 generated
+make ${INSTALLROOT}/man/man3/shell.3
+prev ${INSTALLROOT}/man/man3
+make shell.3
+done shell.3
+exec - test '' = 'shell.3' || ${STDCMP} 2>/dev/null -s shell.3 ${INSTALLROOT}/man/man3/shell.3 || { ${STDMV} ${INSTALLROOT}/man/man3/shell.3 ${INSTALLROOT}/man/man3/shell.3.old 2>/dev/null || true; ${STDCP} shell.3 ${INSTALLROOT}/man/man3/shell.3 ;}
+done ${INSTALLROOT}/man/man3/shell.3 generated
+make ${INSTALLROOT}/man/man3/nval.3
+make nval.3
+done nval.3
+exec - test '' = 'nval.3' || ${STDCMP} 2>/dev/null -s nval.3 ${INSTALLROOT}/man/man3/nval.3 || { ${STDMV} ${INSTALLROOT}/man/man3/nval.3 ${INSTALLROOT}/man/man3/nval.3.old 2>/dev/null || true; ${STDCP} nval.3 ${INSTALLROOT}/man/man3/nval.3 ;}
+done ${INSTALLROOT}/man/man3/nval.3 generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/shell
+prev ${INSTALLROOT}/lib/lib
+prev shell.req
+exec - test '' = 'shell.req' || ${STDCMP} 2>/dev/null -s shell.req ${INSTALLROOT}/lib/lib/shell || { ${STDMV} ${INSTALLROOT}/lib/lib/shell ${INSTALLROOT}/lib/lib/shell.old 2>/dev/null || true; ${STDCP} shell.req ${INSTALLROOT}/lib/lib/shell ;}
+done ${INSTALLROOT}/lib/lib/shell generated
+make ${PACKAGE_ast_INCLUDE}
+exec - if silent test ! -d ${PACKAGE_ast_INCLUDE}
+exec - then mkdir -p ${PACKAGE_ast_INCLUDE}
+exec - fi
+done ${PACKAGE_ast_INCLUDE} generated
+make ${PACKAGE_ast_INCLUDE}/nval.h
+prev ${PACKAGE_ast_INCLUDE}
+prev include/nval.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1982,author=dgk' include/nval.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/nval.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/nval.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/nval.h generated
+make ${PACKAGE_ast_INCLUDE}/shell.h
+prev include/shell.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1982,author=dgk' include/shell.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/shell.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/shell.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/shell.h generated
+make ${PACKAGE_ast_INCLUDE}/history.h
+prev include/history.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1982,author=dgk' include/history.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/history.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/history.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/history.h generated
+make ${INSTALLROOT}/bin/suid_exec
+prev suid_exec
+exec - test '' = 'suid_exec' || ${STDCMP} 2>/dev/null -s suid_exec ${INSTALLROOT}/bin/suid_exec || { ${STDMV} ${INSTALLROOT}/bin/suid_exec ${INSTALLROOT}/bin/suid_exec.old 2>/dev/null || true; ${STDCP} suid_exec ${INSTALLROOT}/bin/suid_exec ;}
+done ${INSTALLROOT}/bin/suid_exec generated
+make ${INSTALLROOT}/bin/shcomp
+prev shcomp
+exec - test '' = 'shcomp' || ${STDCMP} 2>/dev/null -s shcomp ${INSTALLROOT}/bin/shcomp || { ${STDMV} ${INSTALLROOT}/bin/shcomp ${INSTALLROOT}/bin/shcomp.old 2>/dev/null || true; ${STDCP} shcomp ${INSTALLROOT}/bin/shcomp ;}
+done ${INSTALLROOT}/bin/shcomp generated
+make ${INSTALLROOT}/fun
+exec - if silent test ! -d ${INSTALLROOT}/fun
+exec - then mkdir -p ${INSTALLROOT}/fun
+exec - fi
+done ${INSTALLROOT}/fun generated
+make ${INSTALLROOT}/fun/dirs
+prev ${INSTALLROOT}/fun
+make fun/dirs
+done fun/dirs
+setv mode -Dmode="+x"
+exec - test '' = 'fun/dirs' || ${STDCMP} 2>/dev/null -s fun/dirs ${INSTALLROOT}/fun/dirs || { ${STDMV} ${INSTALLROOT}/fun/dirs ${INSTALLROOT}/fun/dirs.old 2>/dev/null || true; ${STDCP} fun/dirs ${INSTALLROOT}/fun/dirs && chmod ugo+x ${INSTALLROOT}/fun/dirs ;}
+done ${INSTALLROOT}/fun/dirs generated
+make ${INSTALLROOT}/fun/popd
+make fun/popd
+done fun/popd
+setv mode -Dmode="+x"
+exec - test '' = 'fun/popd' || ${STDCMP} 2>/dev/null -s fun/popd ${INSTALLROOT}/fun/popd || { ${STDMV} ${INSTALLROOT}/fun/popd ${INSTALLROOT}/fun/popd.old 2>/dev/null || true; ${STDCP} fun/popd ${INSTALLROOT}/fun/popd && chmod ugo+x ${INSTALLROOT}/fun/popd ;}
+done ${INSTALLROOT}/fun/popd generated
+make ${INSTALLROOT}/fun/pushd
+make fun/pushd
+done fun/pushd
+setv mode -Dmode="+x"
+exec - test '' = 'fun/pushd' || ${STDCMP} 2>/dev/null -s fun/pushd ${INSTALLROOT}/fun/pushd || { ${STDMV} ${INSTALLROOT}/fun/pushd ${INSTALLROOT}/fun/pushd.old 2>/dev/null || true; ${STDCP} fun/pushd ${INSTALLROOT}/fun/pushd && chmod ugo+x ${INSTALLROOT}/fun/pushd ;}
+done ${INSTALLROOT}/fun/pushd generated
+done install virtual
+make test
+make test.ksh
+prev ${INSTALLROOT}/bin/ksh
+prev ksh
+make tests/shtests
+done tests/shtests
+exec - silent cmp 2>/dev/null -s ${INSTALLROOT}/bin/ksh ksh 2>/dev/null ||
+exec - echo "make install to run the tests on the latest ksh" >&2
+exec - cd ${PACKAGEROOT}/src/cmd/ksh93/tests
+exec - SHELL=${INSTALLROOT}/bin/ksh ${INSTALLROOT}/bin/ksh shtests
+done test.ksh virtual
+done test dontcare virtual
diff --git a/src/cmd/ksh93/OBSOLETE b/src/cmd/ksh93/OBSOLETE
new file mode 100644
index 0000000..c29cb8b
--- /dev/null
+++ b/src/cmd/ksh93/OBSOLETE
@@ -0,0 +1,152 @@
+.sp 3
+.tl ''Ksh Features That Are Obsolete in Ksh93''
+.sp 2
+.AL 1
+.LI
+Using a pair of grave accents \^\fB\(ga\fR ... \fB\(ga\fR\^
+for command substition. Use \fB$(\fR ... \fB)\fR instead.
+.LI
+.B FCEDIT
+is an obsolete name for
+the default editor name for the
+.B hist
+command.
+.B FCEDIT
+is not used when
+.B HISTEDIT
+is set. Use
+.B HISTEDIT
+instead.
+.LI
+The newtest (\fB[[\fR ... \fB]]\fR) operator
+\fB\-a\fP \fIfile\fP
+is obsolete. Use
+\fB\-e\fP instead.
+.LI
+The newtest (\fB[[\fR ... \fB]]\fR) operator
+.BR = ,
+as used in
+\fIstring\fP \fB=\fP \fIpattern\fP
+is obsolete. Use
+\fB==\fP instead.
+.LI
+The following obsolete arithmetic comparisons are also permitted:
+.in +5
+.VL 20
+.LI "\fIexp1\fP \fB\-eq\fP \fIexp2\fP"
+True, if
+.I exp1
+is equal to
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-ne\fP \fIexp2\fP"
+True, if
+.I exp1
+is not equal to
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-lt\fP \fIexp2\fP"
+True, if
+.I exp1
+is less than
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-gt\fP \fIexp2\fP"
+True, if
+.I exp1
+is greater than
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-le\fP \fIexp2\fP"
+True, if
+.I exp1
+is less than or equal to
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-ge\fP \fIexp2\fP"
+True, if
+.I exp1
+is greater than or equal to
+.IR exp2 .
+.LE \" End .VL
+.in -5
+.LI
+Using test -t or [ -t ] without specifying the file unit number.
+.LI
+The
+.B \-k
+option to the \fBset\fR builtin is obsolete. It causes
+.I all\^
+variable assignment arguments are placed in the environment,
+even if they occur after the command name.
+The following
+first prints
+.B "a=b c"
+and then
+.BR c :
+There is no alternative.
+.LI
+The obsolete
+.B \-xf
+option of the
+.B typeset
+command allows a function to be exported
+to scripts that are executed without a separate
+invocation of the shell.
+Functions that need to be defined across separate
+invocations of the shell should
+be placed in a directory and the
+.B FPATH
+variable should contains the name of this directory.
+They may also
+be specified in the
+.B ENV
+file with the
+.B \-xf
+option of
+.BR typeset .
+.LI
+The shell environment variable
+.B FCEDIT
+is obsolete. Use
+.B HISTEDIT
+instead.
+.LI
+In the
+.B \-s
+option
+(to \fBfc\fR or \fBhist\fR command???)
+(
+and in obsolete versions, the editor name
+.B \-
+)
+is used to skip the editing phase and
+to re-execute the command.
+.LI
+The
+.B \-t
+option to \fBalias\fR builtin is is obsolete. It
+is used to set and list tracked aliases.
+There is no replacement.
+.LI
+The shell command line option
+.B \-t
+is obsolete. This option cause the shell to exit after reading
+and executing one command. The is no replacement (although ending
+\&"command" with the exit builtin should have the same effect).
+.LI
+As an obsolete feature of the "set" builtin,
+if the first
+.I arg\^
+is
+.B \-
+then the
+.B \-x
+and
+.B \-v
+options are turned off and the next
+.I arg
+is treated as the first argument.
+Using
+.B \+
+rather than
+.B \-
+causes these options to be turned off.
+These options can also be used upon invocation of the shell.
+.LE
+
diff --git a/src/cmd/ksh93/PROMO.mm b/src/cmd/ksh93/PROMO.mm
new file mode 100644
index 0000000..def4552
--- /dev/null
+++ b/src/cmd/ksh93/PROMO.mm
@@ -0,0 +1,141 @@
+.H 1 ksh93
+KSH-93 is the most recent version of the KornShell Language
+described in
+"The KornShell Command and Programming Language,"
+by Morris Bolsky and David Korn of AT&T Bell Laboratories, ISBN 0-13-182700-6.
+The KornShell is a shell programming language,
+which is upward compatible with "sh" (the Bourne Shell),
+and is intended to conform to the IEEE P1003.2/ISO 9945.2 Shell and
+Utilities standard.
+KSH-93 provides an enhanced programming environment in
+addition to the major command-entry features of the BSD
+shell "csh". With KSH-93, medium-sized programming tasks can be
+performed at shell-level without a significant loss in performance.
+In addition, "sh" scripts can be run on KSH-93 without modification.
+.P
+The code should conform to the IEEE POSIX 1003.1 standard and to the
+proposed ANSI-C standard so that it should be portable to all
+such systems. Like the previous version, KSH-88,
+it is designed to accept eight bit character sets
+transparently, thereby making it internationally compatible.
+It can support multi-byte characters sets with some characteristics
+of the character set given at run time.
+.P
+KSH-93 provides the following features, many of which were also inherent
+in KSH-88:
+.BL
+.LI
+Enhanced Command Re-entry Capability: The KSH-93 history
+function records commands entered at any shell level and stores
+them, up to a user-specified limit, even after you log off.
+This allows you to re-enter long commands with a few keystrokes
+- even those commands you entered yesterday.
+The history file allows for eight bit characters in
+commands and supports essentially unlimited size histories.
+.LI
+In-line Editing: In "sh", the only way to fix mistyped
+commands is to backspace or retype the line. KSH-93 allows you
+to edit a command line using a choice of EMACS-TC or "vi"
+functions.
+You can use the in-line editors to complete filenames as
+you type them.
+You may also use this editing feature when entering
+command lines from your history file.
+A user can capture keystrokes and rebind keys to customize the
+editing interface.
+.LI
+Extended I/O Capabilities: KSH-93 provides several I/O
+capabilities not available in "sh", including the ability to:
+.BL
+.LI
+specify a file descriptor for input and output
+.LI
+start up and run co-processes
+.LI
+produce a prompt at the terminal before a read
+.LI
+easily format and interpret responses to a menu
+.LI
+echo lines exactly as output without escape processing
+.LI
+format output using printf formats.
+.LI
+read and echo lines ending in "\e".
+.LE
+.LI
+Improved performance: KSH-93 executes many scripts faster
+than the System V Bourne shell. A major reason for this is
+that many of the standard utilities are built-in.
+To reduce the time to initiate a command, KSH-93 allows
+commands to be added as built-ins at run time
+on systems that support dynamic loading such as System V Release 4.
+.LI
+Arithmetic: KSH-93 allows you to do integer arithmetic in any
+base from two to sixty-four. You can also do double
+precision floating point arithmetic.
+Almost the complete set of C language operators are available
+with the same syntax and precedence.
+Arithmetic expressions can be used to as an argument expansion
+or as a separate command.
+In addition there is an arithmetic for command that works
+like the for statement in C.
+.LI
+Arrays: KSH-93 supports both indexed and associative arrays.
+The subscript for an indexed array is an arithmetic expression,
+whereas, the subscript for an associative array is a string.
+.LI
+Shell Functions and Aliases: Two mechanisms - functions and
+aliases - can be used to assign a user-selected identifier to
+an existing command or shell script.
+Functions allow local variables and provide scoping
+for exception handling.
+Functions can be searched for and loaded on first reference the
+way scripts are.
+.LI
+Substring Capabilities: KSH-93 allows you to create a
+substring of any given string either by specifying the starting
+offset and length, or by stripping off leading
+or trailing substrings during parameter substitution.
+You can also specify attributes, such as upper and lower case,
+field width, and justification to shell variables.
+.LI
+More pattern matching capabilities: KSH-93 allows you to specify
+extended regular expressions for file and string matches.
+.LI
+KSH-93 uses a hierarchal name space for variables.
+Compound variables can be defined and variables can
+be passed by reference. In addition, each variable
+can have one or more disciplines associated with
+it to intercept assignments and references.
+.LI
+Improved debugging: KSH-93 can generate line numbers on execution
+traces. Also, I/O redirections are now traced.
+There is a DEBUG trap that gets evaluated before each command
+so that errors can be localized.
+.LI
+Job Control: On systems that support job control, including
+System V Release 4, KSH-93
+provides a job-control mechanism almost identical to that of
+the BSD "csh", version 4.1.
+This feature allows you
+to stop and restart programs, and to move programs between the
+foreground and the background.
+.LI
+Added security:
+KSH-93 can execute scripts which do not have read permission
+and scripts which have the setuid and/or setgid set when
+invoked by name, rather than as an argument to the shell.
+It is possible to log or control the execution of setuid and/or
+setgid scripts.
+The noclobber option prevents you from accidentally erasing
+a file by redirecting to an existing file.
+.LI
+KSH-93 can be extended by adding built-in commands at run time.
+In addition, KSH-93 can be used as a library that can
+be embedded into an application to allow scripting.
+.LE
+Documentation for KSH-93 consists of an "Introduction to KSH-93",
+"Compatibility with the Bourne Shell" and a manual page and a
+README file. In addition, the "New KornShell Command and Programming
+Language," book is available from Prentice Hall.
+
diff --git a/src/cmd/ksh93/README b/src/cmd/ksh93/README
new file mode 100644
index 0000000..1feeec8
--- /dev/null
+++ b/src/cmd/ksh93/README
@@ -0,0 +1,232 @@
+This directory, and its subdirectories contain the source code
+for ksh-93; the language described in the second addition of
+the book, "The KornShell Command and Programming Language," by
+Morris Bolsky and David Korn which is published by Prentice Hall.
+ksh-93 has been compiled and run on several machines with several
+operating systems. The end of this file contains a partial list of
+operating systems and machines that ksh-93 has been known to run on.
+
+The layout of files for ksh-93 has changed somewhat since ksh-88,
+the last major release. Most of the source code for ksh remains in
+the sh directory. However, the shell editing and history routines
+are in the edit sub-directory. The code for shell built-ins is
+in the bltins directory. The data directory contains read-only
+data tables and messages that are used by the shell. The include
+files remain in the include directory and the shlib directory
+is gone. The features directory replaces the older install
+directory. The method for generating systems specific feature
+information has changed substantially.
+
+The Makefile file contains several compilation options that can be set
+before compiling ksh. Options are of the form SHOPT_option and become
+#define inside the code. These options are set to their recommended
+value and some of these may disappear as options in future releases.
+A value of 0, or no value represents off, 1 represents on.
+Note that == is needed, not =, because these are nmake state variables
+and changing their value will cause all modules that could be affected
+by this change to be recompiled.
+The options have the following defaults and meanings:
+ ACCT off Shell accounting.
+ ACCTFILE off Enable per user accounting info.
+ AUDIT off For auditing specific users
+ AUDITFILE "/etc/ksh_audit"
+ APPEND on Allows var+=val string and array append.
+ BASH off Bash compatibility mode. It is not fully implemented
+ and is experimental.
+ BRACEPAT on C-shell type abc{d,e}f style file generation
+ CMDLIB_BLTIN off Makes all commands in libcmd.a builtins. The
+ SH_CMDLIB_DIR nmake state variable can be used to
+ specify a directory.
+ CMDLIB_DIR off Sets CMDLIB_BLTIN=1 and provides a default value
+ of "/opt/ast/bin" for SH_CMDLIB_DIR.
+ COMPOUND_ARRAY
+ on Allows all components of compound variables except the
+ first to be any string by enclosing in [...]. It also
+ allows components other than the last to be arrays.
+ This is experimental and only partially complete.
+ CRNL off <cr><nl> treated as <nl> in shell grammar.
+ DYNAMIC on Dynamic loading of builtins. (Requires dlopen() interface.)
+ ECHOPRINT off Make echo equivalent to print.
+ ESH on Compile with emacs command line editing. The original
+ emacs line editor code was provided by Mike Veach at IH.
+ FILESCAN on Experimental option that allows fast reading of files
+ using while < file;do ...; done and allowing fields in
+ each line to be accessed as positional parameters.
+ FS_3D off For use with 3-D file system. Enabled automatically for
+ sytems with dynamic linking.
+ KIA off Allow generation of shell cross reference database with -I.
+ MULTIBYTE on Multibyte character handling. Requires mblen() and
+ mbctowc().
+ NAMESPACE on Allows namespaces. This is experimental, incomplete
+ and undocumented.
+ OLDTERMIO off Use either termios or termio at runtime.
+ OO on Experimental object oriented extension. This option
+ should disappear soon.
+ OPTIMIZE on Optimize loop invariants for with for and while loops.
+ P_SUID off If set, all real uids, greater than or equal to this
+ value will require the -p flag to run suid/sgid scripts.
+ PFSH off Compile with support for profile shell.
+ RAWONLY off Turn on if the vi line mode doesn't work right unless
+ you do a set -o viraw.
+ SEVENBIT off Strip the eigth bit from characters.
+ SPAWN off Use spawn as combined fork/exec. May improve speed on
+ some systems.
+ STATS on Add .sh.stats compound variable.
+ SUID_EXEC on Execute /etc/suid_exec for setuid, setgid script.
+ TIMEOUT off Set this to the number of seconds for timing out and
+ exiting the shell when you don't enter a command. If
+ non-zero, TMOUT can not be set larger than this value.
+ TYPEDEF on Enable typeset type definitions.
+ VSH on Compile with vi command line editing. The original vi
+ line editor code was provided by Pat Sullivan at CB.
+
+The following compile options are set automatically by the feature testing:
+ DEVFD Set when /dev/fd is a directory that names open files.
+ SHELLMAGIC
+ Set on systems that recognize script beginning with #! specially.
+ VPIX Set on systems the have /usr/bin/vpix program for running MS-DOS.
+
+
+In most instances, you will generate ksh from a higher level directory
+which also generates libcmd and libast libraries on which ksh depends.
+However, it is possible to generate ksh, with by running make -f ksh.mk
+in this directory. The ksh.mk file was generated from the nmake Makefile.
+If you do not have make or nmake, but do have a Version 7 UNIX compatible
+shell, then you can run the script mamexec < Mamfile to build ksh.
+If you have nmake, version 2.3 or later, you can use it without the -f ksh.mk.
+In either case, ksh relies on libraries libast and libcmd which must be
+built first. The binary for ksh becomes the file named ./ksh which can
+be copied to where ever you install it.
+
+If you use old make or the Mamfile, and you system has dynamic shared
+libraries, then you should define the variables mam_cc_static and
+mam_cc_dynanamic as the compiler options that request static linking
+and dynamic linking respectively. This will decrease the number of
+shared libraries that ksh need and cut startup time substantially.
+
+The makefile should also generate shcomp, a program that will precompile
+a script. ksh93 is able to recognize files in this format and process
+them as scripts. You can use shcomp to send out scripts when you
+don't want to give away the original script source.
+
+It is advisable that you put the line PWD=$HOME;export PWD into the
+/etc/profile file to reduce initialization time for ksh.
+
+To be able to run setuid/setgid shell scripts, or scripts without read
+permission, the SUID_EXEC compile option must be on, and ksh must be installed
+in the /bin directory, the /usr/bin directory, the /usr/lbin directory,
+or the /usr/local/bin directory and the name must end in sh. The program
+suid_exec must be installed in the /etc directory, must be owned by root,
+and must be a suid program. If you must install ksh in some other directory
+and want to be able to run setuid/setgid and execute only scripts, then
+you will have to change the source code file sh/suid_exec.c explicitly.
+If you do not have ksh in one of these secure locations, /bin/sh will
+be invoked with the -p options and will fail when you execute a setuid/setgid
+and/or execute only script. Note, that ksh does not read the .profile
+or $ENV file when it the real and effective user/group id's are not
+equal.
+
+The tests sub-directory contains a number of regression tests for ksh.
+To run all these tests with the shell you just built, go to the tests
+directory and run the command
+ SHELL=$dir/ksh $dir/ksh shtests
+where dir is the directory of the ksh you want to test.
+
+The file PROMO.mm is an advertisement that extolls the virtues of ksh.
+The file sh.1 contains the troff (man) description of this Shell.
+The file nval.3 contains the troff (man) description of the name-value
+pair library that is needed for writing built-ins that need to
+access shell variables.
+
+The file sh.memo contains a draft troff (mm) memo describing ksh. The
+file RELEASE88 contains the changes made for ksh88. The file RELEASE93
+contains the changes made in this release since ksh-88. The file
+RELEASE contains bug fixes made in this release since ksh-88. The file
+COMPATIBILITY contains a list of incompatibilities with ksh-88. The
+file bltins.mm is a draft troff (mm) memo describing how to write
+built-in commands that can be loaded at run time.
+
+Most of the work for internationalization has been done with ksh93.
+The file ksh.msg is a generated file that contains error messages
+that need to be translated. In addition, the function translate()
+in sh/init.c has to be completed to interface with the dictionary
+lookup. The translate function takes two argument, the string
+that is to be translated and a type which is
+ 0 when a library string needs translation.
+ 1 when one of the error messages in ksh.msg needs translation.
+ 2 when a string in a script needs translation. You use a $ in front
+ of a double quoted string in a script to indicate that it
+ needs translation. The -D option for ksh builds the dictionary.
+The translate routine needs to return the translated message.
+For dictionaries that need to use a numeric key, it should be
+possible to use the strhash() function to generate numbers to
+go along with each of the messages and to use this number both
+when generating the dictionary and when converting strings.
+If you encounter error messages of type 1 that are not be translated via
+this translate() function send mail to the address below.
+
+Please report any problems or suggestions to:
+
+dgk@research.att.com
+
+
+ksh93 has been compiled and alpha tested on the following. An asterisk
+signifies that ksh has been installed as /bin/sh on this machine.
+
+* Sun OS 4.1.[123] on sparc.
+ Sun OS 4.1.1 on sun.
+ Solaris 2.[1-9] on sparc.
+ Solaris 2.[4-8] on X86.
+ HP/UX 8 on HP-9000/730.
+ HP/UX 9 on HP-9000/730.
+ HP/UX 10 on HP-9000/857.
+ HP/UX 11 on pa-risc.
+ System V Release 3 on Counterpoint C19
+ System V Release 4 on AT&T Intel 486.
+ System V Release 4 on NCR 4850 Intel 486.
+ IRIX Release 4.0.? System V on SGI-MIPS.
+ IRIX Release 5.1 System V on SGI-MIPS.
+ IRIX Release 6.[1-5] System V on SGI-MIPS.
+ System V Release 3.2 on 3B2.
+ UTS 5.2.6 on Amdahl 3090,5990,580.
+ System V Release 3.2 on i386.
+ SMP_DC.OSx olivetti dcosx MIServer-S 2/128.
+ SMP_DC.OSx Pyramid dcosx MIServer-S 2/160 r3000.
+ 4.3BSD on Vax 8650.
+ AIX release 2 on RS6000.
+ AIX 3.2 on RS6000.
+ Linux 1.X on Intel
+ Linux 2.X on Intel
+ Linux 2.X on Alpha
+ Linux 2.X on Alpha
+ Linux 2.X on OS/390
+ Linux 2.X on sparc
+ Linux 2.4 on intel itanium 64
+ Linux Slackware on sparc64
+* Linux ARM on i-PAQ
+ OSF1 on DEC alpha.
+ OSF4 on DEC alpha.
+ UMIPS 4.52 on mips.
+ BSD-i [2-4] on X86.
+ OpenBSD on X86
+ NetBSD on X86
+ FreeBSD on X86
+ NeXT on Intel X86.
+ NeXT on HP.
+* Windows NT using UWIN on X86
+* Windows NT using UWIN on alpha
+ Windows NT using Cygwin on X86
+ Windows NT with NutCracker libraries.
+ Windows NT with Portage libraries.
+ Windows 3.1 using custom C library.
+ OpenEdition on MVS
+ Darwin OS X on PPC
+ MVS on OS 390
+ SCO Openserver 3.2 on X86
+ Unixware 7 on X86
+
+Good luck!!
+
+David Korn
+dgk@research.att.com
+
diff --git a/src/cmd/ksh93/RELEASE b/src/cmd/ksh93/RELEASE
new file mode 100644
index 0000000..2f95505
--- /dev/null
+++ b/src/cmd/ksh93/RELEASE
@@ -0,0 +1,2888 @@
+12-02-29 --- Release ksh93u+ ---
+12-02-29 A bug which could lead to a core dump when more that four shared
+ libraries were added with the builtin command has been fixed.
+12-02-29 Fixed a few bugs which caused SIGCHLD to be blocked preventing
+ background jobs from being reaped until a foreground job was run.
+12-02-27 A bug in which sh -c for a simple command caused a fork() has been
+ fixed.
+12-02-27 A timing bug on systems such as AIX that doesn't support vfork()
+ that could cause the exist status to get lost has been fixed.
+12-02-22 A private file descriptor that was not close-on-exec for a command
+ substitution and has been fixed.
+12-02-14 A bug in which ^Z did not stop a pipeline when the last component
+ was a shell built-in has been fixed.
+12-02-14 getconf("PATH") used to initialize ed(1) path.
+12-02-13 +In earlier version read from standard input would fail when called
+ from the KEYBD trap. Now read options -N, -n, and -t should work
+ when called from a KEYBD trap.
+12-02-13 If FCEDIT is not set and fc is invoked without the -e option,
+ ed will be invoked if found instead of /bin/ed.
+12-02-10 Another bug in the saving and restoring of IFS in a subshell
+ that caused a core dump has been fixed.
+12-02-08 A bug in which .sh.fun disciplines could be cleared after a
+ function completes has been fixed.
+12-02-08 A bug in job control in which the foregroup process group was not
+ set correctly after restarting a stopped pipeline has been fixed.
+12-02-07 A bug in which numbers with leading zeros could be treated as
+ octal constants outside of ((...)) has been fixed.
+12-02-06 A bug in arithmetic with compound variables containing multiple
+ array elements has been fixed.
+12-02-02 A bug in the ulimit option table was fixed.
+12-01-26 A bug in which a set command that did not change monitor could
+ effect the behavior of the monitor when monitor mode is on is fixed.
+12-01-21 +You can now test whether the shell implements a math function using
+ typeset -f .sh.math.name, where name is the name of the function.
+12-01-21 A bug in which typeset -L and typeset -R did not handle multibyte
+ characters correctly has been fixed.
+12-01-20 A bug that could cause the shell to hang waiting for an incorrect
+ job pid has been fixed.
+12-01-19 A memory leak which occured for a nested command subtiution has been
+ fixed.
+12-01-17 A bug in which typeset -u PS1 could enable the uppercase attribute
+ for some other variables, for exampe, HISTFILE has been fixed.
+12-01-16 A bug in which .sh.match was not correct after a substring match when
+ the replacement string contained a substring match has been fixed.
+12-01-12 +Files that are sourced from profile files are now read and executed
+ one command at a time so that alias definitions take effect as they
+ do for profile files.
+12-01-12 A bug in which whence -p would find a function if one existed and
+ there was no command of that name on PATH.
+12-01-11 Change b_* prototype (int, char**, void*) => (int, char**, Shbltin_t*).
+12-01-05 A bug in which read was not terminating for a signal that had a trap
+ set has been fixed.
+12-01-01 A timing problem with >; has been fixed.
+12-01-01 A macro expansion memory leak has been fixed.
+11-12-26 A bug in array assignments of the form arr=( $arr[i] ...) in which
+ arr was not unset before the assignment has been fixed.
+11-12-20 A number of code changes were made based on the results of errors
+ indicated by static code analysis.
+11-12-13 In vi edit mode a lteral <TAB> can now be entered by preceding it
+ with a backshash.
+11-12-13 When tab is entered for completion after a ' or ", the ' and "
+ characters are no longer deleted.
+11-12-07 A bug in which a program in the current direcotry with a . in the
+ name could fail to execute when both PATH and FPATH end with :. has
+ been fixed.
+11-12-07 I fixed a bug in which a variable expansion in a large here-document
+ could be expanded to a null string.
+11-12-06 An optimization to read was added in the case the the read command
+ was redirected from a file.
+11-12-06 Changes were made to make the line limit for read unlimited by
+ default.
+11-12-05 A bug in which unsetting an array variable did not completely clear
+ the variable in some cases has been fixed.
+11-12-02 +The printf alternative character # when applied to the %q format will
+ quote argument in a form suitable for a field in a .csv format file.
+11-12-02 +A -S option was added to read to be able to read .csv format files.
+11-11-28 A bug in which redirection of standard error in a function called from
+ command substitution caused standard error to be lost has ben fixed.
+11-11-21 [[ (-n foo) ]] no longer requires a space before (.
+11-11-11 The readonly attribute for a variable now applies to compound
+ assignments to that variable.
+11-11-07 Changes were made to reduce the stack size to allow deeper function
+ recursion.
+11-10-10 +Added alternate flag to printf %H for encoding of URI's.
+11-10-10 A bug which could lead to a core dump when the shell was invoked
+ with more than twenty five open files has been fixed.
+11-10-06 A bug in the scoping of name references in functions called by other
+ functions has been fixed.
+11-10-05 A bug in which wait on a pid may return the exit status of an
+ earlier background job with that pid instead has been fixed.
+11-09-22 A bug in which a read timed out with TMOUT did not always restore
+ the terminal state has been fixed.
+11-09-21 An optimization that allowed the last command in a script to use
+ the same process id as the script has been eliminated.
+11-09-21 Added letoctal option that enables the let command to recognize
+ octal constants starting with 0.
+11-09-20 A bug in which ${var.} could cause a core dump has been fixed.
+11-09-20 A bug with SHOPT_EDPREDICT when neither vi or emacs was enabled for
+ lines beginning with # when in a multibyte locale has been fixed.
+11-09-20 A bug in emacs edit mode with SHOPT_EDPREDICT that would cause
+ history searches matching comments lines to generate predictions
+ has been fixed. Only user typed comment lines generate predictions.
+11-09-20 A bug in emacs edit mode with a search that matches a comment line
+ that could cause a core dump has been fixed.
+11-09-16 A bug in which a command name ending in .. could cause the shell to
+ abort has been fixed.
+11-09-16 The characters ! + - % and @ in file names are no longer escaped with
+ file name completion.
+11-09-13 The let command no longer treats numbers starting with 0 as octal
+ constants.
+11-09-08 A bug in which printf "%R" could cause a core dump for invalid shell
+ patterns has been fixed.
+11-08-09 With set -u, ${var#pattern} reported that var was unset for special
+ variables.
+11-08-03 A bug in which the shell did not preserve the exit status for a
+ coprocess has been fixed.
+11-08-02 A bug in the saving and restoring of IFS in command substitution that
+ caused a core dump has been fixed.
+11-07-21 Modified the 10-08-27 bug fix so that background jobs started in for
+ and while loops created interactively generate completion messages.
+11-07-20 I fixed a bug in here documents in which multi-byte characters that
+ crossed buffer boundaries were not processed correctly.
+11-06-22 The shell compiler now supports process substitution.
+11-06-22 +Added code to support process substitution on systems that do
+ not supply the /dev/fd directory.
+11-06-21 Fixed extraneous jobs Done messages when builtin is at the end of a
+ pipeline.
+11-06-20 Fixed two regression tests.
+11-06-20 Fixed a bug introduced on last update.
+11-06-14 A bug with pipefail in which the shell would wait for background
+ jobs to complete has been fixed.
+11-06-09 A bug which caused the options.sh regression test to fail on OS390
+ Linux has been fixed. The bug could also have affected other systems.
+11-06-07 +A number of changes to support the still undocuments namespace option
+ have been added.
+11-06-06 A bug in which command substitution of eval would hang when it had
+ standard error redirected to standard output has been fixed.
+11-06-01 A bug in case statement fall through (;&) ignoring set -e was fixed.
+11-06-01 A bug in which creating a left or right justified upper or lowercase
+ variable with an empty string has been fixed.
+11-06-01 A bug in which the .paths directory wasn't read when a subshell was
+ executed before any other command has been fixed.
+11-05-31 The shell now gives an error when a type variable is assigned to
+ an array instance when the array has been declared a compound variable
+ array.
+11-05-31 A bug in which typeset -m of an array instance did not remove the
+ original instance has been fixed.
+11-05-28 A bug in which typeset -m dest=src fails when src and are passed as
+ name references was fixed.
+11-05-28 A bug in which typeset -m "c.board[1][i]=el", where el is a compound
+ variable core dumps has been fixed.
+11-05-28 Two bugs in the display of arrays of compound variables with print -v
+ have been fixed.
+11-05-27 A bug with command substitution with the shift jis locale has been
+ fixed.
+11-05-25 A bug in which unset -f foo, called within function foo could cause
+ the shell to core dump has been fixed.
+11-05-24 A bug in unsetting arrays of compound variables that could lead to
+ a core dump has been fixed.
+11-05-24 A scoping bug in with typeset -m for variables passed as references
+ has been fixed.
+11-05-09 A bug in which 'typeset +p array[$i]' in a subshell could cause an
+ exception has been fixed.
+11-05-03 Two more scoping bugs with name references and read -C were fixed.
+11-05-03 A potential race condition which occurs when here-documents are
+ processed in asynchronous blocks has been eliminated.
+11-05-02 Another scoping bug with name references defined in a function has
+ been fixed.
+11-05-02 A bug in which the shell discards saved exit status of a job if it is
+ followed by a subshell execution has been fixed.
+11-04-28 The shell now checks for numerical overflows with process ids.
+11-04-28 Another scoping bug with compound variables defined by name references
+ inside a function has been fixed.
+11-04-28 A bug which caused a core dump on 32 bit systems with the basic.sh
+ regression test has been fixed.
+11-04-27 A scope binding error for name references has been fixed.
+11-04-27 Assignment of compound variable to compound array element by name
+ is now working.
+11-04-26 I fixed a bug with SHOPT_FIXEDARRAY compilation that could cause
+ an a core dump for not fixed arrays.
+11-04-25 A bug in the references to two dimensional compound arrays has
+ been fixed.
+11-04-20 A bug in which a name reference to a multidimentional index array
+ index, nameref x=foo[3][4], did not work correctly has been fixed.
+11-04-18 Changes were added to allow fixed size arrays of variable sized
+ objects when the SHOPT_FIXEDARRAY compile option defined on 10-09-28.
+11-04-18 A bug in which name references to array elements could fail has
+ been fixed.
+11-04-15 +A compile option, SHOPT_2DMATCH, has been added which causes
+ .sh.match to be a two dimensional array after ${var//pat/str}
+ where the first dimension is the pattern number and the second is
+ the match instance.
+11-04-11 A bug in which readonly var, where var is exported could cause var
+ to be unset has been fixed.
+11-04-06 A tokenizer bug in which ${x/{3}(\d)/ } would cause in infinite
+ loop has been fixed.
+11-04-05 A bug in which ${!x.} could cause a core dump has been fixed.
+11-04-04 A bug in which cleaning out the history file could terminate before
+ keeping all the recent history events has been fixed.
+11-03-29 A bug in which ${#array[@]} was 1 rather than 0 after issuing
+ typeset array[7] has been fixed.
+11-03-29 The subscript out or range message for fixed arrays has been fixed.
+11-03-29 A bug in which suspend could cause a core dump has been fixed.
+11-03-24 For the showme option added 09-09-09, commands beginning with a ;
+ inside an arithmetic for loop, no longer produce syntax errors.
+11-03-18 A bug in _WINIX ~domain/user expansion has been fixed.
+11-03-16 A bug in the pipefail option which could cause a script to hang
+ has been fixed.
+11-03-12 The shell no longer treats ${##pattern} as a syntax error.
+11-03-11 A bug in typeset -u on systems that don't supply the towctrans()
+ function has been fixed.
+11-03-11 A bug in which a compound assignment of the form var[sub]=(...)
+ would evaluate sub for each assignment has been fixed.
+11-03-07 A bug in which reassigning a compound variable to an associative
+ array index could incorrectly increase the count of the number
+ of elements has been fixed.
+11-03-04 +The tilde expansion on windows has been modified to handle user
+ names of the form domain/user so that ~domain/user now expands
+ to the home directory of that domain user.
+11-03-03 A bug in which the width of the prompt was calculated incorectly
+ which cause the wrong line length for edit commands has been fixed.
+11-03-02 A bug in which a global variables set from within a function inside
+ a subshell can leave side effects in parent shell has been fixed.
+11-03-01 A bug in which whence -a could dump core when the first match
+ was due to : in PATH and the program was in the current directory.
+11-02-28 A bug in emacs mode with SHOPT_EDPREDICT (added on 10-05-20) which
+ disabled prediction on a line starting with # when the cursor was not
+ at the end of line has been fixed.
+11-02-28 The output format for compound variables with set has been fixed.
+11-02-25 A bug which could lead to a core dump occurred when a shell script
+ without #! is invoked by name from a parent shell that has name
+ references defined and the script creates name references of the
+ same name.
+11-02-21 The shell now fails with a syntax error when a here-document in a
+ command substition is not completed before the closing ), for
+ example, $( foobar <<! )
+ here_doc
+ !.
+11-02-18 A bug in which the value of $0 in a function defined by name()
+ was changed to name has been fixed.
+11-02-17 A bug in which the declaration typeset var[100] did not work
+ correctly has been fixed.
+11-02-15 A bug in which [[ -v sh.match ]] did not work correctly has been
+ fixed.
+
+11-02-08 --- Release ksh93u ---
+11-02-08 A bug in which opening standard output after it has been closed with
+ exec 1>&- doesn't work has been fixed.
+11-02-07 A bug on some systems for which a command subtitution could hang
+ has been fixed.
+11-01-28 A bug in file name completion for files containing both multibyte
+ characters shell special characters has been fixed.
+11-01-18 The .sh.match variable now shows elements that do not match as
+ as not set rather than an empty string.
+11-01-18 A bug with typeset -m of an array into an element of an indexed
+ array has been fixed.
+11-01-13 A bug in handling of arrays of compound variables inside ((...)) which
+ reported a syntax error been fixed.
+11-01-10 A bug in arithmetic assignment operators of the form op= for array
+ variables when the same array was referenced on the left and the
+ right hand side with different indices has been fixed.
+11-01-10 A bug in which the output of time was lost when { time...;} 2>&1
+ occurred inside command substition has been fixed.
+11-01-07 [[ -v sh.match[i] ]] was returning false when sh.match[i] was set.
+11-01-05 Added and modified warning messages with sh -n.
+11-01-02 Fixed bugs with typeset -l/-u/-M and arrays.
+10-12-28 Fixed a bug with typeset -l/-u/-M values in arithmetic expressions.
+10-12-26 Fixed a time parsing bug in sleep and localeconv() initialization.
+10-12-23 Prevented the shell from generating a core dump when it sends itself
+ a termination signal because the last command terminated with that
+ signal. This prevents a core dump to be overwritten by the shell.
+10-12-22 A bug in the expansion of ${A[@]} ${B[@]}, introduced in 10-12-01
+ when A="" B=B has been fixed.
+10-12-21 +Use MS_3D in b_vpath() for setting win32 WoW mount defaults.
+10-12-17 A bug in the expansion of ${var:i:j} which caused a core dump when
+ i > ${#var} has been fixed.
+10-12-16 +sleep now treats . as decimal point even in locales that use comma.
+10-12-16 +typeset -M mapname was added to generalize on toupper and tolowwer
+ mapping as provided with wctrans().
+10-12-10 A bug in which typeset -l displayed namespaces as well as lower case
+ variables has been fixed.
+10-12-06 A bug in which a pipeline could terminate prematurely for a pipeline
+ whose right hand side is a builtin, and whose left hand side ends in
+ a simple command that has standard output redirected has been fixed.
+10-12-06 A bug in hexfloat assignments when the right hand side is a string
+ variable starting with 0x has been fixed.
+10-12-01 A bug in the expansion of ${$1+"$@"} which causes the last positional
+ parameter to disappear when it is empty has been fixed.
+10-12-01 A number of changes were made to reduce the startup time.
+10-11-29 When wait is interrupted by a signal that is caught, it now exits
+ with a non-zero exit status.
+10-11-29 When a variable is used directly in an arithmetic expression,
+ leading zeros no longer cause the value to be treated as an
+ octal constant. This was true in previous versions for justified
+ variables.
+10-11-29 An incorrect warning message was eliminated with the -n option for
+ arithmetic expressions with associative arrays.
+10-11-29 Some changes were made to slightly reduces startup time.
+10-11-24 A bug in which a name reference is make to arr[0] when arr is not
+ an array has been fixed.
+10-11-23 If a type definition is made without a compound variable assignment it
+ produces an error message and no longer shows up as a defined type.
+10-11-22 The handling of \ inside [...] for for shell and ~(E) patterns has
+ been fixed.
+10-11-22 A patch was made to pfsh to handle an error case.
+10-11-22 +Modified types defined in namespace so that they do not clash with
+ types in other namespaces. Types can be referenced using
+ .namespace.typename.
+10-11-22 A bug which caused functions addressed as .namespace.funct to not
+ work has been fixed.
+10-11-22 A bug in which if nr was a name reference to an unset associative
+ array subscript, then ${!nr} did not output the subscript correctly
+ has been fixed.
+10-11-18 A bug in which shcomp -n was not processing double quotes correctly
+ has been fixed.
+10-11-18 Fixed a bug in which typeset -T foo; typeset -T could cause a
+ core dump.
+10-11-17 Fixed a bug in which the error message for set -u could come out
+ garbelled.
+10-11-17 Modified the parser so that typeset -a var=(...) no longer checks
+ the first index for aliases and reserved words.
+10-11-17 A bug in which a subshell command consisted of only a for or until
+ command has been fixed.
+10-11-16 Fixed a bug in which typeset -u would display namespace variables
+ as well as upper case variables.
+10-11-16 A bug which could cause a core dump when unsetting a type variable
+ when there are references to type elements has been fixed.
+10-11-15 A bug which could cause a core dump when unsetting a compound
+ array variable when there are references to array subscripts has
+ been fixed.
+10-11-15 A bug in which using typeset -m to move an indexed array instance
+ to another array could cause the array to display incorrectly has
+ been fixed.
+10-11-12 A bug in which the unset discipline function for a type is called
+ when the type is initialized has been fixed.
+10-11-12 The sequences \< and \> are now preserved after patterns containing
+ ~(E) in ${var/pattern/string} expansions.
+10-11-11 A bug in typeset -m when the variables were compound arrary instances
+ has been fixed.
+10-11-10 A bug in output of a compound variable with types containing types
+ has been fixed.
+10-11-10 Fixed ``name=value export [-p]'' to list environment.
+10-11-09 shtests resets SIGPIPE to SIG_DFL for all tests.
+10-11-09 Fixed a bug in expansion of $"..." when used in assignments.
+10-11-09 Fixed a getaddrinfo() memory leak that didn't call freeaddrinfo()
+ after an interrupt.
+10-11-08 Modified the behavior of set -u so that the shell terminates with
+ error message when when var is unset with ${!var} and ${#var}.
+10-11-02 Fix a bug in which a signal received while in a subshell could be
+ ignored.
+10-10-26 Fix a bug where terminal interrupt was ignored while in vi/emacs
+ edit search mode.
+10-10-26 Fix $'a\0b'c to expand to 'ac'.
+10-10-26 Provide user defined round() if not in <math.h>.
+10-10-26 Fix bug where $((undefined_function(1))) dumped core.
+10-10-22 Provide user defined iszero() if not in <math.h>.
+10-10-22 Fixed a bug with BGX compile option that could cause the shell to
+ hang.
+10-10-22 Fixed a bug with user define math function on systems for which
+ char is unsigned.
+10-10-21 A bug in which function autoloaded in a function leaves a file open
+ has been fixed.
+10-10-20 Modified the behavior of set -u so that the shell terminates when
+ when var is unset with ${var op string} when op is #, % or /.
+10-10-20 Fixed a bug with the AUDIT option in which the audit file was not
+ not close-on-exec.
+10-10-20 +Made a number of changes and fixes for the NAMESPACE compile option
+ which as added on 10-06-09 but some problems still remain.
+10-10-15 Fixed a bug in which arithmetic functions (added on 10-03-24) did
+ not work when the function definition was in the same compound
+ command in which the function was referenced.
+10-10-13 A bug in which creating an associative array of compound variables
+ with no members as an element of a compound variable did not work
+ has been fixed.
+10-10-08 A bug in which killing the last command in a function defined
+ with function name, terminated the calling script has been fixed.
+10-10-08 A bug which could cause a core dump if IFS is unset inside a function
+ has been fixed.
+10-10-07 +To reduce unwanted side effects, invoking typeset without the export
+ option and without an assignment now causes the variables to be unset
+ if the variable is inherited from the environment.
+10-10-06 The closing brace for ${ command } is now a token no matter what
+ character follows it.
+10-10-04 The change for $'...' expansion on 10-08-09 did not expand parameters
+ contained in the error message and this has been fixed.
+10-10-04 A bug in which a declaration of indexed array (-a_ in a type
+ definition would be displayed as a compound indexed array (-C -a)
+ has been fixed.
+10-09-30 The C99 math function ldexp has been added.
+10-09-30 A bug with two dimensional arrays with expansion of the form
+ ${ref[0..5]} where ref is a nameref to array[i] has been fixed.
+10-09-29 A bug in which an eval with redirections invoked from a dot script
+ would not restore the file has been fixed.
+10-09-29 A bug in which loading a function from FPATH could leave a file
+ descriptor open has been fixed.
+10-09-28 +A new compile option SHOPT_FIXEDARRAY has been added and is being
+ evaluation. It allows fixed sized indexed arrays be to defined
+ using "typeset array[dim1][dim2]...[dimn]". Fixed sized arrays
+ are used the same way indexed arrays are. Currently, only fixed
+ arrays of fixed objects (float, int, and justifies objects) are
+ supported.
+10-09-22 A bug which could cause an exception when a function with static
+ variables was redefined has been fixed.
+10-09-21 A bug in the processing of (command&) which created a job in the
+ parent process has been fixed.
+10-09-21 A for loop optimization bug with arithmetic expression evaluation
+ has been fixed.
+10-09-21 A bug in which a recursive function containing a pipeline could
+ lead to an exception fixed after 8 levels of recursion has been
+ fixed.
+10-09-18 A bug in which the count of elements in an array was wrong leading
+ to an exception has been fixed.
+10-09-13 A bug which occurred when both xtrace and showme options where
+ specified in which the xtrace option disabled showme has been fixed.
+10-09-13 A bug in which creating a reference to an array variable with any
+ elements could cause subsequent array elements to be treated as
+ compound variables has been fixed.
+10-09-09 A bug which caused ((c.ar[x][y])) to be treated as a syntax error
+ has been fixed.
+10-09-08 A bug in the processing of references to multidimensional arrays
+ in arithmetic expressions has been fixed.
+10-09-08 A bug in the handling of multi-dimensional arrays which caused
+ the number of elements in each dimension to be incorrect has
+ been fixed.
+10-09-07 The change for messages on 10-08-09 did not handle message in
+ assignments and this has been fixed.
+10-09-07 A bug in the indentation of compound variables in arrays when
+ output with print -v has been fixed.
+10-09-07 A rare bug with indexed arrays when assigned a null string that could
+ cause a core dump has been fixed.
+10-09-03 A number of changes were made for jobs pools.
+10-08-31 typeset -p was modified to output name references after other
+ variables so that the output could be used as input.
+10-08-31 A bug with typeset -p in which variables with attributes but
+ without attributes were not displayed correctly has been fixed.
+10-08-27 +When running a subshell, the current pool is unset.
+10-08-27 A bug in which jobs started from within for or while lists in
+ interactive shells could generate completion messages has been fixed.
+10-08-25 Fixed a couple of bugs related to job pools.
+10-08-24 +[[ -e /dev/xxx/ ]] can be used to check whether special files of
+ those names are handled by the shell.
+10-08-24 A bug in the running of a compiled dot script in which only the
+ first command was executed has been fixed.
+10-08-23 A bug which sometimes caused a core dump with a configure script
+ has been fixed.
+10-08-20 A bug in command substitution which caused a configure script to
+ hang has been fixed.
+10-08-19 Eliminated unnecessary ; from output of compound variable with
+ typeset -p.
+10-08-17 Fixed a bug in command substitution in which under certain
+ circumstances a file whose size is a power of 2 plus one, and the last
+ character was not a new-line, could cause memory corruption.
+10-08-13 +Added static discipline functions to type similar to C++ static
+ class functions.
+10-08-11 A bug in time when applied to a pipeline in which the shell did
+ not wait for all elements of the pipeline to complete has been fixed.
+10-08-11 Restored sh_fmtq() quoting to not quote NAME= in NAME=VALUE.
+10-08-09 +Modified the expansion of message strings, $"...", so that they
+ are expanded each time they are referenced rather than expanding
+ them when the script is compiled or read in.
+10-08-06 +The process id for jobs in job pools is now of the form poolname.n
+ where n is the jobid in that pool. Commands that accept job names
+ or numbers now understand names in this format.
+10-08-05 A bug in which an assignment from within an arithmetic expression
+ inside a function would create a local variable has been fixed.
+10-08-04 A bug in the expanding of variables whose names contain multibyte
+ characters has been fixed.
+10-08-04 A bug which caused an exception when processing scripts compiled
+ with shcomp -n has been fixed.
+10-08-02 Tests using very small buffer sizes uncovered a number of bug most
+ connected with here documents which have been fixed.
+10-07-27 The format modifier , used for digit grouping with d and f formats
+ has been documented.
+10-07-26 cd '' now produces and error rather than changing to the current
+ directory.
+10-07-26 A bug in multi-byte locales which the last character of a
+ multi-byte character is a \ or pattern character which could occur
+ when the character was the last character of a command substitution
+ has been fixed.
+10-07-23 Another bug in the processing of ${var:offset;len} in multi-byte
+ locales when len is larger than the number of characters has been
+ fixed.
+10-07-23 Many coding changes have been made to eliminate most of the uses
+ of global variables in the shell code.
+10-07-22 Fixed a bug in which discipline functions were not being invoked
+ when it was invoked as ref.discipline where ref was a name reference
+ to an array instance.
+10-07-22 Fixed a bug in which discipline functions were not being invoked it
+ was invoked on a two dimensional array, i.e., arr[5][9].discipline.
+10-07-19 Fixed a buffering problem which occurred when running a script with
+ ssh and the parent ssh process is killed.
+10-07-14 Modified the parser to treat ((...)) inside [[...]] as ( (...) ) to
+ that it is a nested (...).
+10-07-09 A bug in the handling of process substitution inside command
+ substitution as part of a pipeline has been fixed.
+10-07-07 A bug in the output for compound variables containing
+ multi-dimensional arrays has been fixed.
+10-07-06 ksh now recovers from changes made by bash to the history file without
+ loosing history commands.
+10-06-25 A bug in which a large here document containing command substitutions
+ of a dynamically loaded function that contained a here document
+ could get truncated has been fixed.
+10-06-24 If after executing a script found in FPATH, if a function, builtin,
+ or type name corresponding to that script is not defined, the shell
+ now outputs an error message and returns value 126.
+10-06-23 Floating point functions that happened to return integer values
+ were being treated as if the function returned integers so that
+ integer division could be used instead of floating point division.
+10-06-22 Fixed a bug in earlier ksh93u in which an arithmetic assignment to a
+ variable in the global scope would instead create a local variable if
+ the variable had an attribute but did not have a value.
+10-06-18 Modified trap handling so that if the same signal is received when
+ executing the handler, it is deferred until the handler completes.
+10-06-16 Fixed a bug in which ulimit -v was setting the the cpu limit
+ on Linux.
+10-06-14 +The command 'typeset -T' now generates the list of type definitions
+ in a format that can be used as input to the shell.
+10-06-09 Put in patch from Solaris for output quoting with %q.
+10-06-09 +Made changes to the NAMESPACE compile option so that it now seems
+ to work. With this option, namespace <name> { command;} will
+ run command in the namespace .name so that all variables and
+ functions created by command are accessible outside the name
+ space via .name.var and .name.fun. Variables and functions that
+ are not in the namespace are not modified when running command.
+10-06-07 Change most internal interfaces to take Sh_t* argument.
+10-06-03 +Types can be loaded on first reference by putting definitions in
+ PFPATH.
+10-06-03 +The shell is now able to parse commands which use type statements
+ before the typeset -T command to define the type executes.
+10-06-03 A bug in the quoting for name reference declarations which did
+ not properly handle [ and ] in subscripts for associative arrays.
+10-06-02 A bug in which a discipline function defined by a type instance to
+ override the default was not being registered has been fixed.
+10-06-02 A bug in which read -C of an associative array of compound variables
+ was not working has been fixed.
+10-06-02 A bug in which the error message for an unset parameter with set -u
+ did not contain the name of the variable has been fixed.
+10-06-01 A bug in typeset -m for moving an indexed array instance to a variable
+ has been fixed.
+10-06-01 A bug in which caused memory to be freed twice when unset was called
+ for an indexed array that had get or set disciplines has been fixed.
+10-06-01 A bug in which the %b format of printf was not preserving NUL bytes
+ with \0 has been fixed.
+10-06-01 A bug in the handling of name references to array variables in
+ arithmetic expressions has been fixed.
+10-05-28 Fixed bugs in changing attributes for two dimensional arrays.
+10-05-28 Eliminated a few unreferenced variables and a reference to
+ uninitialized memory.
+10-05-27 Rewrote the subshell code to avoid using pipes an many cases.
+10-05-24 Fixed a bug which cause an exception when both -l and -s were
+ specified with typeset -i.
+10-05-21 Inputting of three dimensional indexed arrays with ( ( (...)...)...)
+ was not working and has been fixed.
+10-05-21 A bug in which adding the attributes -Ai to a variable via a name
+ reference could cause the value to display incorrectly has been fixed.
+10-05-21 A bug in which using $var inside ((...)) did not work when var was
+ a hex float variable.
+10-05-20 +The compile option SHOPT_EDPREDICT has been added. When this option
+ is on, as you type a line beginning with a # the following characters
+ are treated as a shell pattern and cause matching lines from the
+ history file to be displayed as a numbered list as you type.
+ You can scroll up and down this list or you can use <ESC>nTAB
+ to make this the current line (n defaults to 1 of omitted) or
+ <ESC>n<cr> to execute.
+10-05-20 A bug which caused an exception when multiple levels of composite
+ functions in arithemtic expressions has been fixed.
+10-05-19 <<< with an empty string no longer gives an error.
+10-05-19 A bug in arithmetic evaluation when a name reference to an array
+ instance was used has been fixed.
+10-05-14 A bug in which the shell treats a valid index array assignment,
+ typeset -a x=(foo (x=3;y=4) bar) as a syntax error has been fixed.
+10-05-13 A bug in creating name references to associative array variable
+ after a lookup of one of its elements has been fixed.
+10-05-12 Two bugs in the handling of function static type variables in
+ subshells have been fixed. One could cause an exception and the
+ other would leave side effects in the parent shell.
+10-05-10 A bug in which static variables in functions were not being saved and
+ restored properly when running subshells has been fixed.
+10-05-05 A bug in which print -v did not work correctly when an operand was an
+ indexed array element referring to a compound variable has been fixed.
+10-05-05 A change to improve performance by special casing empty string
+ assignments to avoid repeated malloc() and free().
+10-05-05 A bug in which creating a name reference to a non-existent associative
+ array element would create the array element has been fixed.
+10-05-04 A bug in which name references to static variables in the static
+ scope were not found has been fixed.
+10-04-30 Do not use socketpair() on systems that implement ioctl(I_PEEK)
+ on pipes.
+10-04-29 +When the current job pool is set, coprocess are run in a job pool.
+10-04-28 A type defined with a member foo that is an associative array without
+ elements followed by an expansion ${bar.foo[a]} and an assignment
+ bar.foo[a]=b, no longer indicates that ${#bar.foo[@]} has 0 members.
+10-04-27 Another bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-26 A type defined with a member that is an indexed array without elements
+ would behave as if the 0th element of each instance was defined after
+ a non-zero element was specified and this has been fixed.
+10-04-26 A bug in which types defined in a subshell were not undefined when
+ the subshell completed has been fixed.
+10-04-23 For file completion in commmand line editing, file names starting
+ with # are now escaped so that they are not treated as comments.
+10-04-23 A bug in which ${t.var:=value}, where t is an instance of a type
+ variable, could assign value to the type variable rather than to
+ the type instance has been fixed.
+10-04-23 +Added &| which can be used in place of | to have portions of a
+ pipeline executed in the pool.
+10-04-22 +The .sh.pool variable was added for use with job pools.
+10-04-22 A bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-20 A bug which corrupted one byte of memory when read was called with
+ reads that did not use a delimiter has been fixed.
+10-04-19 The display of a compound variable with an embedded array with
+ attributes was sometimes not working correctly and has been fixed.
+10-04-16 A bug in which attributes were not be propagated to elements in
+ an associative array has been fixed.
+10-04-15 A bug which caused scripts containing user defined math functions to
+ fail to compile with shcomp has been fixed.
+10-04-15 +Job pools have been added with the SHOPT_COSHELL compilation option.
+ A job pool allows a collection of background jobs to run either locally
+ or remotely and to be managed as a unit. The command '& name ...'
+ creates or uses a named job pool for subsequent background jobs.
+ kill, wait, and jobs allow the pool name as operands.
+10-04-14 A bug in which a coprocess connection could terminate prematurely
+ when running a nested subshell has been fixed.
+10-04-12 +Enumeration constants can be used in arithmetic expressions with the
+ ==, != and = operators when the left hand side is an enum variable
+ and the right hand side is an enumeration constant.
+10-04-07 A bug in which setting the trap on CHLD to ignore could cause
+ an incorrect exit status has been fixed.
+10-04-06 A bug in which LINENO was not incremented for a here-document when
+ the here-document word was followed by a comment has been fixed.
+10-04-06 The optimization that execs the last process of a script rather
+ than creating a new process has been removed when a trap on
+ interrupt has been set.
+10-04-06 Unsetting the 'C', 'A' or 'a' typeset attribute now produces an
+ error message rather than generating an exception.
+10-04-06 A bug in which .sh.name contained the subscript and .sh.subscript
+ was empty in some cases with discipline functions on array instances
+ has been fixed.
+10-04-05 A bug in the edit modes where preceding the interrupt character with
+ the literal next character did not work has been fixed.
+10-04-05 A bug in the creation of type instances of arrays which could cause
+ an exception has been fixed.
+10-03-30 A bug in the display of a compound variable containing an indexed
+ array of compound variables has been fixed.
+10-03-24 +Arithmetic functions can be defined using the shell function syntax,
+ 'function .sh.math.name x y z{...}' , where name is the function name
+ invoked within ((...)) and x y z are long double arguments passed
+ as name references. y and z are used for functions with two and
+ three arguments respectively. The value of the function is the value
+ of the long double .sh.value variable when the function returns.
+10-03-24 A bug in which integer division was mistakenly used when the
+ numerator was a binary operator with the first operand floating
+ point and the second integer, e.g. (.1**3)/3, has been fixed.
+10-03-24 The >; file operator was modified so that the temporary file is
+ created in the same physical directory as file.
+10-03-23 A warning message was added to sh -n when $var was used inside
+ ((...)) instead of var.
+10-03-19 fmin was added to the list of math function on the man page.
+10-03-19 Fixed the return value for unalias when the alias did not
+ exist.
+10-03-19 A bug in which the SHLVL variable exported the value it had on
+ input rather than the incremented value has been fixed.
+10-03-19 A bug which causes whence -q to go into an infinite loop has been
+ fixed.
+10-03-19 Removed space between Stopped message and (SIGTTIN) and (SIGTTOUT).
+10-03-17 Modified profile shell execution so that when builtins that
+ correspond to executable have extended attributes, they are
+ executed by pfksh instead of being treated as built-ins.
+10-03-16 A bug in whence -a which produced duplicate lines of output has
+ been fixed.
+10-03-16 A bug in the handling of process groups in monitor mode for
+ command substitutions has been fixed.
+10-03-15 Fixed a bug in which read -u[fd] could cause the shell to core
+ dump when fd was greater than open_max.
+10-03-15 +Modified the shell I/O so that the shell will not fail if the
+ ulimit for open_max is increased as part of the script.
+10-03-12 A bug in which a here-document containing command substitutions
+ that contained here-documents did not process correctly has been
+ fixed.
+10-03-12 A bug in which the terminal is not restored to canonical mode
+ after read times out when in a multibyte locale with no edit mode
+ enabled has been fixed.
+
+10-03-05 --- Release ksh93t+ ---
+10-03-05 A variable unset memory leak has been fixed and tests/leaks.sh
+ has been added to verify the fix.
+10-03-04 Documentation, comment, and diagnostic spelling typos corrected.
+10-02-14 Fix sh_getenv() initialization to cooperate with the 3d fs.
+10-02-12 A bug in which the get discipline function was not invoked for
+ associative array subscripts for unset array elements has been fixed.
+10-02-12 A bug which could occur if the last line of a script was an eval
+ that executed multiple commands has been fixed.
+10-02-02 A buffer overflow in read and another in binary type base64
+ encoding were fixed.
+10-01-20 A bug in the evaluation of arithmetic expression in which the
+ subscript was evaluated twice for $((foo[x++]++)) has been fixed.
+10-01-19 A workaround for a double-free of a trap in both a subshell and its
+ parent has been added.
+10-01-18 A bug in type handling of typeset -H has been fixed.
+10-01-15 The "adding empty subscript" warning now only emitted with -x set.
+10-01-01 A bug in the parser in which '$((case i in i):;esac);:))' was not
+ parsed correctly was fixed.
+10-01-01 A bug in the parser in which '$(( 2 , 3.6 ))' dumped core for locales
+ with radix char , and thousands separator . has been fixed.
+09-12-28 A bug in the handling of SIGCLD on systems that generated SIGCLD
+ while blocked waiting for process to complete has been fixed.
+09-12-24 ast setlocale() reworked to differentiate env var changes from user
+ override.
+09-12-18 A bug with the SHOPT_BGX option set which disabled traps for signals
+ < SIGCHLD when a trap for a signal > SIGCHLD was set has been fixed.
+09-12-18 A bug where [[ -v var ]] was incorrect for some variables (including
+ LC_* vars) has been fixed.
+09-12-15 A bug that produced a syntax error when a multibyte character
+ straddled a buffer boundary has been fixed.
+09-12-11 A bug where the subscript of an unset variable was not evaluated has
+ been fixed.
+09-12-09 A bug where shcomp dumped core on certain syntax errors has been fixed.
+09-12-07 A bug where a parent shell environment var reset in a subshell removed
+ the value in subsequent children of the parent shell has been fixed.
+09-12-04 A bug in which in some cases a trap in a function executed in
+ a subshell could trigger twice has been fixed.
+09-12-03 A bug in which SHLVL exported with some attributes could cause
+ the shell to abort at startup has been fixed.
+09-12-02 A bug with pipefail in which the shell could hang waiting for the
+ writer to complete before the last reader command has been fixed.
+09-11-30 A bug in which a trap could be inherited by the first element of
+ a pipeline when the command had more than 63 arguments that did
+ not contain any macro expansions has been fixed.
+09-11-19 When read from a terminal was called from with a while or for loop,
+ and an edit mode was on, a backspace or erase no longer will
+ overwrite the prompt.
+09-11-17 +Change .paths parse to handle BUILTIN_LIB=foo BUILTIN_LIB=foo-1.2.
+09-11-17 Inside a function, typeset foo.bar will bind foo to global variable
+ foo if local variable foo does not exist, instead of creating a
+ local variable.
+09-11-17 "read -n1" from the terminal has been fixed to read exactly one character.
+09-11-11 Job control now works for subshell commands, (...).
+09-11-11 If set -e is on for an interactive shell errors in special builtins
+ now cause the shell to exit.
+09-11-11 A bug in which an interrupt handler processed during the read builtin
+ when IFS did not contain a new line has been fixed.
+09-11-09 A bug in which a variable that has been unset in a subshell and then
+ exported from that subshell does not show up in the environment
+ has been fixed.
+09-11-02 ``,2'' is now a valid numeric constant for locales with
+ decimal_point=','.
+09-11-02 A bug where "return" in .profile did not restore the shell state
+ has been fixed.
+09-10-31 A bug that corrupted saved exit status when pids wrapped around has
+ been fixed.
+09-10-26 A bug in { LANG LC_ALL LC_category } ordering has been fixed in -last.
+09-10-16 A bug where notification to libast that the environment has changed
+ has been fixed.
+09-10-12 A bug in which a function loaded in a subshell could leave side
+ effects in the parent shell has been fixed.
+09-10-12 A bug in converting a printf %d operand to a number when the operand
+ contains multiple subscripts for the same variable has been fixed.
+09-10-09 A bug in the handling of the escape character \ in directory prefixes
+ in command completion has been fixed.
+09-10-09 $PATH processing has been changed to delay dir stat() and .paths
+ lookup until the directory is needed in the path search.
+09-09-28 Call the ast setlocale() intercept on unset too.
+09-09-24 A bug in which LANG=foo; LC_ALL=foo; unset LC_ALL; did not revert
+ LC_CTYPE etc. to the LANG value has been fixed.
+09-09-17 A bug in which unsetting SVLVL could cause a script invoked by
+ name without #! to core dump has been fixed.
+09-09-16 A bug in which a pipeline in a here-document could hang when the
+ pipefail option was on has been fixed.
+09-09-09 A bug in the processing of line joining in here documents which
+ occurred when a buffer began with <escape><new-line> has been fixed.
+09-09-09 +A leading ; with commands in a brace group or parenthesis group
+ no longer causes an error. It now is used for the "showme" option.
+09-09-09 A bug in which a subshell containing a background process could
+ block until the background process completed has been fixed.
+09-09-04 A bug in handing ${var[sub]}, where var is a nameref has been fixed.
+09-09-03 A bug which caused an index array to have the wrong number of elements
+ when it was converted from a compound variable by adding an another
+ element has been fixed.
+09-09-03 Specifying export for a compound variable now generates an error.
+09-09-02 $"..." localizations strings are no longer recognized inside `...`.
+09-09-01 A bug in the for loop optimizer in the handling of type static
+ variables has been fixed.
+09-09-01 An error message is not displayed when * and @ are used as subscripts.
+09-09-01 Several bugs in the processing for types that included an associative
+ array of another type has been fixed.
+09-09-01 A bug in the tracing of [[ a < b ]] and [[ a > b ]] has been fixed.
+09-08-26 The .sh.file variable was not being set for a script that was run
+ by name and didn't start with #! and this has been fixed.
+09-08-25 A bug in which a function called to deeply from command substitution
+ did not display an error message has been fixed.
+09-08-24 +When processing profiles, ksh93 now violates the POSIX standard and
+ treats &> as a redirection operator similar to bash.
+09-08-23 A bug in the handling of the trap on SIGPIPE that could lead to a
+ memory fault has been fixed.
+09-08-21 A bug in the handling of the comma operator in arithmetic expressions
+ that could cause a core dump on some systems has been fixed.
+09-08-20 A bug in which a compound variable containing an array of a type
+ that doesn't have any elements now expands correctly.
+09-08-19 A bug which disabled function tracing inside a function after
+ a call to another function has been fixed.
+09-08-19 A bug in which initializing a compound variable instance to another
+ compound variable by name has been fixed.
+09-08-18 A bug in which compound variable instances could be lost after
+ an instance that invoked a type method discipline has been fixed.
+09-08-18 A bug in which a discipline function for a type applied to an
+ array instance when invoked in a function ignored the subscript
+ has been fixed.
+09-08-18 A scoping error with variables in arithmetic expression with
+ type variables when reference with a name reference has been fixed.
+09-08-10 Several memory leaks were fixed primarily related to subshells.
+09-08-06 A bug in which setting the trap on CHLD to ignore could cause
+ a script to hang has been fixed.
+09-07-08 A bug in the processing of name reference assignments when it
+ contained pattern expansions with quoting has been fixed.
+09-06-22 +The default width for typeset -X has been changed so that there
+ should be no loss of precision when converting to a string.
+09-06-19 A bug in the printing of array elements for binary variables with
+ printf %B has been fixed.
+09-06-19 A bug which caused a core dump with trap DEBUG set with an array
+ assignment with no elements has been fixed.
+09-06-19 A bug with read with typeset -b -Z<num> has been fixed.
+09-06-19 Two bugs related to read -b for array variables has been fixed.
+09-06-19 A bug with typeset for compound variables containing arrays of
+ compound variables has been fixed.
+09-06-18 A bug in appending a compound variable to a an indexed array of
+ compound variables has been fixed.
+09-06-18 A bug which occurs when appending a compound variable to an indexed
+ array element has been fixed.
+09-06-18 Setting VISUAL to a value other than one ending in vi or emacs will
+ no longer unset the edit mode.
+09-06-17 A bug in typeset -m when moving a local compound variable to a
+ global compound variable via a name reference has been fixed.
+09-06-17 A bug in appending to nodes of an array of compound variables when
+ addressing them via nameref has been fixed.
+09-06-17 A bug in typeset -p var, when var is an array of compound variables
+ in which the output only contained on array element has been fixed.
+09-06-17 The prefix expansion ${!y.@} now works when y is a name
+ reference to an element of an array.
+09-06-16 Traps on signals that are ignored when the shell is invoked
+ no longer display. Previously they were ignored as required but
+ would be listed with trap -p.
+09-06-12 A bug in vi edit mode in which hitting the up arrow key at the
+ end of a line longer than 40 characters which caused a core dump
+ has been fixed.
+09-06-11 A bug in which "eval non-builtin &" would create two processes,
+ one for the & and another for non-builtin has been fixed.
+09-06-08 When var is an identifier and is unset, ${var} no longer tries to
+ run command substitution on the command var.
+09-06-08 +Process substitution arguments of the form <(command) can now be
+ used following the < redirection operator to redirect from command.
+09-05-13 A bug in which redirections of the form 2>&1 1>&5 inside command
+ substitution could cause the command substitution to hang has been
+ fixed.
+09-05-12 To conform with POSIX, the -u option only checks for unset variables
+ and subscript elements rather than checking for all parameters.
+09-05-12 A bug which could cause a core dump when a variable whose name
+ begins with a . was referenced as part of a name reference inside
+ a function has been fixed.
+09-05-01 A bug that caused a core dump when SIGWINCH was received and
+ both vi and emacs mode were off has been fixed.
+09-04-22 +Default alias compound='typeset -C' added.
+09-04-15 A bug that caused ${...;} to hang for large files has been fixed.
+09-04-08 A change was made in the -n option which printed out an incorrect
+ warning with <>.
+09-04-07 The emacs edit command M-_ and M_. and the vi command _ was fixed
+ to handle the case there there is no history file.
+09-04-05 A bug in handling new-lines with read -n has been fixed.
+09-04-05 The ENV variable defaults the the file named by $HOME/.kshrc rather
+ then to the string $HOME/.kshrc.
+09-03-31 A bug in which a nested command substitution with redirections could
+ leave a file descriptor open has been fixed.
+09-03-24 +ksh now only uses the value of the _ variable on startup if it can
+ verify that it was set by the invoking process rather than being
+ inherited by some other ancestor.
+09-03-24 +When ksh is invoked without -p and ruid!=euid, and the shell is
+ compiled without SHOPT_P_UID or ruid<SHOPT_P_UID, the shell now
+ enables the -p option. The previous version instead set the
+ euid to the ruid as it does for set +p.
+09-03-24 +When SHOPT_P_UID is defined at compile time and the shell is started
+ without -p and ruid!=euid and ruid>=SHOPT_P_UID then euid is set
+ to ruid. A bug that did the wrong test (ruid<SHOPT_P_UID) was fixed.
+09-03-17 +The sleep(1) builtin now accept and ISO 8601 PnYnMnDTnHnMnS
+ duration or date(1) compatible date/time operand.
+09-03-10 If a variable that was left or right justified or zero-filled was
+ changed with a typeset statement that was left or right justified
+ or zero-filled, then the original justification no longer affects
+ the result.
+09-03-10 A bug in the handling of traps when the last command in a script
+ is a subshell grouping command has been fixed.
+09-03-03 A bug in which an expansion of the form ${!prefix@} could generate
+ an exception after the return from a function has been fixed.
+09-02-02 A bug in restricted mode in which the value of ENV could be
+ changed from within a function has been fixed.
+09-02-02 A bug in which an erroneous message indicating that a process
+ terminated with a coredump has been fixed.
+09-02-02 The exit status when exit was called without an argument from
+ a signal handler was incorrect and has been fixed.
+09-02-02 A bug in which a function autoloaded in a subshell could cause
+ a core dump when the subshell completed has been fixed.
+09-02-02 A bug in which 2>&1 inside a command substitution wasn't working
+ correctly has been fixed.
+09-02-02 A bug in the call stack of arithmetic function with 2 args
+ returning int has been fixed.
+09-01-30 A bug in which 'eval print \$0' inside a function was giving the
+ wrong value for $0 has been fixed.
+09-01-28 A bug in which a command substitution could return an exit status
+ of 127 when the pipefail option is enabled has been fixed.
+09-01-26 ksh93 now generates an error message if you attempt to create
+ a global name reference to a local variable.
+09-01-26 +The [[ -v var ]] operator was modified to test for array elements.
+09-01-23 +The redirection operator <>; was added. It is similar to <>
+ except that if the command it is applied to succeeds, the file
+ is truncated to the offset at the command completion.
+09-01-23 The default file descriptor for <> was changed to 1.
+09-01-20 A bug in which the exit status specified in an exit trap was
+ not used when a process terminated with a signal has been fixed.
+09-01-19 A bug in which a signal whose default action is to terminate
+ a process could be ignored when the process is running a sub-shell
+ has been fixed.
+09-01-19 A bug in which sending SIGWINCH to a process that reads from a pipe
+ could cause a memory fault has been fixed.
+09-01-16 +The -R unary operator was added to [[...]] and test to check whether
+ a variable is a name reference.
+09-01-16 +The -v unary operator was added to [[...]] and test to check whether
+ a variable is set.
+09-01-14 The unset built-in was modified to return 0 exit status when
+ unsetting a variable that was unset to conform with the POSIX
+ standard.
+09-01-14 The unset built-in was modified to continue to unset variables
+ after encountering a variable that it could not unset to
+ conform to the POSIX standard.
+09-01-14 The parameter expansion ${x+value} no longer expands the value of
+ the variable x when determining whether x is set or not.
+09-01-13 A bug in which background jobs and pipelines that were not waited
+ for could, in rare instances, cause the shell to go into an infinite
+ loop or fail has been fixed.
+09-01-06 A bug in indexed arrays of compound variables in which referencing
+ non-existent sub-variable in an arithmetic expression could cause
+ the sub-variable to be created has been fixed.
+09-01-05 A bug in which the \ character did not escape extended regular
+ expression pattern characters has been fixed.
+08-12-24 A bug in which killing the last element of a pipe did not cause
+ a write to the pipe to generate a SIGPIPE has been fixed.
+08-12-19 A bug which could cause command substitution to hang when the
+ last element of a pipeline in a command substitution was a built-in
+ and the output was more that PIPE_BUFF.
+08-12-18 A bug which occurs when a here documented marker embedded in a
+ command substitution occurs on a buffer boundary has been fixed.
+08-12-17 A bug in the output of typeset -p for variables that had attributes
+ but did not have a value has been fixed.
+08-12-16 A bug in which a name reference to a name reference variable that
+ references an array element has been fixed.
+08-12-16 A bug in which a variable given both the -A and -C attribute along
+ with an initial assignment didn't work correctly has been fixed.
+08-12-10 The [[ -t fd ]] test was fixed to handle fd>9.
+08-12-10 A bug where function stack misalignment could cause a bus error
+ has been fixed.
+08-12-09 Command completion was changed to use \ to quote special characters
+ instead of quoting the argument in single quotes.
+08-12-07 A bug in typeset -m which occurred when the target node was an
+ associative array element has been fixed.
+08-12-07 A timing bug on some systems (for example darwin), that could
+ cause the last process of a pipeline entered interactively to fail
+ with an "Exec format error" has been fixed.
+08-12-04 +SHOPT_BGX enables background job extensions. Noted by "J" in
+ the version string when enabled. (1) JOBMAX=n limits the number
+ of concurrent & jobs to n; the n+1 & job will block until a
+ running background job completes. (2) SIGCHLD traps are queued
+ so that each completing background job gets its own trap; $! is
+ set to the job pid and $? is set to the job exit status at the
+ beginning of the trap. (3) sleep -s added to sleep until the time
+ expires or until a signal is delivered.
+08-12-04 The sign of floating point zero is preserved across arithmetic
+ function calls.
+08-12-04 A bug that caused print(1) to produce garbled stdout/stderr
+ output has been fixed.
+08-12-04 A bug in which printf "%d\n" "'<euro>'" did not output the
+ numerical value of the EURO symbol, 8354, has been fixed.
+08-11-24 + /dev/fd* and /dev/std* redirections are first attempted with
+ open() to preserve seek semantics; failing that the corresponding
+ file descriptors are dup()'d.
+08-11-20 A bug which could cause a core dump if a function compiled with
+ shcomp was found has been fixed.
+08-11-20 A bug in which jobs were not cleared from the jobs table for
+ interactive shells when the pipefail option is on has been fixed.
+08-11-11 A bug in which a field that was unset in a type definition and later
+ set for an instance could appear twice when displaying the variable
+ has been fixed.
+08-11-11 A bug in which running a simple command & inside a function would
+ not return the correct process id has been fixed.
+08-11-10 A bug in which the exit status of a command could be lost if the pid
+ was that of the most recent command substitution that had completed
+ has been fixed.
+08-11-10 The maximum depth for subshells has been increased from 256 to 65536.
+08-11-06 A bug which could cause a core dump when the _ reference variable was
+ used as an embedded type with a compound assignment has been fixed.
+
+08-10-31 --- Release ksh93t ---
+08-10-31 Variable scoping/initialization bugs that could dump core were fixed.
+08-10-24 The lexer now accepts all RE characters for patterns prefixed
+ with a ksh ~(...) option expression.
+08-10-24 +For ${var/pat/sub} \0 in sub expands to the text matched by pat.
+08-10-18 A bug in array scoping that could dump core has been fixed.
+08-10-10 read -n and -N fixed to count characters in multibyte locales.
+08-10-10 A bug that mishandled _.array[] type references has been fixed.
+08-10-09 +${.sh.version} now contains a concatenation of the following (after
+ 'Version') denoting compile time features:
+ A SHOPT_AUDIT
+ B SHOPT_BASH
+ L SHOPT_ACCT
+ M SHOPT_MULTIBYTE
+08-10-09 A bug that caused subshell command substitution with redirection
+ to hang has been fixed.
+08-10-08 Output errors, other than to stderr, now result in a diagnostic.
+08-10-08 ksh93 now supports types that contain arrays of other types as
+ members. Earlier versions core dumped in this case.
+08-10-05 A bug which caused the shell to emit a syntax error for an arithmetic
+ statement of the form (( var.name[sub] = value)) has been fixed.
+08-10-01 A bug that caused subshell command substitution to hang has
+ been fixed.
+08-09-29 When the -p export option of typeset is used with other options,
+ only those variables matching the specified options are displayed.
+08-09-29 When the shell reads the environment and finds variables that are
+ not valid shell assignments, it now passes these on to subsequent
+ commands rather than deleting them.
+08-09-29 A bug in the display of compound variables containing an indexed
+ array of compound variables has been fixed.
+08-09-29 A bug in the display of compound variables containing an associative
+ array with a subscript containing a . in the name has been fixed.
+08-09-26 A core dump in the subshell environment restore has been fixed.
+08-09-24 $(...) has been fixed to properly set the exit status in $?.
+08-09-23 $(<...) with IFS=$'\n\n' has been fixed to retain all but the last
+ of multiple trailing newlines.
+08-09-23 The -p option to typeset when used with other attributes, restricts
+ the output to variables with the specified attributes.
+08-09-22 A bug that sometimes lost the exit status of a job has been fixed.
+08-09-21 A bug that retained trailing command substitution newlines in
+ cases where the command caused the shell to fork has been fixed.
+08-09-19 type, whence -v, and command -v were fixed to comply with POSIX
+ by writing 'not found' diagnostics to the standard error.
+08-09-18 test and [...] were fixed to comply with POSIX in the case
+ of test '(' binop ')' where binop is a valid binary test operator.
+08-09-16 +If a method discipline named create is specified when defining a
+ type, this function will be called when an instance is created.
+08-09-15 +The variable _ is now set as a reference to the compound variable
+ when defining a compound variable or a type.
+08-09-10 The shell now prints an error message when the type name specified
+ for an indexed array subscript is not an enumeration type.
+08-09-10 A bug in which a subshell that spawned a background process could
+ loose output that was produced after the foreground completed
+ has been fixed.
+08-09-10 A timing bug on some systems that could cause coprocesses started by a
+ subshell to not clean up and prevent other coprocesses has been fixed.
+08-09-09 The typeset -m option is now able to rename array elements from
+ the same array.
+08-09-09 The exit status of 2 from the DEBUG trap causes the next command
+ to be skipped. An exit value of 255 from a DEBUG trap called from
+ a function causes the function to return.
+08-09-08 A bug in which a coprocess created in a subshell that did not
+ complete when the subshell terminated could prevent a coprocess
+ from being created in the parent shell has been fixed.
+08-09-05 An assignment of the form name1=name2 where name1 and name2
+ are both compound variables causes name1 to get a copy of name2.
+ name1+=name2 causes name2 sub-variables to be appended to name1.
+08-09-05 A bug in which unsetting a compound variable did not unset all
+ the sub-variables has been fixed.
+08-09-01 A bug in the subshell cleanup code that could cause SIGSEGV has
+ been fixed.
+06-08-26 +The SHLVL variable which is an environment variable used by bash
+ and zsh that gets incremented when the shell starts.
+08-08-25 +For an indexed array, a negative subscript now refers to offsets
+ from the end so that -1 refers to the last element.
+08-08-24 An alignment error for shorts on 64 bit architectures has been fixed.
+08-08-22 If oldvar is a compound variable, typeset -C newvar=oldvar creates
+ newvar as a copy of oldvar.
+08-08-19 +The ALRM signal no longer cause the sleep builtin to terminate.
+08-08-13 When used in an arithmetic expression, the .sh.version variable
+ now produces a number that will be increasing for each release.
+08-08-11 A bug in which type instantiation with a compound assignment in
+ a dot script in which the type is defined has been fixed.
+08-08-07 +The -m option has been added to typeset to move or rename a
+ variable. Not documented yet.
+08-08-06 A bug in read when used in a loop when a prompt was specified
+ when reading from a terminal has been fixed.
+08-08-01 A bug with the pipefail option in which a nested pipeline could
+ cause an asynchronous command to block has been fixed.
+08-08-01 A for loop optimizer bug that treats .sh.lineno as an invariant
+ has been fixed.
+08-07-30 A bug in which expanding compound variable that had a get discipline
+ from with a here document could cause a syntax error has been fixed.
+08-07-18 A bug in which a nameref caused a local variable to be created
+ rather than binding to an existing variable in the global scope
+ has been fixed.
+08-07-17 A bug which occurred when a nameref was created from within a
+ function that was part of a pipeline has been fixed.
+08-07-14 +The compile option SHOPT_STATS was added. With this option the
+ compound variable .sh.stats keeps usage statistics that could help
+ with performance tuning.
+08-07-10 +The output of set now always uses a single line for each variable.
+ For array variables, the complete set of values is now displayed.
+08-07-09 +The typeset -C option can be used with arrays to indicate that
+ each element should default to a compound variable.
+08-07-08 +The %B format now outputs compound variables and arrays. The
+ alternate flag # can be used to cause output into a single line.
+08-07-03 When the window change signal, WINCH, is received, the current
+ edit line is redrawn in place.
+08-07-01 A bug in the handling of shared variables when inside an embedded
+ type has been fixed.
+08-06-29 A bug in multiline edit mode which occurred when the prompt length
+ was three characters or less has been fixed.
+08-06-23 A bug in which the SIGCLD was not be triggered when background
+ jobs completed has been fixed.
+08-06-23 _KSH_VERSION added as a name reference to .sh.version.
+08-06-20 type now outputs 'special builtin' for special builtins.
+08-06-19 A couple of bugs in multi-dimensional arrays have been fixed.
+08-06-19 A bug in which a syntax error in a dot script could generated
+ a syntax error in the next subsequent command has been fixed.
+08-06-17 Reduced the maximum function call depth to 2048 to avoid exceptions
+ on some architectures.
+08-06-16 A bug in which printf "%B" could generate an exception when the
+ specified variable was not set has been fixed.
+08-06-16 +When typeset -p is followed by variable names, it now displays
+ the attributes names and values for the specific names.
+08-06-14 A bug that could effect the drawing of the screen from multiline
+ emacs or gmacs mode when walking up the history file has been fixed.
+08-06-13 A bug in which a compound variable defined in a subshell could
+ have side effects into the parent shell has been fixed.
+08-06-13 A number of bugs related to using .sh.level to set the stack from
+ for DEBUG traps have been fixed.
+08-06-13 +The .sh.lineno variable has been added. When .sh.level is changed
+ inside a DEBUG trap, the .sh.lineno contains the calling line number
+ for the specified stack frame.
+08-06-13 The .sh.level variable has been documented and now works.
+08-06-11 +The -C option has been added to read for reading compound command
+ definitions from a file.
+08-06-11 +The . command is now permitted inside a compound command definition.
+ The dot script can contain declaration commands and dot commands.
+08-06-09 +Add -C option to typeset so that typeset -C foo, is equivalent
+ to foo=().
+08-06-09 Added -n warning message for typeset option orderings that are valid
+ with ksh88 but not valid with ksh93, for example Lx5.
+08-06-09 A bug in which the return value for an assignment command containing
+ a command substitution with that failed was zero when the assignment
+ contained redirections has been fixed.
+08-06-09 A bug in the quoting of $ inside a ERE pattern ~(E)(pattern)
+ has been fixed.
+08-06-06 A bug when processing `` command substitution with the character
+ sequence \$' has been fixed.
+08-06-02 +When defining a type, the typeset -r attribute causes this field
+ to be required to be specified for each instance of the type and
+ does not allow a default value.
+08-06-02 Several bugs in which compound variables were modified by
+ subshells have been fixed.
+08-05-22 +The ceil function has been added to the math functions.
+08-05-21 A bug in which a name reference defined in a function and passed
+ as an argument to another function could cause an incorrect binding.
+08-05-21 A bug in freeing compound variables that are local to functions
+ has been fixed.
+08-05-19 +The array expansions ${array[sub1..sub2]} and ${!array[sub1..sub2]}
+ to expand to the value (or subscripts) for array between sub1 and
+ sub2 inclusive. For associative arrays, the range is based on
+ location in the POSIX locale. The .. must be explicit and cannot
+ result from an expansion.
+08-05-15 The trap on SIGCLD is no longer triggered by the completion of
+ the foreground job as with ksh88.
+08-05-14 A bug in the implementation of the editing feature added on
+ 07-09-19 in emacs mode has been fixed.
+08-05-12 A bug in processing the test built-in with parenthesis has been
+ fixed.
+08-05-12 The unset built-in now returns non-zero when deleting an array
+ subscript that is not set.
+08-05-08 +Changing the value of HISTFILE or HISTSIZE will cause the old
+ history file to be close and reopened with the new name or size.
+08-05-08 When FPATH is changed functions that were found via a path search
+ will be searched for again.
+08-05-08 A parser bug in which reserved words and labels were recognized
+ inside compound indexed array assignment after a new-line has
+ been fixed.
+08-05-07 A bug in getopts when handling numerical option arguments has
+ been fixed.
+08-05-07 +The typeset -S option was added for variables outside type
+ definitions to provide a storage class similar to C static
+ inside a function defined with function name. When outside
+ type definitions and outside a function, the -S option cause
+ the specified variable so be unset before the assignment and
+ before the remaining attributes are supplied.
+08-05-07 A bug that affected the cursor movement in multiline mode when
+ a character was deleted from near the beginning of the any
+ line other than the first.
+08-05-01 In multiline edit mode, the refresh operation will now clear
+ the remaining portion of the last line.
+08-05-01 A bug in computing prompt widths for the edit modes for prompts
+ with multibyte characters has been fixed.
+08-05-01 A bug in the multiline edit mode which could cause the current
+ line to be displayed incorrectly when moving backwards from third
+ or higher line to the previous line has been fixed.
+08-05-01 A bug in which options set in functions declared with the function
+ name syntax were carried across into functions invoked by these
+ functions has been fixed.
+08-04-30 A bug which could cause a coprocess to hang when the read end
+ is a builtin command has been fixed.
+08-04-30 +The emacs and vi editors have been modified to handle window
+ change commands as soon as they happen rather than waiting for
+ the next command.
+08-04-28 A bug in which ${!x} did not expand to x when x was unset has been
+ fixed.
+08-04-27 A bug in which the assignment x=(typeset -a foo=([0]=abc)) created
+ x.foo as an associative array has been fixed.
+08-04-25 A bug in which $# did not report correctly when there were more
+ than 32K positional parameters has been fixed.
+08-04-04 Choose the name _ as the sub-variable that holds type or instance
+ specific data used by discipline functions.
+08-03-27 A bug in which the terminal group was not given back to the parent
+ shell when the last part of a pipeline was handled by the parent shell
+ and the other parts of the pipeline complete has been fixed.
+ The symptom was that the pipeline became uninterruptable.
+08-03-25 A bug in restricted mode introduced in ksh93s that caused scripts
+ that did not use #! to executed in restricted mode has been fixed.
+08-03-25 A bug in which the pipefail option did not work for a pipeline
+ within a pipeline has been fixed.
+08-03-24 A bug in which OPTIND was not set correctly in subshells has
+ been fixed.
+08-03-24 A bug which could cause a memory exception when a compound variable
+ containing an indexed array with only element 0 defined was expanded.
+08-03-20 A bug in which ${!var[sub].*} was treated as an error has been fixed.
+08-03-20 Associative array assignments of the form ([name]=value ...)
+ now allow ; as well as space tab and new line to separate elements.
+08-03-18 A buffering problem in which standard error was sometimes
+ not flushed before sleep has been fixed.
+08-03-17 A bug in which a signal sent to $$ while in a subshell would be
+ sent to the subshell rather than the parent has been fixed.
+08-03-17 + A --default option added to set(1) to handle set +o POSIX semantics.
+ set --state added as a long name alias for set +o.
+08-03-14 A bug in which using monitor mode from within a script could
+ cause the terminal group to change has been fixed.
+08-03-10 The new ${...} command substitution will treat the trailing }
+ as a reserved word even if it is not at the beginning of a command,
+ for example, ${ date }.
+08-03-10 If the name of the ENV begins with /./ or ././ then the
+ /etc/ksh.kshrc file will not be executed on systems that support
+ this interactive initialization file.
+08-03-07 A bug in which ksh -i did not run the ENV file has been fixed.
+08-03-07 A bug in which ulimit did not always produce the same output as
+ ulimit -fS has been fixed.
+08-03-04 A bug in multiline mode in emacs and vi mode which could cause the
+ cursor to be on the wrong line when interrupt was hit has been fixed.
+08-03-03 The change made in ksh93s+ on 07-06-18 in which braces became
+ optional for ${a[i]} inside [[...]] was restored in the case
+ where the argument can be a pattern.
+08-03-03 A bug in which creating a name reference to an associative array
+ instance would fail when the subscript contained characters [ or
+ ] has been fixed.
+08-02-29 +The redirection operator >; has been added which for non-special
+ files, generates the output in a temporary file and writes the
+ specified file only of the command has completed successfully.
+08-02-15 A bug in ${var/pattern/string} for patterns of the form ?(*) and +(*)
+ has bee fixed.
+08-02-07 A bug in which test \( ! -e \) produced an error has been fixed.
+08-02-14 +The typeset -a option can now optionally be followed by the name
+ of an enumeration type which allows subscripts to be enumerations.
+08-02-14 +The enum builtin which creates enumeration types has been added.
+08-02-12 The backoff logic when there are no more processes has been fixed.
+08-02-07 The -X option has been added to typeset. The -X option creates
+ a double precision number that gets displayed using the C99 %a
+ format. It can be used along with -l for long double.
+08-01-31 The -T option to typeset has been added for creating typed
+ variables. Also the -h and -S options have been added to
+ typeset that are only applicable when defining a type.
+08-01-31 The prefix expansion operator @ has been added. ${@name}
+ expands to the type of name or yields the attributes.
+07-11-15 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-10-03 A bug in which : was not allowed as part of an alias name has been
+ fixed.
+07-09-26 A bug in which appending a compound variable to a compound variable
+ or to an index array didn't work has been fixed.
+07-09-19 In both emacs and vi edit mode, the escape sequence \E[A (usually
+ cursor up, when the cursor is at the end of the line will fetch
+ the most recent line starting with the current line.
+07-09-18 The value of ${!var} was correct when var was a reference to an
+ array instance.
+07-09-18 The value of ${!var[sub]} was not expanding to var[sub] and this
+ was fixed. It also fixed ${name} where name is a name reference
+ to var[sub].
+07-09-18 +It is now legal to create a name reference without an initialization.
+ It will be bound to a variable on the first assignment.
+07-08-30 +A discipline function can be invoked as ${x.foo} and is equivalent
+ to ${ x.foo;} and can be invoked as x.foo inside ((...)).
+07-07-09 A bug in which typeset -a did not list indexed arrays has been
+ fixed.
+07-07-03 +The command substitution ${ command;} has been added. It behaves
+ like $(command) except that command is executed in the current
+ shell environment. The ${ must be followed by a blank or an
+ operator.
+
+08-04-17 --- Release ksh93s+ ---
+08-04-17 A bug in which umask was not being restored correctly after a
+ subshell has been fixed.
+08-04-15 A bug in which sending a STOP signal to a job control shell started
+ from within a shell function caused cause the invoking shell to
+ terminate has been fixed.
+08-04-11 A bug which caused $(exec > /dev/null) to go into an infinite loop
+ has been fixed.
+08-03-27 A bug in which typeset -LZ was being treated as -RZ has been fixed.
+08-03-06 A bug with ksh -P on systems that support the the profile shell,
+ in which it would exit after running a non-builtin has been fixed.
+08-01-31 A bug in which command substitution inside ((...)) could cause
+ syntax errors or lead to core dumps has been fixed.
+08-01-17 A bug in which discipline functions could be deleted when invoked
+ from a subshell has been fixed.
+08-01-17 A bug in which a command substitution consisting only of
+ assignments was treated as a noop has been fixed.
+08-01-17 A bug in which discipline functions invoked from withing a
+ compound assignment could fail has been fixed.
+08-01-16 Incomplete arithmetic assignments, for example ((x += )), now
+ generate an error message.
+08-01-16 A bug in which a set discipline defined for a variable before
+ an array assignment could cause a core dump has been fixed.
+08-01-03 A bug in on some systems in which exit status 0 is incorrectly
+ returned by a process that catches the SIGCONT signal is stopped
+ and then continued.
+07-12-13 A race condition in which a program that has been stopped and then
+ continued could loose the exit status has been fixed.
+07-12-12 Code to check for file system out of space write errors for all
+ writes has been added.
+07-12-11 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-12-06 A bug in the emacs edit mode when multiline was set that output
+ a backspace before the newline to the screen has been fixed.
+07-12-04 A bug in which using <n>TAB after a variable name listing expansion
+ in the edit modes would cause the $ to disappear has been fixed.
+07-11-28 A bug in which setting IFS to readonly could cause a subsequent
+ command substitution to fail has been fixed.
+07-11-27 A work around for a gcc 4.* C99 "feature" that could cause a job
+ control shell to go into an infinite loop by adding the volatile
+ attribute to some auto vars in functions that call setjmp().
+07-11-27 A bug in which the shell could read ahead on a pipe causing the
+ standard input to be incorrectly positioned has been fixed.
+07-11-27 A bug in which compound variable UTF-8 multibyte values were not
+ expanded or traced properly has been fixed.
+07-11-21 A bug where an unbalanced '[' in a command argument was not treated
+ properly has been fixed.
+07-11-15 A bug in which compatibility mode (no long option names) getopts(1)
+ incorrectly set the value of OPTARG for flag options has been fixed.
+07-11-15 A bug in which "hash -- name" treated "--" as an invalid name operand
+ has been fixed.
+07-11-15 typeset now handles "-t -- [-r] [--]" for s5r4 hash(1) compatibility.
+07-11-15 A bug in which the umask builtin mis-handled symbolic mode operands
+ has been fixed.
+07-11-15 Bugs in which shell arithmetic and the printf builtin mis-handled the
+ signs of { -NaN -Inf -0.0 } have been fixed.
+07-11-15 +The full { SIGRTMIN SIGRTMIN+1 ... SIGRTMAX-1 SIGRTMAX } range
+ of signals, determined at runtime, are now supported.
+07-11-15 A bug in which creating an index array with only subscript 0 created
+ only a simple variable has been fixed.
+07-11-14 A bug in which appending to an indexed array using the form
+ name+=([sub]=value) could cause the array to become an associative
+ array has been fixed.
+07-11-14 A bug in which typeset without arguments could coredump if a
+ variable is declared as in indexed array and has no elements has
+ been fixed.
+07-11-14 A bug in which creating a local SECONDS variable with typeset in
+ a function could corrupt memory has been fixed.
+07-11-14 A bug which could cause a core dump when a script invoked by name
+ from a function used compound variables has been fixed.
+07-11-05 A bug in which printf %d "'AB" did not diagnose unconverted characters
+ has been fixed.
+07-11-05 printf %g "'A" support added for all floating point formats.
+07-11-01 A bug in which typeset -f fun did not display the function definition
+ when invoked in a subshell has been fixed.
+07-10-29 The sleep builtin was fixed so that all floating point constants
+ are valid operands.
+07-10-10 A bug in which the locale was not being restored after
+ LANG=value command has been fixed.
+07-09-20 A bug in which a nameref to a compound variable that was local
+ to the calling function would not expand correctly when displaying
+ is value has been fixed.
+07-09-19 A bug which cause cause a core dump if .sh.edchar returned
+ 80 characters or more from a keyboard trap has been fixed.
+07-09-14 A bug in which could cause a core dump when more than 8 file
+ descriptors were in use has been fixed.
+07-09-10 A bug in which creating a name reference to an instance of
+ an array when the array name is itself a reference has been fixed.
+07-09-10 The file completion code has been modified so that after an = in
+ any word, each : will be considered a path delimiter.
+07-09-06 A bug in which subprocess cleanup could corrupt the malloc() heap
+ has been fixed.
+07-08-26 A bug in which a name reference to an associative array instance
+ could cause the subscript to be evaluated as an arithmetic expression
+ has been fixed.
+07-08-22 A bug in which the value of an array instance was of a compound
+ variable was not expanded correctly has been fixed.
+07-08-14 A bug which could cause a core dump when a compound assignment was
+ made to a compound variable element with a typeset -a attribute
+ has been fixed.
+07-08-08 A bug in which a trap ignored in a subshell caused it to be
+ ignored by the parent has been fixed.
+07-08-07 A bug in which the set command would generated erroneous output
+ for a variable with the -RZ attribute if the variable name had been
+ passed to a function has been fixed.
+07-08-02 A bug in which read x[1] could core dump has been fixed.
+07-08-02 A second bug in which after read x[sub] into an associative array
+ of an element that hasn't been assigned could lead to a core dump
+ has been fixed.
+07-07-31 A bug in which a pipeline that completed correctly could have
+ an exit status of 127 when pipefail was enabled has been fixed.
+07-07-09 +The SHOPT_AUDIT compile option has been added for keyboard logging.
+07-06-25 In vi insert mode, ksh no longer emits a backspace character
+ before the carriage return when the newline is entered.
+07-06-25 A bug in which pipefail would cause a command to return 0
+ when the pipeline was the last command and the failure happened
+ on a component other than the last has been fixed.
+07-06-25 A bug in the expansion of ${var/pattern/rep} when pattern or rep
+ contained a left parenthesis in single quotes has been fixed.
+07-06-18 The braces for a subscripted variable with ${var[sub]} are now
+ optional when inside [[...]], ((...)) or as a subscript.
+07-05-28 A bug in brace expansion in which single and double quotes did
+ not treat the comma as a literal character has been fixed.
+07-05-24 The -p option of whence now disables -v.
+07-05-23 Several bug fixes in compound variables and arrays of arrays
+ have been made.
+07-05-15 A bug in which the %B format of printf was affected by the
+ locale has been fixed.
+07-05-14 A bug in which \ was not removed in the replacement pattern with
+ ${var/pattern/rep} when it was not followed by \ or a digit has
+ been fixed.
+07-05-10 A bug in which ksh -R file core dumped if no script was specified
+ has been fixed. it not displays an error message.
+07-05-07 Added additional Solaris signals to signal table.
+07-04-30 A bug in which a pipeline with command substitution inside a
+ function could cause a pipeline that invokes this function to
+ hang when the pipefail option is on has been fixed.
+07-04-30 +Added -q to whence.
+07-04-18 A small memory leak with each redirection of a non-builtin has
+ been fixed.
+07-03-08 A bug in which set +o output command line options has been fixed.
+07-03-08 A bug in which an error in read (for example, an invalid variable
+ name), could leave the terminal in raw mode has been fixed.
+07-03-06 A bug in which read could core dump when specified with an array
+ variable with a subscript that is an arithmetic expression has
+ been fixed.
+07-03-06 Several serious bugs with the restricted shell were reported and
+ fixed.
+07-03-02 If a job is stopped, and subsequently restarted with a CONT
+ signal and exits normally, ksh93 was incorrectly exiting with
+ the exit status of the stop signal number.
+07-02-26 +M-^L added to emacs mode to clear the screen.
+07-02-26 A bug in which setting a variable readonly in a subshell would
+ cause an unset error when the subshell completed has been fixed.
+07-02-19 +The format with printf uses the new = flag to center the output.
+07-02-19 A bug in which ksh93 did not allow multibyte characters in
+ identifier names has been fixed.
+07-02-19 A bug introduced in ksh93 that causes global compound variable
+ definitions inside functions to exit with "no parent" has been fixed.
+07-02-19 A bug in which using compound commands in process redirection
+ arguments would give syntax errors <(...) and >(...) has been fixed.
+07-01-29 A bug which caused the shell to core dump which can occur when a
+ built-in exits without closing files that it opens has been fixed.
+07-01-26 A bug in which ~(E) in patterns containing \ that are not inside ()
+ has been fixed.
+
+06-12-29 --- Release ksh93s ---
+06-12-29 A bug in which the value of IFS could be changed after a command
+ substitution has been fixed.
+06-12-22 +/dev/(tcp|udp|sctp)/HOST/SEVRICE now handles IPv6 addresses on
+ systems that provide getaddrinfo(3).
+06-12-19 +A -v option was added to read. With this option the value of
+ the first variable name argument will become the default value
+ when read from a terminal device.
+06-11-20 A bug in which "${foo[@]:1}}" expands a null argument (instead of
+ no argument), when foo[0] is not empty has been fixed.
+06-11-16 The discipline functions have been modified to allow each subscript
+ to act independently. Currently the discipline function will not
+ be called when called from a discipline function of the same variable.
+06-11-14 A bug which could cause a core dump if a file descriptor for
+ an internal file was closed from with a subshell has been fixed.
+06-10-30 +The redirections <# pattern, and <## pattern have been added.
+ Both seek forward to the beginning of the next line that contains
+ the pattern. The <## form copies the skipped portion to standard
+ output.
+06-10-26 +On systems that support stream control transport, the virtual file
+ name /dev/sctp/host/port can now be used to establish connections.
+06-10-26 +The printf modifier # when used with d produces units in thousands
+ with a single letter suffix added. The modifier # when used with
+ the i specification provides units of 1024 with a two letter suffix.
+06-10-24 The value of $! is now set to the process id of a job put
+ into the background with the bg command as required by POSIX.
+06-10-23 A bug in which the value of $! was affected by a background
+ job started from a subshell has been fixed.
+06-10-23 A bug in ${var:offset:len} in multibyte locales has been fixed.
+06-10-15 +The remaining math functions from C99 were added for any system
+ that supports them.
+06-10-13 The klockwork.com software detected a few coding errors that
+ have been fixed.
+06-10-12 A bug when skipping over `...` with ${x:=`...`} when x is set
+ has been fixed.
+06-10-11 A bug in process floating constants produced by the %a format
+ of printf has been fixed.
+06-10-06 A bug in which IFS was not being restored correctly in some
+ cases after a subshell has been fixed.
+06-10-06 A bug in which pipefail was not detecting some failures in
+ pipelines with 3 or more states has been fixed.
+06-10-03 A bug in the processing of >(...) with builtins which could
+ cause the builtin to hang has been fixed.
+06-10-03 A bug in the for loop optimizer which causes >(...) process
+ substitution to be ignored has been fixed.
+06-09-17 +The -a option was added to typeset for indexed arrays. This
+ is only needed when using the ([subscript]=value ...) form.
+06-09-06 +The showme option was added. Each simple command not beginning
+ with a redirection and not occurring with in the while, until, if,
+ select condition can be preceded by a semi-colon which will
+ be ignored when showme is off. When showme is on, any command
+ preceded by a colon will be traced but not executed.
+06-08-16 +As a new feature, a leading ~(N) on a pattern has no effect
+ except when used for file expansion. In this case if not
+ matches are found, the pattern is replaced by nothing rather
+ than itself.
+06-08-11 A bug in the expansion of ${.sh.match[i]:${#.shmatch[i]}} has
+ been fixed.
+06-08-10 +The read builtin options -n and -N have been modified to treat
+ the size as characters rather than bytes unless storing into a
+ binary (typeset -B) variable.
+06-07-27 +When the here document operator << is followed directly by a #
+ rather than a -, the first line of the here-document determines
+ how much whitespace is removed for each line.
+06-07-26 A bug in the C-shell history (enabled with set -H) in which the
+ history event !$ was not processed has been fixed.
+06-07-21 A bug on some systems in which assigning PATH on a command line
+ would not take effect has been fixed.
+06-07-20 Add ksh93 and rksh93 as allowable names for ksh binaries.
+06-07-20 Removed the SHOPT_OO compilation option which was only partially
+ implemented.
+06-07-20 The ability to use egrep, grep, and fgrep expressions within
+ shell patterns has been documented.
+06-07-17 A bug with arithmetic command expressions for locales in which
+ the comma is a thousands separator has been fixed.
+06-07-13 +The default HISTSIZE was increased from 128 to 512.
+06-07-13 A multibyte problem with locales that use shift codes has been fixed.
+06-06-23 A number of bug fixes for command, file, and variable completion
+ have been mode.
+06-06-20 +Floating point division by zero now yields the constant Inf or -Inf
+ and floating functions with invalid arguments yield NaN.
+06-06-20 +The floating point constants Inf and NaN can be used in arithmetic
+ expressions.
+06-06-20 +The functions isinf(), isnan(), tanhl() have been added for
+ arithmetic expressions.
+06-06-13 Internal change to use ordering for variables instead of hashing
+ to speed up prefix matching.
+06-06-13 A window between fork/exec in which a signal could get lost
+ and cause a program to hang has been eliminated
+06-06-13 A bug in edit completion with quoted strings has been fixed.
+06-06-07 The restricted options can now be enabled by set as well as on
+ the command line. Once set, it can not be disabled.
+06-06-04 Modified built-in binding so that for systems for which /bin
+ and /usr/bin are the same, a builtin bound to /bin will get
+ selected when either /bin or /usr/bin is scanned.
+06-06-04 +Added literal-next character processing for emacs/gmacs mode.
+ This change is not compatible with earlier versions of ksh93
+ and ksh88 when the stty lnext is control-v. The sequence
+ escape-control-v will display the shell version.
+06-05-31 +Modified emacs and vi mode so that entering a TAB after a partial
+ TAB completion, generates a listing of possible completions.
+ After the second TAB, a number followed by a TAB will perform
+ the completion with the corresponding item.
+06-05-19 +Modified arithmetic so that conversions to strings default to
+ the maximum number of precision digits.
+06-05-16 Bug fixes for multibyte locales.
+06-05-10 The =~ operator was added to [[...]] and [[ string ~= ERE ]]
+ is equivalent to [[ string == ~(E)ERE ]].
+06-04-25 A bug in the vi edit mode which could cause the shell to core dump
+ when switching from emacs mode.
+06-04-17 A bug in which using LANG or LC_ in assignment lists with builtins
+ did not restore the localed correctly has been fixed.
+06-04-04 A bug in which discipline functions could not be added to variables
+ whose names started with .sh has been fixed.
+06-03-28 +The -s option to typeset was added to modify -i to indicate short
+ integers.
+06-03-28 A bug in which variables assignment lists before functions
+ defined with function name were not passed on the functions
+ invoked by this function has been fixed.
+06-03-28 A bug in which name references defined within a function defined
+ with function name could not be used with compound variables has
+ been fixed.
+06-03-27 A bug in which read <&p (print >&p) would cause the coprocess input
+ (output) pipe to close before reading from (after writing to)
+ it has been fixed.
+06-02-28 A bug in which stopping a job created with the hist builtin command
+ would create a job that could not be restarted has been fixed.
+
+06-01-24 --- Release ksh93r ---
+06-01-24 A bug in which running commands with standard output closed would
+ not work as expected has been fixed.
+06-01-23 A bug in which print -u<n> could fail when file descriptor <n> was
+ open for writing has been fixed.
+06-01-19 The ?: arithmetic operator fixed to work when the operation after
+ the colon was an assignment.
+05-12-24 A bug which could lead to a core dump when elements of a compound
+ variable were array elements, i.e. foo=(bar=(1 2)), has been fixed.
+05-12-13 An arithmetic bug in which x+=y+=z was not working has been fixed.
+05-12-13 An arithmetic bug in which x||y was returning x when x was non-zero
+ rather than 1 has been fixed.
+05-12-07 +The aliases for integer and float have been changed to use attributes
+ -li and -lE to handle long long and long double types.
+05-12-07 +The histexpand (-H) option has been added which allows C-shell
+ style history expansions using the history character !.
+05-12-07 +The multiline option was added which changes that way the edit
+ modes handle lines longer than the window width. Instead of
+ horizontal scrolling, multiple lines on the screen are used.
+05-12-05 The whence builtin now returns an absolute pathname when the
+ command is found in the current directory.
+05-11-29 A bug which caused ksh -c '[[ ! ((' to core dump rather than
+ report a syntax error has been fixed.
+05-11-29 A bug when reading fixed length records into typeset -b variables
+ which caused a zero byte to terminate the value has been fixed.
+05-11-22 +The ability to seek to an offset within a file has been added
+ with the new I/O redirection operators, <# and >#. Currently,
+ these redirection operators must be followed by ((expr))
+ but in a future release, it should be able to used to seek forward
+ to the specified shell pattern. In addition $(n<#) expands to the
+ current byte offset for file descriptor n.
+05-11-22 +The .sh.match array variable is now set after each [[ ... ]]
+ pattern match. Previously it was only set for substring matches.
+05-10-17 A bug in which the library path variable could be prefixed
+ with a directory when a .path file was not encountered in
+ the directory of the executable has been fixed.
+05-09-15 A for/while loop optimizer bug in which $OPTIND was not
+ correctly expanded has been fixed.
+05-09-05 A bug in which a history command that invoked a history
+ command could go into an infinite loop has been fixed.
+05-08-31 +In the case that IFS contains to adjacent new-lines so that
+ new-line is not treated as a space delimiter, only a single
+ new-line is deleted at the end of a command substitution.
+05-08-19 +When a tilde substitution expands to the / directory and is
+ followed by a /, it is replaced by the empty string.
+05-08-16 A bug in which n<&m did not synchronize m has been fixed.
+05-08-16 A bug in which process substitution ( <() and >() ) was not
+ working within for and while loops has been fixed.
+05-07-24 A bug in which the pattern ~(E)(foo|bar) was treated as a syntax
+ error has been fixed.
+05-07-24 A bug in completion with <n>=, where n was the one of the
+ previous selection choices has been fixed.
+05-07-21 A bug with multibyte input when no edit mode was specified which
+ caused the input line to shift left/right has been fixed.
+05-06-24 A race condition which could cause the exit status to get lost
+ on some fast systems has been fixed.
+05-06-21 A bug in which nested patterns of the form {m,n}(pat) would cause
+ syntax errors has been fixed.
+05-06-21 A bug in the macro expander has been fixed which could cause a
+ syntax error for an expansion of the form ${x-$(...)} when
+ x is set and the command substitution contained certain strings.
+05-06-08 +On systems for which echo does not do System V style \ expansions,
+ the -e option was added to enable these expansion.
+05-06-08 A bug in which ${var op pattern} to not work when inside an
+ arithmetic expression has been fixed.
+05-05-23 +An extension to shell patterns that allows matching of nested
+ groups while skipping over quoted strings has been added.
+05-05-18 A bug in which the line number for errors was not correct for
+ functions loaded from FPATH has been fixed.
+05-04-18 A bug in which the exit status $? is not set when a trap triggered
+ by the [[...]] command is executed has been fixed.
+05-04-08 +Redirection operators can be directly preceded with {varname}
+ with no intervening space, where varname is a variable name which
+ allows the shell to select a file descriptor > 10 and store it
+ into varname.
+05-04-08 +SHOPT_CMDLIB_BLTIN=1 now includes <cmdlist.h> generated table.
+05-04-07 +[[ -o ?option ]] is true if "option" is a supported option.
+05-04-05 A bug in handling file completion with spaces in the names
+ has been fixed.
+05-03-25 +The SIGWINCH signal is caught by default to keeps the LINES and
+ COLUMNS variables in sync with the actual window size.
+05-03-25 +Building ksh with SHOPT_REMOTE=1 causes ksh to set --rc if stdin is
+ a socket (presumably part of a remote shell invocation.)
+05-03-25 +Building ksh with SHOPT_SYSRC=1 causes interactive ksh to source
+ /etc/ksh.kshrc (if it exists) before sourcing the $ENV file.
+05-03-25 +{first..last[..incr][%fmt]} sequences added to brace expansions
+ when braceexpand is enabled.
+05-03-03 A bug where a SIGCHLD interrupt could cause a fifo open to fail has
+ been fixed.
+05-02-25 A bug in which a builtin command run in the background could
+ keep a file descriptor open which could cause a foreground
+ process to hang has been fixed.
+05-02-24 A bug where builtin library commands (e.g., date and TZ) failed to
+ detect environment variable changes has been fixed.
+05-02-22 +The read builtin and word splitting are now consistent with respect
+ to IFS -- both treat IFS as field delimiters.
+05-02-22 +The read builtin no longer strips off trailing delimiters that
+ are not space characters when there are fewer variables than fields.
+05-02-17 A builtin bug on systems where dlsym(libcmd) returns link-time
+ bindings has been fixed.
+05-02-12 A bug in which the lib_init() function for .paths BUILTIN_LIB
+ libraries was not called has been fixed.
+05-02-06 A bug on some systems in which moving the write end of a co-process
+ to a numbered file descriptor could cause it to close has been fixed.
+05-02-06 A bug in the vi-edit mode in which the character under the cursor
+ was not deleted in some cases with the d% directive has been fixed.
+05-02-06 A bug where external builtin stdout/stderr redirection corrupted
+ stdout has been fixed.
+05-02-04 A bug where times formatting assumed CLK_TCK==60 has been fixed.
+
+05-01-11 --- Release ksh93q ---
+05-01-11 A bug in the integral divide by zero check has been fixed.
+05-01-11 +The -l option has been added to read /etc/profile and
+ $HOME/.profile, if they exist, before the first command.
+05-01-11 An argument parsing bug that caused `kill -s x -- n' to fail has
+ been fixed.
+05-01-11 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form 'BUILTIN_LIB=.'
+ When a command is searched for this directory, and the full path
+ matches the path of the built-in version of the command (listed
+ by the 'builtin' command) then the built-in version of the command
+ is used. When ksh is built with SHOPT_CMDLIB_DIR=1 then all libcmd
+ functions become builtins with the '/opt/ast/bin/' directory prefix.
+05-01-10 A bug in which a nameref to a compound name caused a core dump has
+ been fixed.
+05-01-09 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ caused a fatal print/echo error diagnostic has been fixed.
+04-12-24 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ corrupted the internal process/job list, sometimes causing the shell
+ to hang, has been fixed.
+04-12-01 A bug in which typeset -Fn truncated less than n digits for large
+ numbers has been fixed.
+04-11-25 A bug in which standard error could be closed after a redirection
+ to /dev/stderr has been fixed.
+04-11-17 A bug in which an expansion of the form ${array[@]:3} could expand
+ to ${array[0]} when ${array[3]} was not set has been fixed.
+04-10-22 +The -E or -orc command line option reads ${ENV-$HOME/.kshrc} file.
+04-10-22 +`-o foo' equivalent to `+o nofoo', `-o nobar' equivalent to `+o bar'.
+ `--foo' equivalent to `-o foo', `--nofoo' equivalent to `+o foo'
+04-10-05 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form
+ 'BUILTIN_LIB=libname'. When a command is searched for this directory,
+ the shared library named by libname will first be searched for a
+ built-in version of the command.
+04-09-03 <<< here documents now handle quotes in the word token correctly.
+04-08-08 +The maximum size for read -n and and read -N was increased from
+ 4095 to 32M.
+04-08-04 +printf %q was modified so that if an no operand was supplied, no
+ no output would be generated rather than a quoted empty string.
+04-08-01 +The -n and -N options of the read builtin has been modified
+ when reading variables with the binary attribute so that the
+ data is stored directly rather than through assignment.
+04-08-01 +The shcomp command has been modified to process alias commands
+ under some conditions.
+04-07-31 +The .sh.match variable added in ksh93l, now works like other
+ indexed arrays.
+04-07-08 A loop optimizer bug which occurs when typeset is used in
+ a for or while loop inside a function has been fixed.
+04-06-24 +The number of subexpressions in a pattern was increased to 64
+ from the current number of 20.
+04-06-17 +The -t option to read was modified to allow seconds to be
+ specified as any arithmetic expression rather than just
+ an integral number of seconds, for example even -t 'sin(.5)'
+ is now valid.
+04-06-16 Two small memory leak problems were fixed.
+04-06-15 A bug in ${var/pattern/"string"} which occurred when string
+ contained pattern matching characters has been fixed.
+04-05-08 printf $'%d\n' produced an erroneous error message and has
+ been fixed.
+04-05-24 A bug in which an associative array without any elements could
+ cause a core dump when a script with an associative array with
+ the same name was declared in a script invoked by name has
+ been fixed.
+04-05-11 A bug in which an exec statement could close the script that
+ is being processed in a script that is run by name causing
+ a failure has been fixed.
+04-04-28 +If the first character of assignment to an integer variable was 0,
+ the variable had been treated as unsigned. This behavior was
+ undocumented and has been removed.
+04-04-05 A bug in which the positioning of standard input could be incorrect
+ after reading from standard input from a subshell has been fixed.
+04-03-30 A bug in the for loop optimizer which in rare cases could cause
+ memory corruption has been fixed.
+04-03-29 +The preset alias source='command .' has been added.
+04-03-29 A bug introduced in ksh93p on some systems in which invoked by
+ name with #! on the first line would not get the signals handling
+ initialized correctly has been fixed.
+04-03-29 A bug introduced in ksh93p in which a HUP signal received by
+ a shell that is a session group leader was not passed down to
+ its children has been fixed.
+
+04-02-28 --- Release ksh93p ---
+04-02-28 +The ability to apply an append discipline to any variable has
+ been added.
+04-02-14 A bug in which the exportall option (set -a) would cause incorrect
+ results for arrays has been fixed.
+04-02-02 A bug in which an exported array would pass more than
+ the first element to a script invoked by name has been fixed.
+04-02-02 A bug on some systems in which name=value pairs preceding a script
+ invoked by name was not getting passed to the script has been fixed.
+04-01-20 A bug in which an unset discipline function could cause a core
+ dump on some systems has been fixed.
+04-01-12 A bug in which a continue or break called outside a loop from
+ inside a function defined with name() syntax could affect
+ the invoking function has been fixed.
+04-01-08 If a command name begins with ~, only filename completion will be
+ attempted rather than pathname completion using the builtin editors.
+04-01-08 A bug in the vi edit mode in which the wrong repeat count on
+ multiple word replacements with the . directive has been fixed.
+04-01-06 Backspace characters are now handled correctly in prompt strings.
+04-01-06 +The getopts builtin has been modified to accept numerical
+ arguments of size long long on systems that support this.
+04-01-06 A bug in which unsetting all elements of an associative array
+ would cause it to be treated as an indexed array has been fixed.
+03-12-15 A bug in which a quoted string ending with an unescaped $ would
+ delete the ending $ in certain cases has been fixed.
+03-12-05 A bug in which the shell could hang when set -x tracing a command
+ when an invalid multibyte character is encountered has been fixed.
+03-12-05 On some systems, if the KEYBD trap is set, then commands that use
+ the meta key were not processed until return was hit. This
+ has been fixed.
+03-12-05 A problem which occurred when the login shell was not a group
+ leader that could cause it to fail has been fixed.
+03-12-05 A problem in which a shell could core dump after receiving a signal
+ that should cause it to terminate while it was in the process
+ of acquiring more space has been fixed.
+03-12-05 +If ENV is not specified, the shell will default to $HOME/.kshrc
+ for interactive shells.
+03-11-21 A bug introduced in ksh93o in which the DEBUG trap could get
+ disabled after it triggered has been fixed.
+03-11-04 A bug in which using arithmetic prefix operators ++ or -- on a
+ non-lvalue could cause a core dump has been fixed.
+03-11-04 A bug in which leading zeros were stripped from variable
+ expansions within arithmetic computation to avoid being treated
+ as octal constants when they should not have, has been fixed.
+03-10-08 A bug introduced in ksh93o in which a large here document inside
+ a function definition could get corrupted has been fixed.
+03-09-22 A bug in which the .get discipline function was not being
+ called when a string variable was implicitly referenced from
+ within a numerical expression has been fixed.
+03-09-22 A bug in which a script without a leading #! could get executed
+ by /bin/sh rather than the current shell on some systems has
+ been fixed.
+03-09-12 +To improve conformance with ksh88, leading zeros will be ignored
+ when getting the numerical value of a string variable so that
+ they will not be treated as octal constants.
+03-09-03 +The builtin kill command now processes obsolete invocations
+ such as kill -1 -pid.
+03-09-02 The restriction on modifying FPATH in a restricted shell (sh -r)
+ has been documented.
+03-09-02 +The restricted shell (sh -r) has been modified to disallow
+ executing command -p.
+03-08-07 A bug in which the KEYBD trap was not being invoked when
+ characters with the 8th bit set has been fixed.
+03-08-02 A parser bug introduced in ksh93o which caused the character
+ after () in a Posix function definition to be skipped
+ when reading from standard input has been fixed.
+03-08-01 A bug in which "${foo#pattern}(x)" treated (x) as if it were
+ part of the pattern has been fixed.
+03-08-01 +The command -x option has been modified so that any trailing
+ arguments that do expand to a single word will be included
+ on each invocation, so that commands like command -x mv * dir
+ work as expected.
+
+03-07-20 --- Release ksh93o+ ---
+03-07-20 A bug in which could cause memory corruption when a posix
+ function invoked another one has been fixed.
+03-07-15 A bug in which a file descriptor>2 could be closed before
+ executing a script has been fixed.
+03-07-15 A parsing error for <() and >() process substitutions inside
+ command substitution has been fixed.
+03-07-15 A parsing error for patterns of the form {...}(...) when
+ used inside ${...} has been fixed.
+03-07-15 An error in which expanding an indexed array inside a compound
+ variable could cause a core dump has been fixed.
+03-07-15 A bug in which on rare occasions a job completion interrupt
+ could cause to core dump has been fixed.
+03-06-26 A bug in which process substitution embedded within command
+ substitution would generate a syntax error has been fixed.
+03-96-23 A bug in which ${@:offset:len} could core dump when there
+ were no arguments has been fixed.
+03-96-23 A bug in which ${X[@]:offset:len} could core dump when X
+ was unset has been fixed.
+03-06-22 +The -x option was added to the command builtin. If this
+ option is on, and the number of arguments would exceed ARG_MAX,
+ the command will be invoked multiple times with a subset of
+ the arguments. For example, with alias grep='command -x grep,
+ any number of arguments can be specified.
+03-06-14 A bug in which could cause a core dump on some systems with
+ vi and emacs editors with the MULTIBYTE option has been fixed.
+03-06-06 A bug in which the shell could core dump when a script was
+ run from its directory, and the script name a symlink to a file
+ beginning with .., has been fixed.
+03-06-05 A bug in which the shell could core dump when a child process
+ that it is unaware of terminates while it is calling malloc()
+ has been fixed.
+03-06-02 +An option named globstar (set -G) has been added. When enabled,
+ during pathname expansion, any component that consists only of ** is
+ matches all files and any number of directory levels.
+03-05-30 A bug in which the PATH search could give incorrect results when
+ run from directory foo and PATH contained .:foo:xxx has been fixed.
+03-05-29 +Some changes were made to the code that displays the prompt in edit
+ mode to better handle escape sequences in the prompt.
+03-05-27 I added = to the list of characters that mark the beginning of
+ a word for edit completion so that filenames in assignments
+ can be completed.
+03-05-20 A bug in which read -N could hang on some systems when reading
+ from a terminal or a pipe has been fixed.
+03-05-19 A bug in which the output of uname from a command substitution
+ would go to the standard output of the invoking command when
+ uname was invoked with a non-standard option has been fixed.
+03-05-19 A job control bug which would cause the shell to exit because
+ it hadn't take back the terminal has been fixed. The bug
+ could occur when running a function that contained a pipeline
+ whose last element was a function.
+03-05-19 A job control timing bug introduced in ksh93o on some systems
+ which could cause a pipeline to hang if the first component
+ completed quickly has been fixed.
+03-05-13 +The read builtin has been modified so that the builtin editors
+ will not overwrite output from a previous incomplete line.
+03-05-13 A bug in which the name of an identifier could have the string
+ .sh. prefixed to it after expanding a variable whose name begins
+ with .sh. has been fixed.
+03-05-13 A bug in the expansion of $var for compound variables in which
+ some elements would not be output when the name was a prefix
+ of another name in the compound variable has been fixed.
+03-05-08 The last item in the ksh93o release on 03-01-02 has been
+ altered slightly to preserve the leading 0's when the
+ preceding character is a digit. Thus, with typeset -LZ3 x=10,
+ $(( 1$x)) will be 1010 whereas $(( $x) will be 10.
+03-04-25 A bug in which if x is a name reference, then nameref y=x.foo
+ did not follow x has been fixed.
+
+03-03-18 --- Release ksh93o ---
+03-03-18 +A -N unary operator was added to test and [[...]] which returns
+ true if the file exists and the file has been modified since it
+ was last read.
+03-03-18 +The TIMEFORMAT variable was added to control the format for
+ the time compound command. The formatting description is
+ described in the man page.
+03-03-06 +A -N n option was added to read which causes exactly n bytes
+ to be read unlike -n n which causes at most n bytes to be read.
+03-03-03 +Three new shell variables were added. The variable .sh.file
+ stores the full pathname of the file that the current command
+ was found in. The variable .sh.fun names the current function
+ that is running. The variable .sh.subshell contains the depth
+ of the current subshell or command substitution.
+03-03-03 +When the DEBUG trap is executed, the current command line after
+ expansions is placed in the variable .sh.command. The trap
+ is also now triggered before each iteration of a for, select,
+ and case command and before each assignment and redirection.
+03-02-28 +Function definitions are no longer stored in the history file so
+ that set -o nolog no longer has any meaning.
+03-02-28 +All function definitions can be displayed with typeset -f not
+ just those stored in the history file. In addition, typeset +f
+ displays the function name followed by a comment containing the
+ line number and the path name for the file that defined this function.
+03-02-28 A bug in which the value of $LINENO was not correct when executing
+ command contained inside mult-line command substitutions has been
+ fixed.
+03-02-19 +Since some existing ksh88 scripts use the undocumented and
+ unintended ability to insert a : in front of the % and # parameter
+ expansion operators, ksh93 was modified to accept :% as equivalent
+ to % and :# as equivalent to # with ${name op word}.
+03-02-14 A bug which could cause a core dump when reading from standard
+ error when standard error was a pty has been fixed.
+03-02-14 +The shell arithmetic was modified to use long double on systems
+ that provide this data type.
+03-02-09 A bug in which a function located in the first directory in FPATH
+ would not be found when the last component of PATH was . and the
+ current directory was one of the directories in PATH has been fixed.
+03-02-07 +The trap and kill builtin commands now accept a leading SIG prefix
+ on the signal names as documented.
+03-02-05 A bug in the expansion of ${var/$pattern}, when pattern contained
+ \[ has been fixed.
+03-02-05 A bug in which .sh.match[n], n>0, was not being set for substring
+ matches with % and %% has been fixed.
+03-01-15 A bug in which getopts did not work for numerical arguments specified
+ as n#var in the getopts string has been fixed.
+03-01-09 A bug in which using ${.sh.match} multiple times could lead to
+ a memory exception has been fixed.
+03-01-06 A bug in the expansion of ${var/pattern/$string} in the case that
+ $string contains \digit has been fixed.
+03-01-02 +A -P option was added for systems such as Solaris 8 that support
+ profile shell.
+03-01-02 For backward compatibility with ksh88, arithmetic expansion
+ with ((...)) and let has been modified so that if x is a zero-filled
+ variable, $x will not be treated as an octal constant.
+
+02-12-05 --- Release ksh93n+ ---
+02-11-30 A bug that can show up in evaluating arithmetic statements that
+ are in an autoloaded function when the function is autoload from
+ another function has been fixed.
+02-11-30 An optimization bug in which an expansion of the form ${!name.@},
+ which occurred inside a for or a while loop, when name is a name
+ reference, has been fixed.
+02-11-18 A bug in which modifying array variables in a subshell could leave
+ side effects in the parent shell environment has been fixed.
+02-11-18 A memory leak when unsetting an associative array has been fixed.
+02-11-14 +The code to display compound objects was rewritten to make
+ it easier for runtime extensions to reuse this code.
+02-11-14 +A change was made to allow runtime builtins to be notified when
+ a signal is received so that cleanup can be performed.
+02-10-31 +User applications can now trap the ALRM signal. Previously,
+ the ALRM signal was used internally and could not be used
+ by applications.
+02-10-31 A bug in which signals received while reading from a coprocess
+ for which traps were set was not handled correctly has been fixed.
+02-10-31 A bug in which a file opened with exec inside a subshell could
+ be closed before the subshell completed has been fixed.
+02-10-21 A bug in which setting PATH or FPATH inside a function might not
+ take effect has been fixed.
+02-10-21 A bug which could cause a core dump when a local SECONDS variable
+ is defined in a function has been fixed.
+02-10-15 A bug in which the associate array name operator ${!array[@]}
+ could return the same name multiple times has been fixed.
+02-10-15 A bug in which the zero'th element of an associative array was
+ not getting set when an assignment was made without a subscript
+ specified has been fixed.
+
+02-09-30 --- Release ksh93n ---
+02-09-30 +The maximum indexed array size was increased to 16Megs.
+02-09-30 A bug which could cause a core dump when changing attributes
+ of associative array has been fixed.
+02-09-30 A bug in which exporting an array variable would not export the
+ 0-th element has been fixed.
+02-09-30 A bug in which an array assignment of the form a=($a ...) would unset
+ 'a' before the right hand side was evaluated has been fixed.
+02-09-27 A bug in which the error message for ${var?message} when var was
+ null or unset did not contain the variable name var has been fixed.
+02-09-27 A bug in which closing file descriptors 0 through 2 could
+ cause a subsequent here document to fail has been fixed.
+02-09-14 A bug in whence which occurs when the specified name contained
+ a / has been fixed.
+02-09-14 A bug in the parser for strings of the form name$((expr))=value
+ has been fixed.
+02-09-14 A for loop optimization bug in which the number of elements in
+ an array was treated as an invariant has been fixed.
+02-09-09 A bug in which redirection or closing of a file descriptor between
+ 3 and 9 could cause a subsequent here document to fail has been
+ fixed.
+02-09-09 A bug in which a background job was not removed from the job list
+ when a subshell completed has been fixed, for example (prog&).
+02-09-03 A bug in which an assignment of the form name=(integer x=3)
+ could be interpreted as an array assignment rather than a
+ compound variable assignment has been fixed.
+02-08-19 A command completion bug which occurred on file systems that
+ are case insensitive has been fixed.
+02-08-19 A bug which could lead to an exception on some systems (for
+ example FREEBSD) which occurred when setting PATH has been fixed.
+02-08-11 A bug in arithmetic rounding in which a value input as a decimal
+ string would output as a rounded version of the string has
+ been fixed.
+02-08-11 A bug in which the last character could be deleted from shell
+ traces and from whence when called from a multibyte locale
+ has been fixed.
+02-08-01 A bug which could cause a core dump to occur when a shell script
+ is executed while a coprocess is running that has closed the
+ output pipe has been fixed.
+02-08-01 A bug in which command completion in multibyte mode could
+ corrupt memory for long command lines has been fixed.
+
+02-06-17 --- Release ksh93n- ---
+02-06-17 A bug in which user defined macros could cause a core dump in
+ with MULTIBYTE mode has been fixed.
+02-06-17 A bug in which printf format specifiers of the form %2$s were causing
+ a core dump has been fixed.
+02-06-17 A bug in which setting stty to noecho mode did not prevent the
+ echoing of characters by ksh when emacs or viraw mode
+ was enabled has been fixed.
+02-06-17 A bug in which background job completion could cause the sleep
+ builtin to terminate prematurely has been fixed.
+02-06-17 A bug in which the shell could core dump if getopts was called
+ when the OPTIND variable contained a negative value has been fixed.
+02-06-10 +The edit mode prompt has been modified to handle escape sequences.
+02-06-10 A bug which occurred for interactive shells in which the builtin
+ cat command was used in command substitution on a file whose
+ size was larger than PIPE_BUF has been fixed.
+02-06-10 A bug in which the trap on ERR was not being processed when
+ set inside a function has been fixed.
+02-06-07 A bug in which function definitions could cause the history count
+ to be decremented by one (and even become negative) has been fixed.
+02-06-05 A bug in read in which share mode could be enabled has been fixed.
+02-05-28 A bug which could occur when the last command of a script was
+ a case statement and the action selected ended in ;& instead of ;;
+ has been fixed.
+02-05-23 A bug with unary + introduced in ksh93k has been fixed.
+02-05-07 A bug in substitutions of the form ${var/pattern/string} in which
+ a backslash was inserted in the replacement string when it contained
+ a special pattern character has been fixed.
+02-05-01 A bug in the emacs edit mode which occurred in versions compiled
+ for multibyte character sets which occurred when a repeated search
+ was requested after a long line had been returned for the previous
+ search has been fixed.
+02-04-02 +vi and emacs edit modes were modified so that tab completion is
+ disabled when invoked from the read built-in.
+
+02-03-26 --- Release ksh93m+ ---
+02-03-26 A bug in which \ was not handled correctly when used in file
+ expansion has been fixed.
+02-02-18 A bug in which lines beginning with a # were deleted from here
+ documents when the here-document delimiter was followed by
+ a comment has been fixed.
+02-12-06 An optimization bug in which ${!x[@]) was treated as invariant in
+ a for loop has been fixed.
+02-02-06 A bug in which the ERR trap is not cleared for a script invoked
+ by name from within a function has been fixed.
+02-01-08 A bug in which a shell script executed from within a subshell
+ could cause this script to have an invalid pointer leading
+ to a memory fault has been fixed.
+02-01-07 +Added here documents of the form <<< word (as per zsh) which
+ is equivalent to << delim\nword\ndelim.
+02-01-07 A bug in which the first word of a compound assignment,
+ x=(word ...), was treated as a reserved word has been fixed.
+02-01-07 A bug in the handling of \ when noglob was enabled and a
+ substitution of the form ${word op pattern} occurred in the
+ same word has been fixed.
+02-01-07 +A compilation option, CMDLIB_BLTIN in the file OPTION, has
+ been added. When this options is set, all commands implemented
+ in libcmd become shell builtin commands by default.
+02-01-07 A bug in which builtin foo, where foo is already a builtin
+ would result in the builtin foo getting removed has been fixed.
+02-01-07 A bug which the shell executed a command found in the current
+ directory when PATH have no valid directories has been fixed.
+01-11-28 The value of $? was not being set when called with exit.
+01-11-28 If the last command was of the form (...) and a trap on EXIT or
+ ERR was set, and the command inside () modified the trap, then
+ the original trap wasn't executed.
+01-11-26 +The value for 0 is now preceded by the base number when
+ the base was not 10.
+01-11-26 +The default has compilation mode has been changes so that
+ viraw mode will always be on.
+
+01-10-31 --- Release ksh93m ---
+01-10-31 A for loop optimizer bug for subshells contained withing for
+ loops has been fixed.
+01-10-16 typeset without arguments no longer outputs variable names
+ that do not have any attributes that are set.
+01-10-16 A bug introduced in ksh93l in which assignments specified with
+ the exec built-in were not being expanded properly has been
+ fixed.
+01-10-11 An optimization bug in which ${!x) was treated as invariant in
+ a for loop has been fixed.
+01-10-11 Unsigned integer variables in bases other than 10 are printed now
+ expand in that base with the base prefix.
+01-10-10 A number of typos in the self generating man pages for shell
+ built-ins have been fixed.
+01-10-04 The self generated man pages for hist and fc were not working
+ correctly and have been fixed.
+01-10-03 Yet another optimizer bug in which shell patterns were
+ treated as invariants has been fixed.
+01-09-27 Two bugs relating to multibyte history searches and to find
+ have been fixed.
+01-09-27 A bug introduced in ksh93k in which the PATH searching was
+ not restored after running a command with an assignment list
+ has been fixed.
+01-09-26 A bug in which a zero filled field was treated as octal when
+ converted to integer has been fixed.
+01-09-26 Yet another bug in the optimization of for loops related to
+ recursive functions with break or continue statements has been fixed.
+01-09-25 +The exponentiation operator ** was added to the shell arithmetic
+ evaluation. It has higher precedence than * and is left
+ associative.
+01-09-25 The code was modified to use the ast multibyte macros
+ and functions for handing multibyte locales.
+01-09-25 +The expansion ${parameter:offset:length} now handles negative
+ offsets which cause offsets to be measured from the end.
+01-09-25 Some spelling errors in the documentation were corrected.
+01-09-24 +The /dev/tcp/host/port and /dev/udp/host/port now allow
+ the ports to be specified by service name.
+01-09-24 +The change staring with ksh93g in which the the appropriate
+ library path variable is prepended with a corresponding library
+ directory has been modified. With the new method, only the
+ library path defined in the file named .paths in the directory
+ where the executable is found will be modified. See the
+ man page for more details.
+01-09-23 +The .fpath file (see ksh93h) is no longer looked for in each
+ directory on the path to locate function directories. The
+ file named .paths is used instead.
+01-09-23 A bug in which IFS was not being restored after being changed in
+ a subshell has been fixed.
+01-09-16 +With the vi and emacs edit modes, after a list of command
+ or functions is generated with = or M-= respectively,
+ any element from the list can be pasted on the command line
+ by preceding the = or M-= with a numeric parameter specifying
+ the position on the list.
+01-09-16 A bug in ksh93l caused command completion not to find aliases
+ and functions. Command listing from the edit mode was presented
+ in reverse order. This has been fixed.
+01-09-13 Another bug in the optimization of for loops related to subshells
+ when traps were set has been fixed.
+01-09-07 A change in ksh93l caused brace expansion to stop working
+ and this has been fixed.
+01-09-04 A bug introduced in ksh93k in which an arithmetic statement
+ within a function that used name references did not follow the
+ reference has been fixed.
+01-09-04 A bug introduced in ksh93l in which export -p did not prefix
+ each export with the word export has been fixed.
+01-08-29 A bug in multibyte input which occurred when a partial multibyte
+ character was received has been fixed.
+01-08-29 A bug introduced in ksh93l which could cause a core dump
+ when an assignment list containing PATH is specified inside
+ command substitution has been fixed.
+01-08-09 Another bug in the optimization of for loops in ksh93l caused
+ errors in recursive functions using local variables that
+ contained for loops has been fixed.
+01-07-27 A bug in which IFS would be unset after a command substitution
+ inside a here document has been fixed.
+01-07-26 To conform to the POSIX standard, if you invoked ksh name,
+ and name does not contain a /, it will first try to run
+ one in the current directory whether it is executable or not
+ before doing a path search for an executable script. Earlier
+ versions first checked for an executable script using the
+ PATH variable.
+01-07-23 A bug in which unset -f invoked in a subshell could unset a
+ function defined in the parent has been fixed.
+01-07-16 A bug in the optimization of for loops in ksh93l caused
+ name references to be treated as invariants has been fixed.
+01-07-09 A bug in which a discipline function applied to a local variable
+ could cause a shell exception has been fixed. Discipline
+ functions can only be specified for global variables.
+
+01-06-18 --- Release ksh93l ---
+01-06-18 A bug in assigning integers larger than can be represented as
+ long integers to floating point variables has been fixed.
+01-06-18 A bug in the handling of unsigned integers (typeset -ui) has
+ been fixed.
+01-06-04 The evaluation of the PS1 prompt no longer effects the value
+ of the $? variable.
+01-06-01 A small memory leak from subshells has been fixed.
+01-05-22 A bug in which attributes for variables that did not have
+ values would be lost after a subshell has been fixed.
+01-05-22 +The %R format has been added to convert a shell pattern into
+ an extended regular expression.
+01-05-22 +The escape sequences \e, \cX, \C[.collating-element.], and
+ \x{hex} have been added to ASCII-C strings and to printf format
+ strings.
+01-05-20 +Patterns of the form {n}(pattern) and {m,n}(pattern) are now
+ recognized. The first form matches exactly n of pattern whereas,
+ the second form matches from m to n instances of pattern.
+01-05-20 +The shell allows *-(pattern), +-(pattern), ?-(pattern),
+ {m,n}-(pattern}, and @-(pattern) to cause the minimal
+ match of pattern to be selected whenever possible rather
+ than the maximal (greedy) match.
+01-05-20 +The character class [:word:] has been added to patterns.
+ The word class is the union of [:alnum:] and the character _.
+01-05-20 +Inside (...) pattern groups, the \ character is now treated
+ specially even when in an enclosing character class. The
+ sequences, \w, \d, \s are equivalent to the character classes
+ word, digit, and space respectively. The sequences \W, \D,
+ and \S are their complement sets.
+01-05-20 +The shell now recognizes pattern groups of the form
+ ~(options:pattern) where options or :pattern can be omitted.
+ Options use the letters + and - to enable and disable options
+ respectively. The option letters g (greedy), i (ignore case)
+ are used to cause maximal matching and to cause case
+ insensitive matching respectively. If :pattern is also
+ specified, these options are only in effect while this
+ pattern is being processed. Otherwise, these options remain
+ in effect until the end of the pattern group that they are contained
+ in or until another ~(...) is encountered. These pattern groups
+ are not counted with respect to group numbering.
+01-05-14 When edit completion, expansion, or listing occurs in the
+ middle of a quoted string, the leading quote is ignored when
+ performing the completion, expansion, or listing.
+01-05-14 A small memory leak from subshells has been fixed.
+01-05-10 A bug in which open files were not restored after a subshell
+ that had used exec to replace a file has been fixed.
+01-05-10 +Redirection to a null file name now generates an error message.
+01-05-09 The shell now rejects some invalid parameter substitutions that
+ were previously processed in undefined ways.
+01-05-09 A bug in which the output of select was not flushed before the
+ read when input did not come from the terminal has been fixed.
+01-05-08 A bug in which job ids would not be freed for interactive shells
+ when subshells ran built-ins in the background has been fixed.
+01-05-08 +The FPATH variable now requires an explicit . to cause the
+ current directory to be treated as a function directory.
+01-05-08 A bug in read -n when echo mode was disabled has been fixed.
+01-05-07 A bug in which function definitions could be listed as part
+ of the history has been fixed.
+01-04-30 +This release uses a new and often much faster pattern matcher than
+ earlier releases.
+01-04-30 +An optimizer now eliminates invariant parameter expansions from
+ for while and until loops.
+01-04-30 +The variable .sh.match is set after each pattern match (# % or /)
+ in a variable substitution. The variable .sh.match is an
+ indexed array with element 0 being the complete match.
+ The array is only valid until the next subsequent pattern
+ match or until the value of the variable changes which ever
+ comes first.
+01-04-30 +A self generating man page has been added to shcomp. Also,
+ shcomp now stops compiling when it finds an exit or exec
+ command and copies the remainder so that it can be used
+ for standard input.
+01-04-30 +The shcomp command was modified so that it can work in an
+ EBCIDIC environment and that binary scripts are portable
+ across environments.
+01-04-30 A bug in the handling of a trailing : in PATH has been fixed.
+01-04-30 A bug in which the builtin version of a command would get invoked
+ even though the full pathname for the command was specified
+ has been fixed.
+01-04-30 A bug in which read would loose the last character when
+ reading the last line of a file that did not contain a new-line
+ character has been fixed.
+01-04-23 A bug on some systems in which in vi mode the end of file
+ character and end of line character could be swapped has
+ been fixed.
+01-04-23 A bug on some systems in which invoking a shell script that
+ did not have execute permission could set the exit value to
+ 127 rather than 126 has been fixed.
+01-04-20 A bug in which read -n from a pipe would block if fewer than
+ n characters was received has been fixed.
+01-04-09 A bug in which invalid patterns, for example, ) by itself,
+ was not treated as a string has been fixed so that if i=')',
+ then [[ $i == $i ]] is true.
+01-04-09 +The shell arithmetic now interprets C character constants.
+01-04-09 A bug in which a non-zero return from a function defined
+ with the function reserved word did not trigger the ERR
+ trap or exit with set -e has been fixed.
+01-04-02 A bug on some systems, in which characters above 127 were
+ not displayed correctly in vi or emacs edit mode has been fixed.
+01-04-02 A bug on some systems, introduced in the 'k' point release, in
+ which the erase character in viraw mode was moving the cursor
+ to the left without erasing the character has been fixed.
+01-04-02 On some systems the wcwith() function was returning a wrong
+ value for characters and caused characters to be displayed
+ incorrectly from the shell edit modes. A work around for
+ this problem has been added.
+01-03-26 A bug in which valid scripts could produce syntax errors
+ when run with locales that considered characters such as "'"
+ to be space characters has been fixed.
+01-03-20 A bug in which an syntax error in an arithmetic expression
+ entered interactively could cause the shell to go into
+ an infinite loop outputting the error message has been fixed.
+01-03-10 +ksh93 accepts -l as a synonym for -L in test on systems for
+ which /bin/test -l tests for symbolic links.
+01-03-10 A bug in parsing scripts in which { and } are used in place of
+ in and esac in case statements embedded in compound commands
+ has been fixed. Use of { and } for in and esac is obsolete.
+01-03-06 A bug in which an argument of the form foo=bar was not
+ being passed correctly to a traced function whose name
+ was foo has been fixed.
+01-03-02 Using $(trap -p name) did not print the name of the current
+ trap setting for trap name.
+01-02-26 Exported floating point variables gave incorrect results
+ when passing them to ksh88. This has been fixed.
+01-02-25 A race condition in which a coprocess which completed too quickly
+ would not allow subsequent coprocesses to start has been fixed.
+01-02-25 The 'g' format specifier is now handled by printf. It had
+ inadvertently been omitted.
+01-02-20 The + was not being displayed during an execution trace
+ with the += assignment operator.
+01-02-19 The error message which occurs when the interpreter name
+ defined on the #! line does not exist is more informative.
+01-02-19 A bug in which $0 would not be set correctly when a
+ script with #! was invoked by full pathname from the
+ directory of the script has been fixed.
+01-02-19 A shell script did not always pick up tty mode changes
+ made by external commands such as stty which could
+ effect the behavior of read.
+01-02-19 The -u, -g, and -k unary tests did not give the correct
+ results when used with negation and this has been fixed.
+
+01-02-05 --- Release ksh93k+ ---
+01-02-05 The sequence \<newline> inside $'...' was not incrementing
+ the line count and this has been fixed.
+01-02-05 +Modified expansion of "${@-}" so that if no arguments are set
+ it results in null string rather than nothing.
+01-02-02 memory leak problem with local variables in functions fixed.
+01-01-25 +allow arithmetic expressions with float%int and treat them
+ as ((int)float)%int rather than as an error.
+01-01-19 read -n1 was not working and has been fixed.
+01-01-17 +ksh now handles the case in which a here document in command
+ substitution $() is terminated by the trailing ). Previously,
+ a new-line was needed at the end of the delimiter word.
+01-01-02 A bug in which a KEYBD trap would cause a multi-line token
+ to be processed incorrectly has been fixed.
+00-12-10 +Arithmetic integer constants can now have L and U suffices.
+00-12-10 A bug in the processing of arithmetic expressions with compound
+ variables when the -n option is on has been fixed.
+00-12-08 A bug in M-f and M-b from emacs mode has been fixed. This
+ bug only occurs when ksh93 is compiled without MULTIBYTE enabled.
+00-11-29 A bug in which jobs -p would yield 0 for background
+ jobs run in a script has been fixed.
+00-11-21 A bug in integer arrays in which the number of elements is
+ incorrect when the ++ operator is applied to a non-existing
+ element has been fixed. For example, integer x; ((x[3]++)).
+00-11-20 A timing bug in which the shell could reset the terminal
+ group to the wrong value in the case that the a new process
+ changes the terminal group during startup has been fixed.
+
+00-10-27 --- Release ksh93k ---
+00-10-27 Using tab for completion now works only when applied
+ after a non-blank character at the end of the current line.
+ In other case a tab is inserted.
+00-10-27 A bug in the emacs edit mode for ^X^E has been fixed.
+ The ^X^E sequence is supposed to invoke the full editor
+ on the current command.
+00-10-18 A bug in which expansions of the form ${var//pattern/string}
+ did not work correctly when pattern was '/' or "/" has
+ been fixed.
+00-10-18 +The output format for indexed arrays in compound variables
+ has been modified so that it can be used as input.
+00-10-18 Assignments with name references (typeset -n) will now
+ implicitly unreference an existing name reference.
+00-10-17 A bug the += append operator when a single array element
+ is appended to a variable that is not an array has been fixed.
+00-10-16 A bug in which the SIGCONT signal was being sent to
+ each process will kill -0 or kill -n 0 has been fixed.
+00-10-12 +The arithmetic evaluation portion has been rewritten to
+ perform a number of optimizations.
+00-10-10 A bug in which name prefix matching ${!name.*} was not
+ checking name to see if it was a name reference has been fixed.
+00-09-26 A bug in the multibyte version in which the width of for
+ non-printing characters was not correct has been fixed.
+00-09-12 +Made changes to get multibyte editing work on UWIN for windows
+00-09-12 A bug in which multibyte characters would be displayed incorrectly
+ has been fixed.
+00-08-08 Removed build dependency on iswprint() and iswalph().
+00-07-20 In some cases the read builtin would read more than a single
+ line from a pipe on standard input and therefore leave the seek
+ position in the wrong location.
+00-07-05 +If the directory / is on the path, a / will not be inserted
+ between the directory and the file name during path searching
+ to avoid searching // for systems that treat this specially.
+00-06-26 A bug in which on rare occasions wait could return before all
+ jobs have completed has been fixed.
+00-06-21 A bug in which backspace did not work correctly during the
+ R replace directive in vi-mode has been fixed.
+00-06-12 +Added variable name completion/expansion/listing to the set of
+ completions. Variable name completions begin with $ or "$ followed
+ by a letter.
+00-05-09 --- Release ksh93j ---
+00-05-09 Modified command substitution to avoid using /tmp files when
+ run on read-only file systems.
+00-04-17 +Modified printf to handle '%..Xc' and '%..Xs' options where X
+ is not an alpha character. Previous versions core dumped with this.
+00-04-10 +Changes to multibyte editing code were made to use standard
+ ISO C functions rather than methods devised before the standard.
+00-04-09 Add %H options to printf to output strings with <"'&\t> properly
+ converted for use in HTML and XML documents.
+00-04-07 +Modified getopts builtin to handle \f...\f in usage string
+ by invoking specified function.
+00-04-04 Added self generating man pages for bg, fc, fg, disown, jobs,
+ hist, let, ., and ulimit.
+00-03-30 +The append operator += has been added and can be used
+ for all assignments, strings, arrays, and compound variables.
+00-03-30 +Code was modified in several places to support automatic
+ generation of C locale dictionaries.
+00-03-28 A bug in which the set and trap commands invoked with --name
+ type arguments would terminate the invoking script has
+ been fixed.
+00-03-27 A bug in which the library path variable was not updated
+ correctly on some systems as described in the 'g' point
+ release has been fixed.
+00-03-07 printf now returns a non-zero exit status when one of
+ its arguments cannot be converted to the given type.
+00-03-05 The return value and error message for a command that
+ was found on the path but was not executable was set
+ incorrectly.
+00-03-05 A prototype for ioctl() was removed from the vi edit mode.
+
+00-01-28 --- Release ksh93i ---
+00-01-28 +Most of the built-in commands and ksh itself are now
+ self documenting. Running command --man will produce
+ screen output. Running command --html produces the
+ man page in html format.
+00-01-28 +The getopts builtin can process command description
+ strings to produce man pages.
+00-01-28 A bug in which a script could terminate when getopts
+ encountered an error when invoked inside a function
+ has been fixed.
+00-01-28 When a symbolic link was specified as the name of
+ the script to invoke by name, the value of $0 was
+ set to the real file name rather than the link name
+ in some cases and this has been fixed.
+00-01-28 A bug in which the precision given as an argument
+ to printf was not working has been fixed.
+
+99-03-31 --- Release ksh93h ---
+99-03-31 +The PATH search algorithm has been modified to look
+ for a file named .fpath in each bin directory and if
+ found, to search for functions in this directory if
+ it cannot find the command in that directory.
+99-03-31 +When performing pathname expansion, the shell checks
+ to see whether each directory it reads is case sensitive
+ or not, and performs the matching accordingly.
+99-03-31 +The %T format for printing formatted date/time.
+99-03-31 +The emacs and vi modes now handle arrow keys when
+ they use standard ANSI escape sequences.
+99-03-31 +The TAB key can be used for completion in emacs and viraw mode.
+99-03-31 A bug in setting .sh.editchar during the KEYBD trap
+ for the MULTIBYTE option was fixed in release ksh93h.
+99-03-31 A bug in shcomp for compilation of unary operators with [[...]]
+ has been fixed.
+99-03-31 A bug in which the value of $? was changed when executing
+ a keyboard trap has been fixed.
+99-03-31 The handling of SIGCHLD has been changed so that the
+ trap is not triggered while executing trap commands
+ to avoid recursive trap calls.
+99-03-31 A bug in which a local variable in a function declared readonly
+ would generated an error when the function went out of
+ scope has been fixed.
+99-03-31 A bug in which \<new_line> entered from the keyboard
+ with the KEYBD trap enabled has been fixed.
+99-03-31 The error message for a misplaced ((, for example print ((3),
+ was often garbled and has been fixed.
+99-03-31 A bug in the KEYBD trap in which escape sequences of the form
+ <ESC>[#~ were not being handled as a unit has been fixed.
+99-03-31 A bug in which ksh would consider expressions like [[ (a) ]]
+ as syntax errors has been fixed.
+99-03-31 A function defined as foo() without a function body
+ was not reported as a syntax error.
+99-03-31 A bug in which ksh could run out of file descriptors when
+ a stream was repeatedly opened with exec and read from
+ has been fixed.
+
+98-04-30 --- Release ksh93g ---
+98-04-30 +The pipefail option has been added. With pipefail
+ enabled, a pipeline will not complete until all
+ commands are complete, and the return value will
+ be that of the last command to fail, or zero if
+ all complete successfully.
+98-04-30 +The name-value pair library uses the cdt library rather
+ than the hash library. This change should be transparent
+ to applications.
+98-04-30 +On the U/WIN version for Window 95 and Windows NT,
+ when a directory beginning with a letter followed by
+ a colon is given to cd, it is assumed to be an absolute
+ directory
+98-04-30 +When an executable is found on a given path,
+ the appropriate library path variable is prepended
+ with a corresponding library directory.
+98-04-30 A bug in which a name reference could be created to
+ itself and later cause the shell to get into an infinite
+ loop has been fixed.
+98-04-30 A bug in shcomp relating to compound variables was fixed.
+98-04-30 A bug introduced in ksh93e in which leading 0's in -Z
+ fields caused the value to be treated as octal for arithmetic
+ evaluation has been fixed.
+98-04-30 A bug when a name reference with a shorter name than
+ the variable it references was the subject of a compound
+ assignment has been fixed.
+98-04-30 A bug which in which assignment to array variables in
+ a subshell could effect the parent shell has been
+ fixed.
+98-04-30 read name?prompt was putting a 0 byte at the end of the
+ prompt on standard error.
+98-04-30 A bug in [[ string1 > string2 ]] when ksh was run with -x
+ has been fixed.
+98-04-30 A bug in which the escape character was not processed
+ correctly inside {...} when brace expansion is enabled
+ has been fixed, for example {\$foo}.
+98-04-30 A bug in line continuation in here-documents has been
+ fixed.
+98-04-30 The default base when not specified with typeset -i is
+ 10 in accordance with the documentation. Previously,
+ the value was determined by the first assignment.
+98-04-30 A parsing bug in which a # preceded alphanumeric
+ characters inside a command substitution caused
+ a syntax error to be reported has been fixed.
+98-04-30 A bug in which a decimal constant represented as 10#ddd
+ where ddd was more than five digits generated a syntax
+ error has been fixed.
+98-04-30 A bug in here document expansion in which ${...} expansions
+ were split across buffer boundaries has been fixed.
+98-04-30 +The sh_fun() function now takes third argument which
+ is an argument list for the invoked discipline function
+ or built-in.
+98-04-30 +A callback function can be installed which will give
+ notification of file duplications and file closes.
+98-04-30 When ksh is compiled on systems that do not use fork()
+ current option settings where not propagated to sub-shells.
+
+97-06-30 --- Release ksh93f ---
+97-06-30 +Hostnames in addition to host addresses can be given in
+ /dev/tcp/host/port virtual file names.
+97-06-30 File name completion and expansion now quotes special
+ characters in file names from both emacs and vi edit modes.
+97-06-30 An empty for list behave like a for list with null expansions.
+ It produces a warning message with sh -n.
+97-06-30 +The code has been modified to work with EBCDIC as well as ASCII.
+97-06-30 A bug which would cause the secondary prompt to be
+ displayed when a user entered a literal carriage
+ return has been fixed.
+97-06-30 A bug which caused ksh read -s name to core dump was
+ fixed.
+97-06-30 A bug with the expansion of \} and \] inside double
+ quoted strings that also contained variable expansions
+ has been fixed
+97-06-30 Changes in the ksh93e point release caused autoload
+ functions invoked from within command substitution
+ to fail. This has been fixed.
+97-06-30 A bug in the processing of here-documents that could
+ prevent variable substitution to occur after $(...) command
+ substitution for long here documents has been fixed.
+97-06-30 A bug caused by a race condition that could cause SIGTERM
+ to be ignored by a child process has been fixed.
+97-06-30 A bug which prevented the startup of a coprocess immediately
+ after killing a running coprocess has been fixed.
+97-06-30 ulimit foobar, where foobar is not an arithmetic
+ expression, now gives an error message as it did with ksh88
+ instead of setting the file size limit to 0.
+97-06-30 A bug which could cause an interactive shell to terminate when
+ the last process of a pipeline was a POSIX function was fixed.
+97-06-30 A bug which could cause command substitution of a shell script
+ to core dump has been fixed.
+97-06-30 A security hole was fixed in suid_exec.
+97-06-30 Arithmetic functions such as pow() that take more than
+ one argument, did not work if arguments other than the
+ first contained parenthesized sub-expression.
+97-06-30 The error message from a script containing an incomplete
+ arithmetic expression has been corrected.
+97-06-30 A bug which caused a core dump on some machines when
+ the value of a name reference contained a positional
+ parameter and the name reference was not defined inside
+ a function has been fixed.
+97-06-30 Arithmetic expressions now correctly handle hexadecimal
+ constants.
+97-06-30 A bug in which integer variables could be expanded
+ with a leading 10# when declared with typeset -i
+ multiple times has been corrected.
+97-06-30 A bug in which IFS wasn't correctly restored when
+ set within command substitution has been fixed.
+97-06-30 The _ character is now considered as part of a word
+ with the M-f and M-b emacs directives as it was in ksh88.
+97-06-30 A bug in brace pattern expansions that caused expressions
+ such as {foo\,bar,bam} to expand incorrectly have been fixed.
+
+
+96-07-31 --- Release ksh93e ---
+96-07-31 +The math functions, atan2, hypot, fmod, and pow were added.
+96-07-31 +When a shared library is loaded, if the function lib_init()
+ is defined in the library, it is invoked the first time that
+ the library is loaded with builtin -f library.
+96-07-31 The k-shell information abstraction database option, KIA,
+ has been revamped.
+96-07-31 Empty command substitutions of the form $() now work.
+ whence -v foo now gives the correct result after calling
+ builtin -d foo.
+96-07-31 A bug in right to left arithmetic assignment for which
+ the arithmetic expression (( y = x = 1.5 )) did not
+ yield 1 for y when x was declared typeset -i was fixed.
+96-07-31 printf has been fixed to handle format containing \0
+ and/or \0145 correctly. In addition, characters following
+ %b in the format string are no longer displayed when
+ the operand contains \c.
+96-07-31 A bug in printf that could cause the %E format to
+ produce unnormalized results has been fixed.
+96-07-31 A bug which causes some arithmetic expressions to be
+ incorrectly evaluated as integer expressions rather
+ that floating point has been fixed.
+96-07-31 Functions defined inside a subshell no longer remain
+ defined when the subshell completes.
+96-07-31 The error message from sh -c ';echo foo' has been
+ corrected.
+96-07-31 The format for umask -S has been changed to agree
+ with the specification in the POSIX standard.
+96-07-31 A bug that caused side effects in subscript evaluation
+ when tracing was enabled for subscripts using ++ or --
+ has been fixed.
+96-07-31 To conform to the Posix standard getopts has been changed
+ so that the option char is set to ? when it returns with
+ a non-zero exit status.
+96-07-31 The handling of \} inside ${name...} has been fixed so
+ that the \ quotes the }.
+96-07-31 A bug that caused the read builtin to resume execution
+ after processing a trap has been fixed.
+96-07-31 [[ -s file ]] has been fixed so that if file is open
+ by ksh, it is flushed first.
+96-07-31 In some cases attributes and sizes for non exported
+ variables weren't being reset before running a script.
+96-07-31 The value of TMOUT was affected by changes make to
+ it in a subshell.
+96-07-31 The jobs command did not reflect changes make by
+ sending the CONT signal to a command.
+96-07-31 The error message for ksh -o unknown was incorrect.
+96-07-31 Functions invoked as name=value name, did not use
+ values from the calling scope when evaluating value.
+96-07-31 A bug in which the shell would reexecute previously
+ executed code when a shell script or coprocess was
+ run in the background has been fixed.
+96-07-31 A bug in which an empty here-document would leave
+ a file descriptor open has been fixed.
+96-07-31 A bug in which $(set -A array ...) would leave a
+ side effect has been fixed.
+96-07-31 A discipline function for a global variable defined
+ within a function defined with the function keyword,
+ incorrectly created a local variable of the same name
+ and applied the discipline to it.
+
+95-08-28 --- Release ksh93d ---
+95-08-28 The \ character was not handled correctly in replacement
+ patterns with ${x/pattern/replace}.
+95-08-28 A bug with read in which the line did not end with
+ a new-line has been fixed.
+95-08-28 A bug in file name generation which sometimes
+ appended a . for filenames that ended in / has
+ been fixed.
+95-08-28 +If a process is waited for after a status has
+ been returned by a previous wait, wait now
+ returns 127.
+95-08-28 A bug with hist (fc) -e which prevented a command
+ to re-executed after it had been edited has been fixed.
+95-08-28 A bug which prevented quoting from removing the meaning
+ of unary test operators has been fixed.
+95-08-28 A bug with typeahead and KEYBOARD traps with the
+ MULTIBYTE option set has been fixed.
+95-08-28 +Builtin functions can take a third argument which is
+ a void*.
+95-08-28 The nv_scan() function can restrict the scope of a walk
+ to the top scope.
+
+95-04-31 --- Release ksh93c ---
+95-04-31 The expansion of "$@" was incorrect when $1 was the null
+ string.
+95-04-31 A bug which could incorrectly report a syntax error in
+ a backquoted expression when a $ was preceded by \\
+ has been fixed.
+95-04-31 A bug which prevented the shell from exiting after
+ reporting an error when failing to open a script
+ has been fixed.
+95-04-31 A bug that could lead to memory corruption when a
+ large here document that required parameter or command
+ substitution was expanded has been fixed.
+95-04-31 A bug that could cause a core dump on some systems
+ after ksh detected an error when reading a function
+ has been fixed.
+95-04-31 A bug which could cause a coprocess to hang when
+ reading from a process that has terminated has been fixed.
+95-04-31 A bug which caused a script to terminate when set -e
+ was on and the first command of and && or || list
+ failed has been fixed.
+95-04-31 A bug with here documents inside $(...) when the delimiter
+ word is an identifier has been fixed.
+95-04-31 A bug which caused $0 to display the wrong value when
+ a script was invoked as an argument to the . command
+ and the eval command has been fixed.
+95-04-31 A bug that could cause the built-in sleep to hang
+ has been fixed.
+95-04-31 A bug introduces in 12/28/93b which caused the backslash
+ to be removed when it was followed by digit inside double
+ quotes in some instances has been fixed.
+95-04-31 A bug which could cause a core dump if ksh was invoked with
+ standard input closed has been fixed.
+95-04-31 A bug which could cause a core dump if typeset -A was
+ specified for an existing variable has been fixed.
+95-04-31 Variables that were unset but had attributes such as readonly
+ and export were not listed with readonly, export and typeset.
+95-04-31 Several problems with signals have been fixed.
+95-04-31 A bug which prevented ulimit -t from working has been fixed.
+ Also, a bug in which failed ulimits could cause a core dump
+ has also been fixed.
+95-04-31 A bug in expansion of the form ${name/#pattern/string} and
+ ${name/%pattern/string} has been fixed.
+95-04-31 A bug which caused read -r on a line that contained only
+ blanks to get a non-null value has been fixed.
+95-04-31 A bug introduced in the 'a' point release in which
+ ${x='\\'} expanded to \ when x was unset has been fixed.
+95-04-31 A bug which prevented a trap on EXIT from being executed
+ when the last command in a script was a function invocation
+ has been fixed.
+95-04-31 A bug which caused an interactive shell ignore input when
+ standard error was redirected to a file with exec,
+ and then restored with exec 2>&1 has been fixed.
+95-04-31 An interactive shell turns on monitor mode even when
+ standard error has been redirected to a file.
+95-04-31 A bug which could cause standard input to be incorrectly
+ positioned for the last command of a script has been fixed.
+95-04-31 A bug in the edit modes which allowed walking back in
+ the history file for more than HISTSIZE commands has
+ been fixed.
+95-04-31 A bug which could cause a core dump if variable TMPDIR was
+ changed between two command substitutions has been fixed.
+95-04-31. A bug which prevented a trap on EXIT from being cleared
+ has been fixed.
+95-04-31 A bug fixed for the v directive in vi MULTIBYTE has been
+ fixed.
+95-04-31 Code to for IFS handling of multibyte characters has
+ been added.
+95-04-31 The displaying of multibyte strings in export, readonly,
+ typeset, and execution traces has been fixed.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 A few changes have been made to the name-value library
+ that affect built-ins that use disciplines. The
+ changes allow disciplines to be shared by variables
+ and should make it possible to add new disciplines
+ without recompilation.
+95-04-31 +The name-value library interface has undergone significant
+ change for this revision. See the new nval.3 man page.
+
+94-12-31 --- Release ksh93b ---
+94-12-31 +Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+94-12-31 +If IFS contains two consecutive identical characters belonging
+ to the [:space:] class, then this character is treated as
+ a non-space delimiter so that each instance will delimit
+ a field. For example, IFS=$'\t\t' will cause two consecutive
+ tabs to delimit a null field.
+94-12-31 +The getopts command has a -a name option that specifies a
+ name that will be used for usage messages.
+94-12-31 A bug which caused unset RANDOM to dump core has been
+ fixed.
+94-12-31 A bug which prevented return for terminating a profile
+ or ENV file has been fixed.
+94-12-31 A bug which prevented standard input from being
+ directed to /dev/null for background jobs when
+ monitor mode was turned off has been fixed.
+94-12-31 Statements of the form typeset -options var[expr]=value
+ did not perform substitutions on expr as expected.
+94-12-31 A bug which prevented the shell from sending a HUP
+ signal to some background jobs that were not disowned
+ has been fixed.
+94-12-31 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked by exec
+ has been fixed.
+94-12-31 A bug which could cause a core dump when a discipline
+ function was unset within a discipline was fixed.
+94-12-31 The typeset builtin now accepts a first argument of
+ + or - for compatibility with ksh88.
+94-12-31 For compatibility with ksh88, the results of expansions
+ of command arguments will treat the extended character
+ match characters ()|& as ordinary characters.
+94-12-31 A bug which caused read to fail on a file that was
+ open for read/write with <> when the first operation
+ was print or printf has been fixed.
+94-12-31 When a job is suspended, it is put on the top of
+ the job list as required by the POSIX standard.
+94-12-31 The value of OPTARG when an option that required
+ an argument but didn't have one was incorrect in the
+ case the the option string began with a :.
+94-12-31 A bug which caused the terminal to get into a bad
+ state with some KEYBD traps in vi-mode has been fixed.
+94-12-31 A bug which caused an invalid trap to cause a script
+ to terminate, rather than just return an error, has
+ been fixed.
+94-12-31 Backreferencing sub-expressions in patterns and replacement
+ strings now works.
+94-12-31 A bug in chmod which caused the -R option to fail has
+ been fixed.
+94-12-31 +More signal names have been added for Solaris
+
+94-06-30 --- Release ksh93a ---
+94-06-30 An expansion bug which causes portions of a word after
+ a $((...)) expansion that contains a nested $var expansion
+ to be lost has been fixed.
+94-06-30 A bug that caused a core dump when a script that did not
+ have PWD set and did a cd inside command substitution
+ has been fixed.
+94-06-30 A bug which caused a core dump on some machines when
+ the LANG variable was assigned to has been fixed.
+94-06-30 A bug which incorrectly handled set disciplines that
+ performed arithmetic evaluation when the discipline
+ was called from the arithmetic evaluator has been fixed.
+94-06-30 A bug caused by an EXIT trap inside a function that
+ was executed in a subshell was fixed.
+94-06-30 If foo is a function, and not a program, then command foo
+ now reports that foo isn't found rather than invoking foo.
+94-06-30 The previous version incorrectly listed -A as an
+ invocation option. The -A option is only for set.
+94-06-30 A bug was fixed which caused ksh to loop when execution trace
+ was enabled and the PS4 prompt required command substitution.
+94-06-30 A bug which could cause the job control switch character
+ to be disabled when a script that enabled monitor mode
+ terminated was fixed.
+94-06-30 A bug in the macro expansion global replacement operator //,
+ when the pattern began with a [ or +( has been fixed.
+94-06-30 A bug which prevented ~ expansion from occurring when
+ it was terminated with a colon inside an assignment
+ has been fixed.
+94-06-30 A bug in the dot command which prevented autoload functions
+ from working has been fixed.
+94-06-30 A bug which caused a variable to be unset if the
+ its value were expanded inside a set discipline has
+ been fixed.
+94-06-30 Whence -a now longer reports that a defined function
+ is undefined.
+94-06-30 A bug on some systems in which $0 would be incorrect
+ in scripts invoked by name has been fixed.
+94-06-30 Here documents with an empty body now work.
+94-06-30 A bug which disabled argument passing and resetting
+ of options for a script invoked by name inside a
+ function has been fixed.
+94-06-30 A bug in which an EXIT trap set the caller of a function
+ would be executed if a command called inside a function
+ was not found has been fixed.
+94-06-30 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked has
+ been fixed.
+94-06-30 A bug which caused 2<&1- when applied to a shell built-in
+ to leave standard input closed has been fixed.
+94-06-30 A bug which caused the shell to incorrectly parse
+ $() command substitutions with nested case statements
+ has been fixed.
+
diff --git a/src/cmd/ksh93/RELEASE88 b/src/cmd/ksh93/RELEASE88
new file mode 100644
index 0000000..2466e39
--- /dev/null
+++ b/src/cmd/ksh93/RELEASE88
@@ -0,0 +1,422 @@
+This is a list of changes that have been made since the 11/16/88 version
+of ksh.
+
+1. New features in 12/28/93
+ a. Associative arrays. The new version of ksh supports both
+ associate arrays and the older indexed arrays with the same
+ array syntax. A new -A option of typeset is used to declare
+ an array to be associative. As with indexed arrays, $name is
+ equivalent to ${name[0]}. The prefix operator ! was added
+ to the parameter expansion syntax to expand to the list of
+ indices. For example, ${!name[@]} expands to the list of array
+ indices for variable name.
+
+ b. Several additions have been made to shell arithmetic:
+ 1. The shell now performs floating point arithmetic. The
+ typeset options -F and -E have been added for floating
+ point and scientific notation respectively.
+ 2. The prefix and postfix ++ and -- operators.
+ 3. The comma and ?: operators.
+ 4. The math library functions.
+ 5. An arithmetic for statement of the form
+ for ((expr1; expr2; expr3))
+ do ...
+ done
+ 6. Integer arithmetic extended up to base 64.
+
+ c. Some additions to the macro expansion syntax have been made
+ to specify substrings and sub-arrays:
+ 1. ${name:expr} expands to the substring of ${name} starting at
+ the character position defined by arithmetic expression expr.
+ 2. ${name:expr1:expr2} expands to the substring of ${name} starting
+ at expr1 and consisting of at most expr2 characters.
+ 3. ${name[@]:expr} expands to the values of ${name[@]} starting at
+ the element defined by arithmetic expression expr.
+ 4. ${name[@]:expr1:expr2} expands to at most expr2 values of
+ ${name} starting at expr1.
+ 5. ${@:expr} expands the positional parameters starting at expr.
+ 6. ${@:expr1:expr2} expands to at most expr2 positional parameters
+ starting at expr1.
+ 7. ${!name} expands to the name of the variable named by name.
+ It will expand to name unless name is reference variable.
+ 8. ${!name[sub]} expands to the name of the subscript of the
+ given variable. If sub is @ or * the list of subscripts
+ is generated.
+ 9. ${!prefix*} and ${!prefix@} expand to the list of variable
+ names beginning with prefix.
+ 10. The substring operators, # and % can be now be applied
+ with aggregates (@ or *) and are applied to each.
+ 11. ${name/pattern/string} expands to the value of name with
+ the first occurrence of pattern replaced by string.
+ With aggregates (@ or *) this operation is applied to each.
+ 12. ${name/#pattern/string} Same as above but the pattern
+ to be replaced must match at the beginning.
+ 13. ${name/%pattern/string} Same as above but the pattern
+ to be replaced must match at the end.
+ 14. ${name//pattern/string} expands to the value of name with
+ the each occurrence of pattern replaced by string.
+ With aggregates (@ or *) this operation is applied to each.
+
+ d. The name space for variables has been extended. The character '.'
+ can be used at the beginning of a name, and to separate identifiers
+ within a name. However, to create a name of the form, foo.bar,
+ the variable foo must exist. The namespace starting with .sh
+ is reserved for shell implementation variables. Exported
+ variable cannot contain a '.'.
+
+ e. Compound assignments. The assignment syntax, varname=value,
+ has been extended to allow assignments of the form
+ varname=(assignment_list). As elsewhere in the shell
+ spaces or tabs are optional around the parentheses, and
+ no space is permitted between the varname and the =. The
+ assignment_list can be one of the following:
+ 1. A list of words. In this case each word is expanded as
+ in a for list and the resulting items become elements
+ of the indexed array varname.
+ 2. A list of subscript assignments in the form
+ [subscript]=value. In this, these elements become
+ elements of the associative array varname.
+ 3. A list of assignments; simple or compound. In this
+ case, each assignment is made to varname.name, where
+ name is the name of the enclosed assignment.
+ 4. Assignments in the form of readonly or typeset
+ statements. In this case each assignment is made as
+ in 3 above, and the attributes are given to the
+ corresponding variable.
+ In case 3 and 4 above, the value of "$varname" after
+ the above assignment is (assignment_list), where the
+ assignment_list produced would reproduce all of the
+ variables under varname.*.
+
+ f. Function names of the form variable.action (called discipline
+ functions) can be defined where variable is any valid variable
+ name and action is get, set, or unset. The function variable.get
+ is invoked each time the variable is referenced. The set
+ discipline is invoked each time the variable is assigned to.
+ The unset discipline is invoked when a variable is unset.
+ The new variables .sh.name, .sh.subscript, and .sh.value are
+ defined inside the function body. Other shell extensions
+ may have their own set of discipline functions.
+
+ g. The compound command !, which negates the return value of the
+ following pipeline, has been added.
+
+ h. On systems that support dynamic loading with dlopen(), it is
+ now possible to add built-in commands at runtime with the
+ a builtin command named builtin.
+
+ i. The following builtins have been added:
+ 1. command name [ ... ]
+ 2. sleep [decimal-seconds]
+ 3. builtin [-ds] [-f file] [name...]
+ 4. getconf name [pathname]
+ 5. disown [job...]
+
+ j. An addition format for literal strings, $'....' can
+ be used where ever literal strings are valid. The string
+ inside the single quotes will be converted using the ANSI-C
+ escape conventions. Additionally, the escape sequence \E
+ expands to the escape character (default \033) whenever ANSI-C
+ escape sequences are recognized.
+
+ k. A typeset -n option has been added which causes the value of a
+ variable to be treated as a reference to another variable so that
+ variables can be indirectly named. For example, if $1 contains
+ the name of a variable, then typeset -n foo=$1 causes the variable
+ foo to be synonymous with the variable whose name is $1. A builtin
+ alias, nameref='typeset -n' has been added to aid mnemonics.
+ Reference names cannot contain a '.'. Whenever that portion of
+ a variable up to the first '.' matches a reference name, the
+ reference value is substituted. For example, with nameref foo=.top,
+ then ${foo.bar} is equivalent to ${.top.bar}. When used as the
+ index of a for or select loop, each assignment causes a
+ new name reference to occur.
+
+ l. The KEYBD trap has been added which is triggered when a key
+ or escape sequence is typed while reading from the keyboard
+ in an edit mode. This, combined with some new variables
+ makes it possible to program your key bindings in ksh.
+
+ m. New variables have been added:
+ 1. FIGNORE defines a set of file names to be ignored in each
+ directory when performing pathname expansion, replacing
+ the rule that requires that a leading . be matched explicitly.
+ 2. Variable sh.edchar contains the value of the keyboard character
+ that has been entered when processing a KEYBD trap. If the value
+ is changed as part of the trap action, then the new value replaces
+ the key or keys that caused the trap.
+ 3. Variable sh.edcol is set to the character position of the cursor
+ within the input buffer during a KEYBD trap.
+ 4. Variable sh.edmode is set to the escape character when in vi
+ insert mode.
+ 5. Variable sh.edtext is set to the contents of the input buffer
+ during a KEYBD trap.
+ 6. HISTEDIT is checked before FCEDIT. FCEDIT is obsolete.
+ 7. HISTCMD is the number of the current command in the history
+ file.
+ 8. Variable .sh.version is set to the version string for
+ this shell.
+ 9. Variable .sh.name is set to the name of the variable
+ that that was referenced or assigned to when executing a get
+ or set discipline function.
+ 10. Variable .sh.subscript is set to the subscript for the variable
+ that was referenced or assign to when executing a get or
+ set discipline function.
+ 11. Variable .sh.value is set to the new value for the variable
+ that was assigned to when executing the set discipline function.
+
+ n. New invocation and set -o options have been added:
+ 1. set -o notify (or set -b) causes background completion messages
+ to be displayed as soon as the job completes.
+ 2. There is a compile time option named KIA which enables
+ creation of a relational database for commands, variables
+ and functions defined and referenced by a script. The
+ option -I <filename>, causes the database to be generated
+ in <filename>. The database format can be queried via
+ the cql command.
+ o. ksh93 can read and evaluate pre-compiled scripts generated by
+ a separate program called shcomp.
+ p. More work on internationalization has been added:
+ 1. The decimal point character is processed per locale
+ 2. A $ can be placed in front of each string to indicate
+ that the string needs translation but is otherwise ignored.
+ This means that if a message catalog of all $"..." strings
+ is generated, then a program such as print $"hello world"
+ could display "bonjour monde" in the french locale.
+ q. Backreferences have been added to pattern matching. The sequence
+ \d, where d is a digit from 1-9, matches the same string as
+ the d-th previous parenthesis group. Backreferences
+ can be used within patterns, and within replacement strings
+ with any of the ${name/...} operators.
+
+2. Changes made in 12/28/93
+ a. The output format of many commands has changed as follows:
+ 1. System error messages are displayed whenever a failure
+ is caused by a system call.
+ 2. The exit status has changed in many cases:
+ a. USAGE messages cause an exit status of 2.
+ b. Commands not found cause exit - 127.
+ c. Command found, but not executable - 126.
+ d. Terminated because of signal - 256+sig
+ 3. The output of values from built-ins that contain special
+ characters are quoted in a manner that then can be re-input.
+ 4. The trace output puts quotes around the output so that it
+ can be reused as input.
+ 5. The output for trap is in a format that can be reinput the
+ the shell to restore the traps.
+ 6. kill -l lists the signal names without numbers as
+ required by the POSIX standard.
+
+ b. The following changes have been made to shell functions:
+ 1. The semantics of functions declared with name() has changed
+ to conform with the IEEE-POSIX 1003.2 standard. In particular,
+ these functions are executed in a dot script environment rather
+ than a separated function environment so that there are no
+ local variables and no scoping for traps.
+ 2. Functions declared as function name, preserve the old ksh
+ semantics can be also used as the first argument to the dot (.)
+ command to have them executed in a dot script environment.
+
+ c. The command search rules have changed as follows:
+ 1. Special built-ins (those with a dagger in front of them) are
+ executed first.
+ 2. Functions are executed next.
+ 3. Other built-ins that do not require an executable version
+ (for example cd and read) come next.
+ 4. If the command name contains a slash, the pathname corresponding
+ to the command name is executed.
+ 5. If name corresponds to a previously encountered pathname
+ on the PATH variable, the corresponding command is executed.
+ 6. If the command name does not contain a slash, then the PATH
+ variable is used to find an executable by that name. If
+ the directory that the command is found is also contained in
+ the FPATH variable, then the command treated as a function.
+ If the shell has a built-in version of the command corresponding
+ to this command, then the built-in version of this command
+ is executed. Otherwise, the shell remembers that pathname
+ corresponding to this command name and executes this pathname.
+ 7. If the name is not found on PATH, then the directories in
+ FPATH are searched. If found, then the command is executed
+ as a function.
+
+ d. Built-in commands options now conform to the IEEE-POSIX 1003.2
+ conventions with some additions. In particular,
+ name -?
+ will now print a Usage line for name, except for true, false,
+ colon, login, newgrp, echo, [, and command.
+
+ e. Tilde expansion is now performed as part of the word expansions.
+ The effect of this is that if word begins with ~ in ${name op word},
+ it will be expanded unless escaped.
+
+ f. Pathname expansion is no longer performed on redirection words
+ unless the shell is interactive.
+
+ g. Changes to shell and options:
+ 1. The -n option has been enhanced to produce more warning and
+ portability messages.
+ 2. The -C option is equivalent to -o noclobber. Files are
+ created with O_EXCL when -C is on.
+
+ h. The following changes have been made to [[...]]:
+ 1. A string by itself is equivalent to -n string.
+ 2. -e has been added as equivalent to -a.
+ 3. == has been added as equivalent =.
+ 4. -a and = are now considered obsolete.
+ 5. Arithmetic comparisons are now considered obsolete.
+
+ i. kill has been changed as follows:
+ 1. Signal names can be upper case or lower case.
+ 2. Numerical arguments to kill -l cause the given signal names to
+ be displayed.
+ 3. String arguments to kill -l cause the given signal numbers to
+ be displayed.
+ 4. Synopsis changed for getopts conformance.
+
+ j. print has a -f format option which is equivalent to
+ the IEEE POSIX printf. Both print -f format, and
+ printf have the following extensions from IEEE POSIX:
+ 1. Floating point formats are supported.
+ 2. Size and precision specifications can be *.
+ 3. The %d option can take an argument after precision to
+ specify the base that the number will be displayed.
+ 4. A %q format can be used to output a string quoted so
+ that it can be re-input to the shell.
+ 5. A %P format can be used to output the shell pattern which
+ corresponds to the give extended regular expression.
+ 6. For numerical fields, the arguments can be arithmetic
+ expressions which will be evaluated.
+ 7. The %n format works as described in ANSI-C.
+
+ k. The following changes have been made to fc:
+ 1. It has been renamed hist. fc is now a predefined alias.
+ 2. hist uses ${HISTEDIT:-$FCEDIT}. FCEDIT is obsolete.
+ 3. A new -s option is equivalent to the obsolete -e -.
+ 4. If the first argument refers to a command earlier than the
+ first accessible command, it now implies the first accessible
+ command, so that hist -l 1 lists all accessible history commands.
+
+ l. The dot command (.) has changed as follows:
+ 1. The argument can be the name of a function declared as
+ function name. The function will execute without creating a
+ new scope.
+ 2. If there are arguments to the given script or function,
+ the positional parameters are restored to their original
+ value when . completes.
+
+ m. The read built-in has been changed as follows:
+ 1. A -A option to read has been added to allow the fields to be
+ read into an indexed array.
+ 2. A -t n option has been added which causes read to
+ timeout after n seconds when reading from a slow device.
+ 3. A -d char option has been added which causes the read
+ to terminate at char rather than at new-line.
+
+ n. The trap command has been changed as follows:
+ 1. Trap names can be either upper case or lower case.
+ 2. Trap -p cause only the specified trap values to be displayed.
+ 3. The value of trap in a subshell will be the value in the parent
+ shell until a call to trap which changes the trap settings has
+ been made. Thus, savetraps=$(trap) works as required by the
+ POSIX standard.
+
+ o. The exec command has been extended as follows:
+ 1. The -c option clears the environment first.
+ 2. The -a name option sets argv[0] to name for the program.
+
+ p. true and false are built-ins, not aliases to built-ins.
+
+ q. test has been modified to conform to the IEEE-POSIX 1003.2
+ standard when there are three or less arguments.
+
+ r. umask -S option displays the mask in a symbolic format.
+
+ s. wait now returns the correct exit status of any previous
+ background job that has not been waited for, not just
+ the most recent one.
+
+ t. The whence built-in has an option -a which causes all
+ uses for the given command name to be reported.
+
+ u. unalias has -a option to clear all the aliases.
+
+ v. The times built-in command has been removed. The time
+ reserved word, without a command, gives time cumulative
+ time for the shell and its children. A built-in alias
+ for times should enable scripts using times to continue
+ to run.
+
+ w. Command substitution and arithmetic substitution will now be
+ performed for PS1, ENV, and PS4 evaluation in addition to
+ parameter expansion.
+
+ x. The SECONDS variable now displays elapsed time in floating
+ point seconds with 3 places after the decimal point by
+ default.
+
+ y. The getopts built-in now handles the complete libast optget
+ functionality. If any errors have occurred with getopts
+ when it has reached the end of arguments, then the Usage
+ message will be generated from the option string and the
+ exit status from getopts will be 2 rather than 1. The
+ usage message will be stored in the OPTARG variable if
+ the option string contains a leading colon; otherwise
+ it will be printed on standard error automatically.
+
+ z. THE ENV file is only processed for interactive shell
+ invocations. In addition, the -x attributes for
+ aliases and functions is ignored.
+
+ aa. The built-in edit modes have been changed as follows:
+ 1. The pathname completion and pathname listing options
+ now perform command completion and command listing
+ when applied to a word in the command position.
+ 2. In emacs mode ^N as the first related command after
+ the prompt will move to the next command relative to the
+ last known history position.
+ 3. In emacs mode, successive kill and delete commands will
+ accumulate their data in the kill buffer, by appending or
+ prepending as appropriate. This mode will be reset by any
+ command not adding something to the kill buffer.
+ 4. The control-T of emacs mode has been changed to behave like
+ control-T in gnu-emacs.
+ bb. The TMOUT variable also sets a limit for select timeouts
+ and default timeouts for read.
+
+
+4. The source code has undergone significant modification.
+ a. Much of the code has been rewritten, In many cases this has
+ resulted in significant performance improvement.
+
+ b. The code is organized differently. See the README files
+ for more details.
+
+ c. Most configuration parameters now get generated using
+ the FEATURE mechanism of nmake. Other options are set
+ in the OPTIONS file.
+
+ c. The are several new compile time options. See the README
+ file for details. Some of the old ones have been removed.
+
+ d. The install script is a Mamfile that is generated by
+ nmake and processed by a script that comes with the
+ distribution.
+
+ e. There are far fewer global names. This should make it
+ must easier to add built-in commands without worrying
+ about conflicts.
+
+ f. The code uses the sfio library which makes it possible
+ to mix with stdio.
+
+ g. The code is written in ANSI C with full prototypes.
+ The code is based on the IEEE POSIX 1003.1 standard.
+ The code can be compiled with K&R C and with C++ by
+ using the ANSI cpp that comes with nmake or running
+ the code through the proto filter before pre-processing.
+ This happens automatically with our shipping system.
+
+ h. There is a programming interface for capturing references
+ and assignment to shell variables. It is also possible
+ to intercept variable creation and supply the array processing
+ function for that variable. See nval.3 for a description.
diff --git a/src/cmd/ksh93/RELEASE93 b/src/cmd/ksh93/RELEASE93
new file mode 100644
index 0000000..e99c878
--- /dev/null
+++ b/src/cmd/ksh93/RELEASE93
@@ -0,0 +1,455 @@
+This is a list of changes that have been made since the 12/28/93 version
+of ksh.
+
+1. New features in 12/28/93b
+ a. If IFS contains two consecutive identical characters belonging
+ to the [:space:] class, then this character is treated as
+ a non-space delimiter so that each instance will delimit
+ a field. For example, IFS=$'\t\t' will cause two consecutive
+ tabs to delimit a null field.
+ b. The getopts command has a -a name option that specifies a
+ name that will be used for usage messages.
+
+2. New features in 12/28/93e
+ a. The math functions, atan2, hypot, fmod, and pow were added.
+ b. When a shared library is loaded, if the function lib_init()
+ is defined in the library, it is invoked the first time that
+ the library is loaded with builtin -f library.
+
+3. New features in 12/28/93f
+ a. Hostnames in addition to host addresses can be given in
+ /dev/tcp/host/port virtual file names.
+ b. File name completion and expansion now quotes special
+ characters in file names from both emacs and vi edit modes.
+
+4. New features in 12/28/93g
+ a. The pipefail option has been added. With pipefail
+ enabled, a pipeline will not complete until all
+ commands are complete, and the return value will
+ be that of the last command to fail, or zero if
+ all complete successfully.
+ b. When an executable is found on a given path,
+ the appropriate library path variable is prepended
+ with a corresponding library directory.
+5. New features in 12/28/93h
+ a. The PATH search algorithm has been modified to look
+ for a file named .fpath in each bin directory and if
+ found, to search for functions in this directory if
+ it cannot find the command in that directory.
+ b. When performing pathname expansion, the shell checks
+ to see whether each directory it reads is case sensitive
+ or not, and performs the matching accordingly.
+ c. The %T format for printing formatted date/time.
+6. New features in 12/28/93i
+ a. Most of the built-in commands and ksh itself are now
+ self documenting. Running command --man will produce
+ screen output. Running command --html produces the
+ man page in html format.
+ b. The getopts builtin can process command description
+ strings to produce man pages.
+
+7. Bugs fixed in 12/28/93a for default OPTIONS
+ a. An expansion bug which causes portions of a word after
+ a $((...)) expansion that contains a nested $var expansion
+ to be lost has been fixed.
+ b. A bug that caused a core dump when a script that did not
+ have PWD set and did a cd inside command substitution
+ has been fixed.
+ c. A bug which caused a core dump on some machines when
+ the LANG variable was assigned to has been fixed.
+ d. A bug which incorrectly handled set disciplines that
+ performed arithmetic evaluation when the discipline
+ was called from the arithmetic evaluator has been fixed.
+ e. A bug caused by an EXIT trap inside a function that
+ was executed in a subshell was fixed.
+ f. If foo is a function, and not a program, then command foo
+ now reports that foo isn't found rather than invoking foo.
+ g. The previous version incorrectly listed -A as an
+ invocation option. The -A option is only for set.
+ h. A bug was fixed which caused ksh to loop when execution trace
+ was enabled and the PS4 prompt required command substitution.
+ i. A bug which could cause the job control switch character
+ to be disabled when a script that enabled monitor mode
+ terminated was fixed.
+ j. A bug in the macro expansion global replacement operator //,
+ when the pattern began with a [ or +( has been fixed.
+ k. A bug which prevented ~ expansion from occurring when
+ it was terminated with a colon inside an assignment
+ has been fixed.
+ l. A bug in the dot command which prevented autoload functions
+ from working has been fixed.
+ m. A bug which caused a variable to be unset if the
+ its value were expanded inside a set discipline has
+ been fixed.
+ n. Whence -a now longer reports that a defined function
+ is undefined.
+ o. A bug on some systems in which $0 would be incorrect
+ in scripts invoked by name has been fixed.
+ p. Here documents with an empty body now work.
+ 1. A bug which disabled argument passing and resetting
+ of options for a script invoked by name inside a
+ function has been fixed.
+ r. A bug in which an EXIT trap set the caller of a function
+ would be executed if a command called inside a function
+ was not found has been fixed.
+ s. A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked has
+ been fixed.
+ t. A bug which caused 2<&1- when applied to a shell built-in
+ to leave standard input closed has been fixed.
+ u. A bug which caused the shell to incorrectly parse
+ $() command substitutions with nested case statements
+ has been fixed.
+
+8. Bugs fixed in 12/28/93b for default OPTIONS
+ a. A bug which caused unset RANDOM to dump core has been
+ fixed.
+ b. A bug which prevented return for terminating a profile
+ or ENV file has been fixed.
+ c. A bug which prevented standard input from being
+ directed to /dev/null for background jobs when
+ monitor mode was turned off has been fixed.
+ d. Statements of the form typeset -options var[expr]=value
+ did not perform substitutions on expr as expected.
+ e. A bug which prevented the shell from sending a HUP
+ signal to some background jobs that were not disowned
+ has been fixed.
+ f. A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked by exec
+ has been fixed.
+ g. A bug which could cause a core dump when a discipline
+ function was unset within a discipline was fixed.
+ h. The typeset builtin now accepts a first argument of
+ + or - for compatibility with ksh88.
+ i. For compatibility with ksh88, the results of expansions
+ of command arguments will treat the extended character
+ match characters ()|& as ordinary characters.
+ j. A bug which caused read to fail on a file that was
+ open for read/write with <> when the first operation
+ was print or printf has been fixed.
+ k. When a job is suspended, it is put on the top of
+ the job list as required by the POSIX standard.
+ l. The value of OPTARG when an option that required
+ an argument but didn't have one was incorrect in the
+ case the the option string began with a :.
+ m. A bug which caused the terminal to get into a bad
+ state with some KEYBD traps in vi-mode has been fixed.
+ n. A bug which caused an invalid trap to cause a script
+ to terminate, rather than just return an error, has
+ been fixed.
+ o. Backreferencing sub-expressions in patterns and replacement
+ strings now works.
+ p. A bug in chmod which caused the -R option to fail has
+ been fixed.
+
+9. Bugs fixed in 12/28/93c for default OPTIONS
+ a. The expansion of "$@" was incorrect when $1 was the null
+ string.
+ b. A bug which could incorrectly report a syntax error in
+ a backquoted expression when a $ was preceded by \\
+ has been fixed.
+ c. A bug which prevented the shell from exiting after
+ reporting an error when failing to open a script
+ has been fixed.
+ d. A bug that could lead to memory corruption when a
+ large here document that required parameter or command
+ substitution was expanded has been fixed.
+ e. A bug that could cause a core dump on some systems
+ after ksh detected an error when reading a function
+ has been fixed.
+ f. A bug which could cause a coprocess to hang when
+ reading from a process that has terminated has been fixed.
+ g. A bug which caused a script to terminate when set -e
+ was on and the first command of and && or || list
+ failed has been fixed.
+ h. A bug with here documents inside $(...) when the delimiter
+ word is an identifier has been fixed.
+ i. A bug which caused $0 to display the wrong value when
+ a script was invoked as an argument to the . command
+ and the eval command has been fixed.
+ j. A bug that could cause the built-in sleep to hang
+ has been fixed.
+ k. A bug introduces in 12/28/93b which caused the backslash
+ to be removed when it was followed by digit inside double
+ quotes in some instances has been fixed.
+ l. A bug which could cause a core dump if ksh was invoked with
+ standard input closed has been fixed.
+ m. A bug which could cause a core dump if typeset -A was
+ specified for an existing variable has been fixed.
+ n. Variables that were unset but had attributes such as readonly
+ and export were not listed with readonly, export and typeset.
+ o. Several problems with signals have been fixed.
+ p. A bug which prevented ulimit -t from working has been fixed.
+ Also, a bug in which failed ulimits could cause a core dump
+ has also been fixed.
+ q. A bug in expansion of the form ${name/#pattern/string} and
+ ${name/%pattern/string} has been fixed.
+ r. A bug which caused read -r on a line that contained only
+ blanks to get a non-null value has been fixed.
+ s. A bug introduced in the 'a' point release in which
+ ${x='\\'} expanded to \ when x was unset has been fixed.
+ t. A bug which prevented a trap on EXIT from being executed
+ when the last command in a script was a function invocation
+ has been fixed.
+ u. A bug which caused an interactive shell ignore input when
+ standard error was redirected to a file with exec,
+ and then restored with exec 2>&1 has been fixed.
+ v. An interactive shell turns on monitor mode even when
+ standard error has been redirected to a file.
+ w. A bug which could cause standard input to be incorrectly
+ positioned for the last command of a script has been fixed.
+ y. A bug in the edit modes which allowed walking back in
+ the history file for more than HISTSIZE commands has
+ beed fixed.
+ z. A bug which could cause a core dump if variable TMPDIR was
+ changed between two command substitutions has been fixed.
+ aa. A bug which prevented a trap on EXIT from being cleared
+ has been fixed.
+
+10. Bugs fixed in 12/28/93d for default OPTIONS
+ a. The \ character was not handled correctly in replacement
+ patterns with ${x/pattern/replace}.
+ b. A bug with read in which the line did not end with
+ a new-line has been fixed.
+ c. A bug in file name generation which sometimes
+ appended a . for filenames that ended in / has
+ been fixed.
+ d. If a process is waited for after a status has
+ been returned by a previous wait, wait now
+ returns 127.
+ e. A bug with hist (fc) -e which prevented a command
+ to re-executed after it had been edited has been fixed.
+ f. A bug which prevented quoting from removing the meaning
+ of unary test operators has been fixed.
+
+11. Bugs fixed in 12/28/93e for default OPTIONS
+ a. Empty command substitutions of the form $() now work.
+ b. whence -v foo now gives the correct result after calling
+ builtin -d foo.
+ c. A bug in right to left arithmetic assignment for which
+ the arithmetic expression (( y = x = 1.5 )) did not
+ yield 1 for y when x was declared typeset -i was fixed.
+ d. printf has been fixed to handle format containing \0
+ and/or \0145 correctly. In addition, characters following
+ %b in the format string are no longer displayed when
+ the operand contains \c.
+ e. A bug in printf that could cause the %E format to
+ produce unnormalized results has been fixed.
+ f. A bug which causes some arithmetic expressions to be
+ incorrectly evaluated as integer expressions rather
+ that floating point has been fixed.
+ g. Functions defined inside a subshell no longer remain
+ defined when the subshell completes.
+ h. The error message from sh -c ';echo foo' has been
+ corrected.
+ i. The format for umask -S has been changed to agree
+ with the specification in the POSIX standard.
+ j. A bug that caused side effects in subscript evaluation
+ when tracing was enabled for subscripts using ++ or --
+ has been fixed.
+ k. To conform to the Posix standard getopts has been changed
+ so that the option char is set to ? when it returns with
+ a non-zero exit status.
+ l. The handling of \} inside ${name...} has been fixed so
+ that the \ quotes the }.
+ m. A bug that caused the read builtin to resume execution
+ after processing a trap has been fixed.
+ n. [[ -s file ]] has been fixed so that if file is open
+ by ksh, it is flushed first.
+ o. In some cases attributes and sizes for non exported
+ variables weren't being reset before running a script.
+ p. The value of TMOUT was affected by changes make to
+ it in a subshell.
+ q. The jobs command did not reflect changes make by
+ sending the CONT signal to a command.
+ r. The error message for ksh -o unknown was incorrect.
+ s. Functions invoked as name=value name, did not use
+ values from the calling scope when evaluating value.
+ t. A bug in which the shell would reexecute previously
+ executed code when a shell script or coprocess was
+ run in the background has been fixed.
+ u. A bug in which an empty here-document would leave
+ a file descriptor open has been fixed.
+ v. A bug in which $(set -A array ...) would leave a
+ side effect has been fixed.
+ w. A discipline function for a global variable defined
+ within a function defined with the function keyword,
+ incorrectly created a local variable of the same name
+ and applied the discipline to it.
+
+12. Bugs fixed in 12/28/93f for default OPTIONS
+ a. A bug which would cause the secondary prompt to be
+ displayed when a user entered a literal carriage
+ return has been fixed.
+ b. I bug which caused ksh read -s name to core dump was
+ fixed.
+ c. I bug with the expansion of \} and \] inside double
+ quoted strings that also contained variable expansions
+ has been fixed
+ d. Changes in the 'e' point release caused autoload
+ functions invoked from within command substitution
+ to fail. This has been fixed.
+ e. A bug in the processing of here-documents that could
+ prevent variable substitution to occur after $(...) command
+ substitution for long here documents has been fixed.
+ f. A bug caused by a race condition that could cause SIGTERM
+ to be ignored by a child process has been fixed.
+ g. A bug which prevented the startup of a coprocess immediately
+ after killing a running coprocess has been fixed.
+ h. ulimit foobar, where foobar is not an arithmetic
+ expression, now gives an error message as it did with ksh88
+ instead of setting the file size limit to 0.
+ i. A bug which could cause an interactive shell to terminate when
+ the last process of a pipeline was a POSIX function was fixed.
+ j. A bug which could cause command substitution of a shell script
+ to core dump has been fixed.
+ k. A security hole was fixed in suid_exec.
+ l. Arithmetic functions such as pow() that take more than
+ one argument, did not work if arguments other than the
+ first contained parenthesized sub-expression.
+ m. The error message from a script containing an incomplete
+ arithmetic expression has been corrected.
+ n. A bug which caused a core dump on some machines when
+ the value of a name reference contained a positional
+ parameter and the name reference was not defined inside
+ a function has been fixed.
+ o. Arithmetic expressions now correctly handle hexidecimal
+ constants.
+ p. A bug in which integer variables could be expanded
+ with a leading 10# when declared with typeset -i
+ multiple times has been corrected.
+ q. A bug in which IFS wasn't correctly restored when
+ set within command substitution has been fixed.
+ r. The _ character is now considered as part of a word
+ with the M-f and M-b emacs directives as it was in ksh88.
+
+13. Bugs fixed in 12/28/93g for default OPTIONS
+ a. A bug in which a name reference could be created to
+ itself and later cause the shell to get into an infinite
+ loop has been fixed.
+ b. A bug in shcomp relating to compound variables was fixed.
+ c. A bug introduced in 'e' in which leading 0's in -Z
+ fields caused the value to be treated as octal for arithmetic
+ evaluation has been fixed.
+ d. A bug when a name reference with a shorter name than
+ the variable it references was the subject of a compound
+ assignment has been fixed.
+ e. A bug which in which assignment to array variables in
+ a subshell could effect the parent shell has been
+ fixed.
+ f. read name?prompt was putting a 0 byte at the end of the
+ prompt on standard error.
+ g. A bug in [[ string1 > string2 ]] when ksh was run with -x
+ has been fixed.
+ k. A bug in which the escape character was not processed
+ correctly inside {...} when brace expansion is enabled
+ has been fixed, for example {\$foo}.
+ l. A bug in line continuation in here-documents has been
+ fixed.
+ m. The default base when not specified with typeset -i is
+ 10 in accordance with the documentation. Previously,
+ the value was determined by the first assignment.
+ n. A parsing bug in which a # preceded alphanumeric
+ characters inside a command substitution caused
+ a syntax error to be reported has been fixed.
+ o. A bug in which a decimal constant represented as 10#ddd
+ where ddd was more than five digits generated a syntax
+ error has been fixed.
+ p. A bug in here document expansion in which ${...} expansions
+ were split across buffer boundaries has been fixed.
+
+14. Bugs fixed in 12/28/93h for default OPTIONS
+ a. I bug in shcomp for compilation of unary operators with [[...]]
+ has been fixed.
+ b. A bug in which the value of $? was changed when executing
+ a keyboard trap has been fixed.
+ c. The handling of SIGCHLD has been changed so that the
+ trap is not triggered while executing trap commands
+ to avoid recursive trap calls.
+ d. I bug in which a local variable in a function declared readonly
+ would generated an error when the function went out of
+ scope has been fixed.
+ e. I bug in which \<new_line> entered from the keyboard
+ with the KEYBD trap enabled has been fixed.
+ f. The error message for a misplaced ((, for example print ((3),
+ was often garbled and has been fixed.
+ g. I bug in the KEYBD trap in which escape sequences of the form
+ <ESC>[#~ were not being handled as a unit has been fixed.
+ h. A bug in which ksh would consider expressions like [[ (a) ]]
+ as syntax errors has been fixed.
+ i. A function defined as foo() without a function body
+ was not reported as a syntax error.
+ j. A bug in which ksh could run out of file descriptors when
+ a stream was repeatedly opened with exec and read from
+ has been fixed.
+ k. A bug introduced when fixing item n from the 'g' point
+ release has been fixed.
+
+15. Bugs fixed in 12/28/93i for default OPTIONS
+ a. A bug in which a script could terminate when getopts
+ encountered an error when invoked inside a function
+ has been fixed.
+ b. When a symbolic link was specified as the name of
+ the script to invoke by name, the value of $0 was
+ set to the real file name rather than the link name
+ in some cases and this has been fixed.
+
+16. Bug fixes for specific non-default option combinations.
+ a. More signal names have been added for Solaris
+ b. A bug fixed for the v directive in vi MULTIBYTE has been
+ fixed.
+ c. Code to for IFS handling of multibyte characters has
+ been added.
+ d. The displaying of multibyte strings in export, readonly,
+ typeset, and execution traces has been fixed.
+ e. A bug with type ahead and KEYBOARD traps with the
+ MULTIBYTE option set has been fixed.
+ f. The k-shell information abstraction database option, KIA,
+ has been revamped for the 'e' point release.
+ g. A bug in brace pattern expansions that caused expressions
+ such as {foo\,bar,bam} to expand incorrectly have been fixed.
+ h. On the U/WIN version for Window 95 and Windows NT,
+ when a directory beginning with a letter followed by
+ a colon is given to cd, it is assumed to be an absolute
+ directory.
+ i. There was a bug in the compile option that does not
+ use fork() in which the current option settings where
+ not propagated to sub-shells.
+ j. A bug in setting .sh.editchar during the KEYBD trap
+ for the MULTIBYTE option was fixed in release 'h'.
+ k. A bug in which the precision given as an argument
+ to printf was not working has been fixed.
+
+17. Other changes to 12/28/93[abcdefghi]
+ a. A couple of minor changes to make adding built-ins easier.
+ b. Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+ c. A few changes have been made to the name-value library
+ that affect built-ins that use disciplines. The
+ changes allow disciplines to be shared by variables
+ and should make it possible to add new disciplines
+ without recompilation.
+ d. The name-value library interface has undergone significant
+ change for this revision. See the new nval.3 man page.
+ e. Builtin functions can take a third argument which is
+ a void*.
+ f. The nv_scan() function can restrict the scope of a walk
+ to the top scope. Starting in 'f', nv_scan() has an
+ additional pointer argument that is passed to each invoked
+ function.
+ g. Starting with release 'f', an empty for list behave like
+ a for list with null expansions. It produces a warning
+ message with sh -n.
+ h. Starting with release 'f' the code has been modified to
+ work with EBCDIC as well as ASCII.
+ i. Starting with the release 'g', the name-value pair library
+ uses the cdt library rather than the hash library.
+ j. The sh_fun() function now takes third argument which
+ is an argument list for the invoked discipline function
+ or built-in.
+ k. A callback function can be installed which will give
+ notification of file duplications and file closes.
+
+18. Incompatibilities with 12/28/93 version.
+ None intentional.
+
diff --git a/src/cmd/ksh93/TYPES b/src/cmd/ksh93/TYPES
new file mode 100644
index 0000000..6eb6f41
--- /dev/null
+++ b/src/cmd/ksh93/TYPES
@@ -0,0 +1,182 @@
+
+The ability for users to define types has been added to ksh93t.
+Here is a quick summary of how types are defined and used in ksh93t.
+This is still a work in progress so some changes and additions
+are likely.
+
+A type can be defined either by a shared library or by using the new
+typeset -T option to the shell. The method for defining types via
+a shared library is not described here. However, the source file
+bltins/enum.c is an example of a builtin that creates enumeration types.
+
+By convention, typenames begin with a capitol letter and end in _t.
+To define a type, use
+ typeset -T Type_t=(
+ definition
+ )
+where definition contains assignment commands, declaration commands,
+and function definitions. A declaration command (for example typeset,
+readonly, and export), is a built-in that differs from other builtins in
+that tilde substitution is performed on arguments after an =, assignments
+do not have to precede the command name, and field splitting and pathname
+expansion is not performed on the arguments.
+For example,
+ typeset -T Pt_t=(
+ float -h 'length in inches' x=1
+ float -h 'width in inches' y=0
+ integer -S count=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+ set()
+ {
+ (( _.count++))
+ }
+ )
+
+defines a type Pt_t that has three variables x, y, and count defined as well
+as the discipline functions len and set. The variable x has an initial value
+of 1 and the variable y has an initial value of 0. The new -h option argument,
+is used for documentations purposes as described later and is ignored outside
+of a type definition.
+
+
+The variable count has the new -S attribute which means that it is shared
+between all instances of the type. The -S option to typeset is ignored
+outside of a type definition. Note the variable named _ that is used inside
+the function definition for len and set. It will be a reference to the
+instance of Pt_t that invoked the function. The functions len and set
+could also have been defined with function len and function set, but
+since there are no local variables, the len() and set() form are more
+efficient since they don't need to set up a context for local variables
+and for saving and restoring traps.
+
+If the discipline function named create is defined it will be
+invoked when creating each instance for that type. A function named
+create cannot be defined by any instance.
+
+When a type is defined, a declaration built-in command by this name
+is added to ksh. As with other shell builtins, you can get the man page
+for this newly added command by invoking Pt_t --man. The information from
+the -h options will be embedded in this man page. Any functions that
+use getopts to process arguments will be cross referenced on the generated
+man page.
+
+Since Pt_t is now a declaration command it can be used in the definition
+of other types, for example
+ typeset -T Rect_t=( Pt_t ur ll)
+
+Because a type definition is a command, it can be loaded on first reference
+by putting the definition into a file that is found on FPATH.
+Thus, if this definition is in a file named Pt_t on FPATH, then
+a program can create instances of Pt_t without first including
+the definition.
+
+A type definition is readonly and cannot be unset. Unsetting non-shared
+elements of a type restores them to their default value. Unsetting a
+shared element has no effect.
+
+The Pt_t command is used to create an instance of Pt_t.
+ Pt_t p1
+creates an instance named p1 with the initial value for p1.x set to 1
+and the initial value of p1.y set to 0.
+ Pt_t p2=(x=3 y=4)
+creates an instance with the specified initial values. The len function
+gives the distance of the point to the origin. Thus, p1.len will output
+1 and p2.len will output 5.
+
+ksh93t also introduces a more efficient command substitution mechanism.
+Instead of $(command), the new command substitution ${ command;}
+can be used. Unlike (and ) which are always special, the { and } are
+reserved words and require the space after { and a newline or ; before }.
+Unlike $(), the ${ ;} command substitution executes the command in
+the current shell context saving the need to save and restore
+changes, therefore also allowing side effects.
+
+When trying to expand an element of a type, if the element does not exist,
+ksh will look for a discipline function with that name and treat this as if
+it were the ${ ;} command substitution. Thus, ${p1.len} is equivalent to
+${ p1.len;} and within an arithmetic expression, p1.len will be expanded
+via the new command substitution method.
+
+The type of any variable can be obtained from the new prefix
+operator @. Thus, ${@p1} will output Pt_t.
+
+By default, each instance inherits all the discipline functions defined
+by the type definition other than create. However, each instance can define
+a function by the same name that will override this definition.
+However, only discipline functions with the same name as those defined
+by the type or the standard get, set, append, and unset disciplines
+can be defined by each instance.
+
+Each instance of the type Pt_t behaves like a compound variable except
+that only the variables defined by the type can be referenced or set.
+Thus, p2.x=9 is valid, but p2.z=9 is not. Unless a set discipline function
+does otherwise, the value of $p1 will be expanded to the form of a compound
+variable that can be used for reinput into ksh.
+
+If the variables var1 and var2 are of the same type, then the assignment
+ var2=var1
+will create a copy of the variable var1 into var2. This is equivalent to
+ eval var2="$var1"
+but is faster since the variable does not need to get expanded or reparsed.
+
+The type Pt_t can be referenced as if it were a variable using the name
+.sh.type.Pt_t. To change the default point location for subsequent
+instances of Pt_t, you can do
+ .sh.type.Pt_t=(x=5 y=12)
+so that
+ Pt_t p3
+ p3.len
+would be 13.
+
+Types can be defined for simple variables as well as for compound
+objects such as Pt_t. In this case, the variable named . inside
+the definition refers to the real value for the variable. For example,
+the type definition
+ typeset -T Time_t=(
+ integer .=0
+ _='%H:%M:%S'
+ get()
+ {
+ .sh.value=$(printf "%(${_._})T" "#$((_))" )
+ }
+ set()
+ {
+ .sh.value=$(printf "%(%#)T" "${.sh.value}")
+
+ }
+ )
+
+The sub-variable name _ is reserved for data used by discipline functions
+and will not be included with data written with the %B option to printf.
+In this case it is used to specify a date format.
+
+In this case
+ Time_t t1 t2=now
+will define t1 as the time at the beginning of the epoch and t2
+as the current time. Unlike the previous case, $t2 will output
+the current time in the date format specified by the value t2._.
+However, the value of ${t2.} will expand the instance to a form
+that can be used as input to the shell.
+
+Finally, types can be derived from an existing type. If the first
+element in a type definition is named _, then the new type
+consists of all the elements and discipline functions from the
+type of _ extended by elements and discipline functions defined
+by new type definition. For example,
+
+ typeset -T Pq_t=(
+ Pt_t _
+ float z=0.
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ }
+ )
+
+defines a new type Pq_t which is based on Pq_t and contains an additional
+field z and a different len discipline function. It is also possible
+to create a new type Pt_t based on the original Pt_t. In this case
+the original Pt_t is no longer accessible.
diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c
new file mode 100644
index 0000000..50261c6
--- /dev/null
+++ b/src/cmd/ksh93/bltins/alarm.c
@@ -0,0 +1,276 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * alarm [-r] [varname [+]when]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <error.h>
+#include <stak.h>
+#include "builtins.h"
+#include "FEATURE/time"
+
+#define R_FLAG 1
+#define L_FLAG 2
+
+struct tevent
+{
+ Namfun_t fun;
+ Namval_t *node;
+ Namval_t *action;
+ struct tevent *next;
+ long milli;
+ int flags;
+ void *timeout;
+ Shell_t *sh;
+};
+
+static const char ALARM[] = "alarm";
+
+static void trap_timeout(void*);
+
+/*
+ * insert timeout item on current given list in sorted order
+ */
+static void *time_add(struct tevent *item, void *list)
+{
+ register struct tevent *tp = (struct tevent*)list;
+ if(!tp || item->milli < tp->milli)
+ {
+ item->next = tp;
+ list = (void*)item;
+ }
+ else
+ {
+ while(tp->next && item->milli > tp->next->milli)
+ tp = tp->next;
+ item->next = tp->next;
+ tp->next = item;
+ }
+ tp = item;
+ tp->timeout = (void*)sh_timeradd(tp->milli,tp->flags&R_FLAG,trap_timeout,(void*)tp);
+ return(list);
+}
+
+/*
+ * delete timeout item from current given list, delete timer
+ */
+static void *time_delete(register struct tevent *item, void *list)
+{
+ register struct tevent *tp = (struct tevent*)list;
+ if(item==tp)
+ list = (void*)tp->next;
+ else
+ {
+ while(tp && tp->next != item)
+ tp = tp->next;
+ if(tp)
+ tp->next = item->next;
+ }
+ if(item->timeout)
+ timerdel((void*)item->timeout);
+ return(list);
+}
+
+static void print_alarms(void *list)
+{
+ register struct tevent *tp = (struct tevent*)list;
+ while(tp)
+ {
+ if(tp->timeout)
+ {
+ register char *name = nv_name(tp->node);
+ if(tp->flags&R_FLAG)
+ {
+ double d = tp->milli;
+ sfprintf(sfstdout,e_alrm1,name,d/1000.);
+ }
+ else
+ sfprintf(sfstdout,e_alrm2,name,nv_getnum(tp->node));
+ }
+ tp = tp->next;
+ }
+}
+
+static void trap_timeout(void* handle)
+{
+ register struct tevent *tp = (struct tevent*)handle;
+ tp->sh->trapnote |= SH_SIGALRM;
+ if(!(tp->flags&R_FLAG))
+ tp->timeout = 0;
+ tp->flags |= L_FLAG;
+ tp->sh->sigflag[SIGALRM] |= SH_SIGALRM;
+ if(sh_isstate(SH_TTYWAIT))
+ sh_timetraps(tp->sh);
+}
+
+void sh_timetraps(Shell_t *shp)
+{
+ register struct tevent *tp, *tpnext;
+ register struct tevent *tptop;
+ while(1)
+ {
+ shp->sigflag[SIGALRM] &= ~SH_SIGALRM;
+ tptop= (struct tevent*)shp->st.timetrap;
+ for(tp=tptop;tp;tp=tpnext)
+ {
+ tpnext = tp->next;
+ if(tp->flags&L_FLAG)
+ {
+ tp->flags &= ~L_FLAG;
+ if(tp->action)
+ sh_fun(tp->action,tp->node,(char**)0);
+ tp->flags &= ~L_FLAG;
+ if(!tp->flags)
+ {
+ nv_unset(tp->node);
+ nv_close(tp->node);
+ }
+ }
+ }
+ if(!(shp->sigflag[SIGALRM]&SH_SIGALRM))
+ break;
+ }
+}
+
+
+/*
+ * This trap function catches "alarm" actions only
+ */
+static char *setdisc(Namval_t *np, const char *event, Namval_t* action, Namfun_t
+ *fp)
+{
+ register struct tevent *tp = (struct tevent*)fp;
+ if(!event)
+ return(action?"":(char*)ALARM);
+ if(strcmp(event,ALARM)!=0)
+ {
+ /* try the next level */
+ return(nv_setdisc(np, event, action, fp));
+ }
+ if(action==np)
+ action = tp->action;
+ else
+ tp->action = action;
+ return(action?(char*)action:"");
+}
+
+/*
+ * catch assignments and set alarm traps
+ */
+static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ register struct tevent *tp = (struct tevent*)fp;
+ register double d;
+ Shell_t *shp = tp->sh;
+ if(val)
+ {
+ double now;
+#ifdef timeofday
+ struct timeval tmp;
+ timeofday(&tmp);
+ now = tmp.tv_sec + 1.e-6*tmp.tv_usec;
+#else
+ now = (double)time(NIL(time_t*));
+#endif /* timeofday */
+ nv_putv(np,val,flag,fp);
+ d = nv_getnum(np);
+ if(*val=='+')
+ {
+ double x = d + now;
+ nv_putv(np,(char*)&x,NV_INTEGER|NV_DOUBLE,fp);
+ }
+ else
+ d -= now;
+ tp->milli = 1000*(d+.0005);
+ if(tp->timeout)
+ shp->st.timetrap = time_delete(tp,shp->st.timetrap);
+ if(tp->milli > 0)
+ shp->st.timetrap = time_add(tp,shp->st.timetrap);
+ }
+ else
+ {
+ tp = (struct tevent*)nv_stack(np, (Namfun_t*)0);
+ shp->st.timetrap = time_delete(tp,shp->st.timetrap);
+ if(tp->action)
+ nv_close(tp->action);
+ nv_unset(np);
+ free((void*)fp);
+ }
+}
+
+static const Namdisc_t alarmdisc =
+{
+ sizeof(struct tevent),
+ putval,
+ 0,
+ 0,
+ setdisc,
+};
+
+int b_alarm(int argc,char *argv[],Shbltin_t *context)
+{
+ register int n,rflag=0;
+ register Namval_t *np;
+ register struct tevent *tp;
+ register Shell_t *shp = context->shp;
+ while (n = optget(argv, sh_optalarm)) switch (n)
+ {
+ case 'r':
+ rflag = R_FLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argc -= opt_info.index;
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ if(argc==0)
+ {
+ print_alarms(shp->st.timetrap);
+ return(0);
+ }
+ if(argc!=2)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ np = nv_open(argv[0],shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOASSIGN);
+ if(!nv_isnull(np))
+ nv_unset(np);
+ nv_setattr(np, NV_DOUBLE);
+ if(!(tp = newof(NIL(struct tevent*),struct tevent,1,0)))
+ errormsg(SH_DICT,ERROR_exit(1),e_nospace);
+ tp->fun.disc = &alarmdisc;
+ tp->flags = rflag;
+ tp->node = np;
+ tp->sh = shp;
+ nv_stack(np,(Namfun_t*)tp);
+ nv_putval(np, argv[1], 0);
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/cd_pwd.c b/src/cmd/ksh93/bltins/cd_pwd.c
new file mode 100644
index 0000000..fb0dcda
--- /dev/null
+++ b/src/cmd/ksh93/bltins/cd_pwd.c
@@ -0,0 +1,250 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * cd [-LP] [dirname]
+ * cd [-LP] [old] [new]
+ * pwd [-LP]
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include "defs.h"
+#include <stak.h>
+#include <error.h>
+#include "variables.h"
+#include "path.h"
+#include "name.h"
+#include "builtins.h"
+#include <ls.h>
+
+/*
+ * Invalidate path name bindings to relative paths
+ */
+static void rehash(register Namval_t *np,void *data)
+{
+ Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
+ NOT_USED(data);
+ if(pp && *pp->name!='/')
+ _nv_unset(np,0);
+}
+
+int b_cd(int argc, char *argv[],Shbltin_t *context)
+{
+ register char *dir;
+ Pathcomp_t *cdpath = 0;
+ register const char *dp;
+ register Shell_t *shp = context->shp;
+ int saverrno=0;
+ int rval,flag=0;
+ char *oldpwd;
+ Namval_t *opwdnod, *pwdnod;
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
+ while((rval = optget(argv,sh_optcd))) switch(rval)
+ {
+ case 'L':
+ flag = 0;
+ break;
+ case 'P':
+ flag = 1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ dir = argv[0];
+ if(error_info.errors>0 || argc >2)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ oldpwd = (char*)shp->pwd;
+ opwdnod = (shp->subshell?sh_assignok(OLDPWDNOD,1):OLDPWDNOD);
+ pwdnod = (shp->subshell?sh_assignok(PWDNOD,1):PWDNOD);
+ if(argc==2)
+ dir = sh_substitute(oldpwd,dir,argv[1]);
+ else if(!dir)
+ dir = nv_getval(HOME);
+ else if(*dir == '-' && dir[1]==0)
+ dir = nv_getval(opwdnod);
+ if(!dir || *dir==0)
+ errormsg(SH_DICT,ERROR_exit(1),argc==2?e_subst+4:e_direct);
+#if _WINIX
+ if(*dir != '/' && (dir[1]!=':'))
+#else
+ if(*dir != '/')
+#endif /* _WINIX */
+ {
+ if(!(cdpath = (Pathcomp_t*)shp->cdpathlist) && (dp=sh_scoped(shp,CDPNOD)->nvalue.cp))
+ {
+ if(cdpath=path_addpath(shp,(Pathcomp_t*)0,dp,PATH_CDPATH))
+ {
+ shp->cdpathlist = (void*)cdpath;
+ cdpath->shp = shp;
+ }
+ }
+ if(!oldpwd)
+ oldpwd = path_pwd(shp,1);
+ }
+ if(*dir=='.')
+ {
+ /* test for pathname . ./ .. or ../ */
+ if(*(dp=dir+1) == '.')
+ dp++;
+ if(*dp==0 || *dp=='/')
+ cdpath = 0;
+ }
+ rval = -1;
+ do
+ {
+ dp = cdpath?cdpath->name:"";
+ cdpath = path_nextcomp(shp,cdpath,dir,0);
+#if _WINIX
+ if(*stakptr(PATH_OFFSET+1)==':' && isalpha(*stakptr(PATH_OFFSET)))
+ {
+ *stakptr(PATH_OFFSET+1) = *stakptr(PATH_OFFSET);
+ *stakptr(PATH_OFFSET)='/';
+ }
+#endif /* _WINIX */
+ if(*stakptr(PATH_OFFSET)!='/')
+
+ {
+ char *last=(char*)stakfreeze(1);
+ stakseek(PATH_OFFSET);
+ stakputs(oldpwd);
+ /* don't add '/' of oldpwd is / itself */
+ if(*oldpwd!='/' || oldpwd[1])
+ stakputc('/');
+ stakputs(last+PATH_OFFSET);
+ stakputc(0);
+ }
+ if(!flag)
+ {
+ register char *cp;
+ stakseek(PATH_MAX+PATH_OFFSET);
+#if SHOPT_FS_3D
+ if(!(cp = pathcanon(stakptr(PATH_OFFSET),PATH_DOTDOT)))
+ continue;
+ /* eliminate trailing '/' */
+ while(*--cp == '/' && cp>stakptr(PATH_OFFSET))
+ *cp = 0;
+#else
+ if(*(cp=stakptr(PATH_OFFSET))=='/')
+ if(!pathcanon(cp,PATH_DOTDOT))
+ continue;
+#endif /* SHOPT_FS_3D */
+ }
+ if((rval=chdir(path_relative(shp,stakptr(PATH_OFFSET)))) >= 0)
+ goto success;
+ if(errno!=ENOENT && saverrno==0)
+ saverrno=errno;
+ }
+ while(cdpath);
+ if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/')
+ rval = chdir(dir);
+ /* use absolute chdir() if relative chdir() fails */
+ if(rval<0)
+ {
+ if(saverrno)
+ errno = saverrno;
+ errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
+ }
+success:
+ if(dir == nv_getval(opwdnod) || argc==2)
+ dp = dir; /* print out directory for cd - */
+ if(flag)
+ {
+ dir = stakptr(PATH_OFFSET);
+ if (!(dir=pathcanon(dir,PATH_PHYSICAL)))
+ {
+ dir = stakptr(PATH_OFFSET);
+ errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
+ }
+ stakseek(dir-stakptr(0));
+ }
+ dir = (char*)stakfreeze(1)+PATH_OFFSET;
+ if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/'))
+ sfputr(sfstdout,dir,'\n');
+ if(*dir != '/')
+ return(0);
+ nv_putval(opwdnod,oldpwd,NV_RDONLY);
+ if(oldpwd)
+ free(oldpwd);
+ flag = strlen(dir);
+ /* delete trailing '/' */
+ while(--flag>0 && dir[flag]=='/')
+ dir[flag] = 0;
+ nv_putval(pwdnod,dir,NV_RDONLY);
+ nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
+ shp->pwd = pwdnod->nvalue.cp;
+ nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
+ path_newdir(shp,shp->pathlist);
+ path_newdir(shp,shp->cdpathlist);
+ return(0);
+}
+
+int b_pwd(int argc, char *argv[],Shbltin_t *context)
+{
+ register int n, flag = 0;
+ register char *cp;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while((n = optget(argv,sh_optpwd))) switch(n)
+ {
+ case 'L':
+ flag = 0;
+ break;
+ case 'P':
+ flag = 1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*(cp = path_pwd(shp,0)) != '/')
+ errormsg(SH_DICT,ERROR_system(1), e_pwd);
+ if(flag)
+ {
+#if SHOPT_FS_3D
+ if(shp->gd->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
+ {
+ cp = (char*)stakseek(++flag+PATH_MAX);
+ mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0);
+ }
+ else
+#endif /* SHOPT_FS_3D */
+ cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp);
+ pathcanon(cp,PATH_PHYSICAL);
+ }
+ sfputr(sfstdout,cp,'\n');
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/cflow.c b/src/cmd/ksh93/bltins/cflow.c
new file mode 100644
index 0000000..c78659f
--- /dev/null
+++ b/src/cmd/ksh93/bltins/cflow.c
@@ -0,0 +1,117 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * break [n]
+ * continue [n]
+ * return [n]
+ * exit [n]
+ *
+ * David Korn
+ * AT&T Labs
+ * dgk@research.att.com
+ *
+ */
+
+#include "defs.h"
+#include <ast.h>
+#include <error.h>
+#include "shnodes.h"
+#include "builtins.h"
+
+/*
+ * return and exit
+ */
+#if 0
+ /* for the dictionary generator */
+ int b_exit(int n, register char *argv[],Shbltin_t *context){}
+#endif
+int b_return(register int n, register char *argv[],Shbltin_t *context)
+{
+ register char *arg;
+ register Shell_t *shp = context->shp;
+ struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ const char *options = (**argv=='r'?sh_optreturn:sh_optexit);
+ while((n = optget(argv,options))) switch(n)
+ {
+ case ':':
+ if(!strmatch(argv[opt_info.index],"[+-]+([0-9])"))
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ goto done;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+done:
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ pp->mode = (**argv=='e'?SH_JMPEXIT:SH_JMPFUN);
+ argv += opt_info.index;
+ n = (((arg= *argv)?(int)strtol(arg, (char**)0, 10)&SH_EXITMASK:shp->oldexit));
+ /* return outside of function, dotscript and profile is exit */
+ if(shp->fn_depth==0 && shp->dot_depth==0 && !sh_isstate(SH_PROFILE))
+ pp->mode = SH_JMPEXIT;
+ sh_exit(shp->savexit=n);
+ return(1);
+}
+
+
+/*
+ * break and continue
+ */
+#if 0
+ /* for the dictionary generator */
+ int b_continue(int n, register char *argv[],Shbltin_t *context){}
+#endif
+int b_break(register int n, register char *argv[],Shbltin_t *context)
+{
+ char *arg;
+ register int cont= **argv=='c';
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,cont?sh_optcont:sh_optbreak))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ n=1;
+ if(arg= *argv)
+ {
+ n = strtol(arg,&arg,10);
+ if(n<=0 || *arg)
+ errormsg(SH_DICT,ERROR_exit(1),e_nolabels,*argv);
+ }
+ if(shp->st.loopcnt)
+ {
+ shp->st.execbrk = shp->st.breakcnt = n;
+ if(shp->st.breakcnt > shp->st.loopcnt)
+ shp->st.breakcnt = shp->st.loopcnt;
+ if(cont)
+ shp->st.breakcnt = -shp->st.breakcnt;
+ }
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/enum.c b/src/cmd/ksh93/bltins/enum.c
new file mode 100644
index 0000000..5cc749c
--- /dev/null
+++ b/src/cmd/ksh93/bltins/enum.c
@@ -0,0 +1,284 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include <shell.h>
+
+static const char enum_usage[] =
+"[-?@(#)$Id: enum (AT&T Research) 2008-01-08 $\n]"
+USAGE_LICENSE
+"[+NAME?enum - create an enumeration type]"
+"[+DESCRIPTION?\benum\b is a declaration command that creates an enumeration "
+ "type \atypename\a that can only store any one of the values in the indexed "
+ "array variable \atypename\a.]"
+"[+?If the list of \avalue\as is omitted, then \atypename\a must name an "
+ "indexed array variable with at least two elements.]"
+"[i:ignorecase?The values are case insensitive.]"
+"\n"
+"\n\atypename\a[\b=(\b \avalue\a ... \b)\b]\n"
+"\n"
+"[+EXIT STATUS]"
+ "{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+ "}"
+"[+SEE ALSO?\bksh\b(1), \btypeset\b(1).]"
+;
+
+static const char enum_type[] =
+"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-01-08 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - create an instance of type \b\f?\f\b]"
+"[+DESCRIPTION?\b\f?\f\b creates a variable for each \aname\a with "
+ "enumeration type \b\f?\f\b where \b\f?\f\b is a type that has been "
+ "created with the \benum\b(1) command.]"
+"[+?The variable can have one of the following values\fvalues\f. "
+ "The the values are \fcase\fcase sensitive.]"
+"[+?If \b=\b\avalue\a is omitted, the default is \fdefault\f.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "variables of this type are written to standard output.]"
+"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[r?Enables readonly. Once enabled, the value cannot be changed or unset.]"
+"[a?index array. Each \aname\a will converted to an index "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become index \b0\b.]"
+"[A?Associative array. Each \aname\a will converted to an associate "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become subscript \b0\b.]"
+"[h]:[string?Used within a type definition to provide a help string "
+ "for variable \aname\a. Otherwise, it is ignored.]"
+"[S?Used with a type definition to indicate that the variable is shared by "
+ "each instance of the type. When used inside a function defined "
+ "with the \bfunction\b reserved word, the specified variables "
+ "will have function static scope. Otherwise, the variable is "
+ "unset prior to processing the assignment list.]"
+#if 0
+"[p?Causes the output to be in a form of \b\f?\f\b commands that can be "
+ "used as input to the shell to recreate the current type of "
+ "these variables.]"
+#endif
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\benum\b(1), \btypeset\b(1)]"
+;
+
+struct Enum
+{
+ Namfun_t hdr;
+ short nelem;
+ short iflag;
+ const char *values[1];
+};
+
+static int enuminfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
+{
+ Namval_t *np;
+ struct Enum *ep;
+ int n=0;
+ const char *v;
+ np = *(Namval_t**)(fp+1);
+ ep = (struct Enum*)np->nvfun;
+ if(strcmp(str,"default")==0)
+#if 0
+ sfprintf(out,"\b%s\b%c",ep->values[0],0);
+#else
+ sfprintf(out,"\b%s\b",ep->values[0]);
+#endif
+ else if(strcmp(str,"case")==0)
+ {
+ if(ep->iflag)
+ sfprintf(out,"not ");
+ }
+ else while(v=ep->values[n++])
+ {
+ sfprintf(out,", \b%s\b",v);
+ }
+ return(0);
+}
+
+static Namfun_t *clone_enum(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ struct Enum *ep, *pp=(struct Enum*)fp;
+ ep = newof(0,struct Enum,1,pp->nelem*sizeof(char*));
+ memcpy((void*)ep,(void*)pp,sizeof(struct Enum)+pp->nelem*sizeof(char*));
+ return(&ep->hdr);
+}
+
+static void put_enum(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct Enum *ep = (struct Enum*)fp;
+ register const char *v;
+ unsigned short i=0, n;
+ if(!val)
+ {
+ nv_putv(np, val, flags,fp);
+ nv_disc(np,&ep->hdr,NV_POP);
+ if(!ep->hdr.nofree)
+ free((void*)ep);
+ return;
+ }
+ if(flags&NV_INTEGER)
+ {
+ nv_putv(np,val,flags,fp);
+ return;
+ }
+ while(v=ep->values[i])
+ {
+ if(ep->iflag)
+ n = strcasecmp(v,val);
+ else
+ n = strcmp(v,val);
+ if(n==0)
+ {
+ nv_putv(np, (char*)&i, NV_UINT16, fp);
+ return;
+ }
+ i++;
+ }
+ if(nv_isattr(np,NV_NOFREE))
+ error(ERROR_exit(1), "%s: invalid value %s",nv_name(np),val);
+}
+
+static char* get_enum(register Namval_t* np, Namfun_t *fp)
+{
+ static char buff[6];
+ struct Enum *ep = (struct Enum*)fp;
+ long n = nv_getn(np,fp);
+ if(n < ep->nelem)
+ return((char*)ep->values[n]);
+ sfsprintf(buff,sizeof(buff),"%u%c",n,0);
+ return(buff);
+}
+
+static Sfdouble_t get_nenum(register Namval_t* np, Namfun_t *fp)
+{
+ return(nv_getn(np,fp));
+}
+
+const Namdisc_t ENUM_disc = { 0, put_enum, get_enum, get_nenum, 0,0,clone_enum };
+
+#ifdef STANDALONE
+static int enum_create(int argc, char** argv, Shbltin_t *context)
+#else
+int b_enum(int argc, char** argv, Shbltin_t *context)
+#endif
+{
+ int sz,i,n,iflag = 0;
+ Namval_t *np, *tp;
+ Namarr_t *ap;
+ char *cp,*sp;
+ struct Enum *ep;
+ Shell_t *shp = context->shp;
+ struct {
+ Optdisc_t opt;
+ Namval_t *np;
+ } optdisc;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ for (;;)
+ {
+ switch (optget(argv, enum_usage))
+ {
+ case 'i':
+ iflag = 'i';
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !*argv || *(argv + 1))
+ {
+ error(ERROR_USAGE|2, "%s", optusage(NiL));
+ return 1;
+ }
+ while(cp = *argv++)
+ {
+ if(!(np = nv_open(cp, (void*)0, NV_VARNAME|NV_NOADD)) || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem&(((1L<<ARRAY_BITS)-1))) < 2)
+ error(ERROR_exit(1), "%s must name an array containing at least two elements",cp);
+ n = staktell();
+ sfprintf(stkstd,"%s.%s%c",NV_CLASS,np->nvname,0);
+ tp = nv_open(stakptr(n), shp->var_tree, NV_VARNAME);
+ stakseek(n);
+ n = sz;
+ i = 0;
+ nv_onattr(tp, NV_UINT16);
+ nv_putval(tp, (char*)&i, NV_INTEGER);
+ nv_putsub(np, (char*)0, ARRAY_SCAN);
+ do
+ {
+ sz += strlen(nv_getval(np));
+ }
+ while(nv_nextsub(np));
+ sz += n*sizeof(char*);
+ if(!(ep = newof(0,struct Enum,1,sz)))
+ error(ERROR_system(1), "out of space");
+ ep->iflag = iflag;
+ ep->nelem = n;
+ cp = (char*)&ep->values[n+1];
+ nv_putsub(np, (char*)0, ARRAY_SCAN);
+ ep->values[n] = 0;
+ i = 0;
+ do
+ {
+ ep->values[i++] = cp;
+ sp = nv_getval(np);
+ n = strlen(sp);
+ memcpy(cp,sp,n+1);
+ cp += n+1;
+ }
+ while(nv_nextsub(np));
+ ep->hdr.dsize = sizeof(struct Enum)+sz;
+ ep->hdr.disc = &ENUM_disc;
+ ep->hdr.type = tp;
+ nv_onattr(tp, NV_RDONLY);
+ nv_disc(tp, &ep->hdr,NV_FIRST);
+ memset(&optdisc,0,sizeof(optdisc));
+ optdisc.opt.infof = enuminfo;
+ optdisc.np = tp;
+ nv_addtype(tp, enum_type, &optdisc.opt, sizeof(optdisc));
+ }
+ return error_info.errors != 0;
+}
+
+#ifdef STANDALONE
+void lib_init(int flag, void* context)
+{
+ Shell_t *shp = ((Shbltin_t*)context)->shp;
+ Namval_t *mp,*bp;
+ if(flag)
+ return;
+ bp = sh_addbuiltin("Enum", enum_create, (void*)0);
+ mp = nv_search("typeset",shp->bltin_tree,0);
+ nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
+}
+#endif
diff --git a/src/cmd/ksh93/bltins/getopts.c b/src/cmd/ksh93/bltins/getopts.c
new file mode 100644
index 0000000..8b92b73
--- /dev/null
+++ b/src/cmd/ksh93/bltins/getopts.c
@@ -0,0 +1,199 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * getopts optstring name [arg...]
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include "defs.h"
+#include "variables.h"
+#include <error.h>
+#include <nval.h>
+#include "builtins.h"
+
+static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+ Shell_t *shp = *(Shell_t**)(dp+1);
+ Stk_t *stkp = shp->stk;
+ if(nv_search(s,shp->fun_tree,0))
+ {
+ int savtop = stktell(stkp);
+ char *savptr = stkfreeze(stkp,0);
+ sfputc(stkp,'$');
+ sfputc(stkp,'(');
+ sfputr(stkp,s,')');
+ sfputr(sp,sh_mactry(shp,stkfreeze(stkp,1)),-1);
+ stkset(stkp,savptr,savtop);
+ }
+ return(1);
+}
+
+int b_getopts(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *options=error_info.context->id;
+ register Namval_t *np;
+ register int flag, mode;
+ register Shell_t *shp = context->shp;
+ char value[2], key[2];
+ int jmpval,extended;
+ volatile int r= -1;
+ struct checkpt buff, *pp;
+ struct {
+ Optdisc_t hdr;
+ Shell_t *sh;
+ } disc;
+ memset(&disc, 0, sizeof(disc));
+ disc.hdr.version = OPT_VERSION;
+ disc.hdr.infof = infof;
+ disc.sh = shp;
+ value[1] = 0;
+ key[1] = 0;
+ while((flag = optget(argv,sh_optgetopts))) switch(flag)
+ {
+ case 'a':
+ options = opt_info.arg;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc<2)
+ errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
+ error_info.context->flags |= ERROR_SILENT;
+ error_info.id = options;
+ options = argv[0];
+ np = nv_open(argv[1],shp->var_tree,NV_NOASSIGN|NV_VARNAME);
+ if(argc>2)
+ {
+ argv +=1;
+ argc -=1;
+ }
+ else
+ {
+ argv = shp->st.dolv;
+ argc = shp->st.dolc;
+ }
+ opt_info.index = shp->st.optindex;
+ opt_info.offset = shp->st.optchar;
+ if(mode= (*options==':'))
+ options++;
+ extended = *options=='\n' && *(options+1)=='[' || *options=='[' && *(options+1)=='-';
+ sh_pushcontext(shp,&buff,1);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval)
+ {
+ sh_popcontext(shp,&buff);
+ shp->st.opterror = 1;
+ if(r==0)
+ return(2);
+ pp = (struct checkpt*)shp->jmplist;
+ pp->mode = SH_JMPERREXIT;
+ sh_exit(2);
+ }
+ opt_info.disc = &disc.hdr;
+ switch(opt_info.index>=0 && opt_info.index<=argc?(opt_info.num= LONG_MIN,flag=optget(argv,options)):0)
+ {
+ case '?':
+ if(mode==0)
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ opt_info.option[1] = '?';
+ /* FALL THRU */
+ case ':':
+ key[0] = opt_info.option[1];
+ if(strmatch(opt_info.arg,"*unknown*"))
+ flag = '?';
+ if(mode)
+ opt_info.arg = key;
+ else
+ {
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ opt_info.arg = 0;
+ flag = '?';
+ }
+ *(options = value) = flag;
+ shp->st.opterror = 1;
+ if (opt_info.offset != 0 && !argv[opt_info.index][opt_info.offset])
+ {
+ opt_info.offset = 0;
+ opt_info.index++;
+ }
+ break;
+ case 0:
+ if(shp->st.opterror)
+ {
+ char *com[2];
+ com[0] = "-?";
+ com[1] = 0;
+ flag = opt_info.index;
+ opt_info.index = 0;
+ optget(com,options);
+ opt_info.index = flag;
+ if(!mode && strchr(options,' '))
+ errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
+ }
+ opt_info.arg = 0;
+ options = value;
+ *options = '?';
+ r=1;
+ opt_info.offset = 0;
+ break;
+ default:
+ options = opt_info.option + (*opt_info.option!='+');
+ }
+ if(r<0)
+ r = 0;
+ error_info.context->flags &= ~ERROR_SILENT;
+ shp->st.optindex = opt_info.index;
+ shp->st.optchar = opt_info.offset;
+ nv_putval(np, options, 0);
+ nv_close(np);
+ np = nv_open(nv_name(OPTARGNOD),shp->var_tree,NV_NOSCOPE);
+ if(opt_info.num == LONG_MIN)
+ nv_putval(np, opt_info.arg, NV_RDONLY);
+ else if (opt_info.arg && opt_info.num > 0 && isalpha((char)opt_info.num) && !isdigit(opt_info.arg[0]) && opt_info.arg[0] != '-' && opt_info.arg[0] != '+')
+ {
+ key[0] = (char)opt_info.num;
+ key[1] = 0;
+ nv_putval(np, key, NV_RDONLY);
+ }
+ else if(extended)
+ {
+ Sfdouble_t d;
+ d = opt_info.number;
+ nv_putval(np, (char*)&d, NV_LDOUBLE|NV_RDONLY);
+ }
+ else
+ nv_putval(np, opt_info.arg, NV_RDONLY);
+ nv_close(np);
+ sh_popcontext(shp,&buff);
+ opt_info.disc = 0;
+ return(r);
+}
+
diff --git a/src/cmd/ksh93/bltins/hist.c b/src/cmd/ksh93/bltins/hist.c
new file mode 100644
index 0000000..1c2bc72
--- /dev/null
+++ b/src/cmd/ksh93/bltins/hist.c
@@ -0,0 +1,312 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include "defs.h"
+#include <stak.h>
+#include <ls.h>
+#include <error.h>
+#include "variables.h"
+#include "io.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#if SHOPT_HISTEXPAND
+# include "edit.h"
+#endif
+
+#define HIST_RECURSE 5
+
+static void hist_subst(const char*, int fd, char*);
+
+#if 0
+ /* for the benefit of the dictionary generator */
+ int b_fc(int argc,char *argv[], Shbltin_t *context){}
+#endif
+int b_hist(int argc,char *argv[], Shbltin_t *context)
+{
+ register History_t *hp;
+ register char *arg;
+ register int flag,fdo;
+ register Shell_t *shp = context->shp;
+ Sfio_t *outfile;
+ char *fname;
+ int range[2], incr, index2, indx= -1;
+ char *edit = 0; /* name of editor */
+ char *replace = 0; /* replace old=new */
+ int lflag = 0, nflag = 0, rflag = 0;
+#if SHOPT_HISTEXPAND
+ int pflag = 0;
+#endif
+ Histloc_t location;
+ NOT_USED(argc);
+ if(!sh_histinit((void*)shp))
+ errormsg(SH_DICT,ERROR_system(1),e_histopen);
+ hp = shp->gd->hist_ptr;
+ while((flag = optget(argv,sh_opthist))) switch(flag)
+ {
+ case 'e':
+ edit = opt_info.arg;
+ break;
+ case 'n':
+ nflag++;
+ break;
+ case 'l':
+ lflag++;
+ break;
+ case 'r':
+ rflag++;
+ break;
+ case 's':
+ edit = "-";
+ break;
+#if SHOPT_HISTEXPAND
+ case 'p':
+ pflag++;
+ break;
+#endif
+ case 'N':
+ if(indx<=0)
+ {
+ if((flag = hist_max(hp) - opt_info.num-1) < 0)
+ flag = 1;
+ range[++indx] = flag;
+ break;
+ }
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += (opt_info.index-1);
+#if SHOPT_HISTEXPAND
+ if(pflag)
+ {
+ hist_cancel(hp);
+ pflag = 0;
+ while(arg=argv[1])
+ {
+ flag = hist_expand(arg,&replace);
+ if(!(flag & HIST_ERROR))
+ sfputr(sfstdout, replace, '\n');
+ else
+ pflag = 1;
+ if(replace)
+ free(replace);
+ argv++;
+ }
+ return pflag;
+ }
+#endif
+ flag = indx;
+ while(flag<1 && (arg=argv[1]))
+ {
+ /* look for old=new argument */
+ if(!replace && strchr(arg+1,'='))
+ {
+ replace = arg;
+ argv++;
+ continue;
+ }
+ else if(isdigit(*arg) || *arg == '-')
+ {
+ /* see if completely numeric */
+ do arg++;
+ while(isdigit(*arg));
+ if(*arg==0)
+ {
+ arg = argv[1];
+ range[++flag] = (int)strtol(arg, (char**)0, 10);
+ if(*arg == '-')
+ range[flag] += (hist_max(hp)-1);
+ argv++;
+ continue;
+ }
+ }
+ /* search for last line starting with string */
+ location = hist_find(hp,argv[1],hist_max(hp)-1,0,-1);
+ if((range[++flag] = location.hist_command) < 0)
+ errormsg(SH_DICT,ERROR_exit(1),e_found,argv[1]);
+ argv++;
+ }
+ if(flag <0)
+ {
+ /* set default starting range */
+ if(lflag)
+ {
+ flag = hist_max(hp)-16;
+ if(flag<1)
+ flag = 1;
+ }
+ else
+ flag = hist_max(hp)-2;
+ range[0] = flag;
+ flag = 0;
+ }
+ index2 = hist_min(hp);
+ if(range[0]<index2)
+ range[0] = index2;
+ if(flag==0)
+ /* set default termination range */
+ range[1] = ((lflag && !edit)?hist_max(hp)-1:range[0]);
+ if(range[1]>=(flag=(hist_max(hp) - !lflag)))
+ range[1] = flag;
+ /* check for valid ranges */
+ if(range[1]<index2 || range[0]>=flag)
+ errormsg(SH_DICT,ERROR_exit(1),e_badrange,range[0],range[1]);
+ if(edit && *edit=='-' && range[0]!=range[1])
+ errormsg(SH_DICT,ERROR_exit(1),e_eneedsarg);
+ /* now list commands from range[rflag] to range[1-rflag] */
+ incr = 1;
+ flag = rflag>0;
+ if(range[1-flag] < range[flag])
+ incr = -1;
+ if(lflag)
+ {
+ outfile = sfstdout;
+ arg = "\n\t";
+ }
+ else
+ {
+ if(!(fname=pathtmp(NIL(char*),0,0,NIL(int*))))
+ errormsg(SH_DICT,ERROR_exit(1),e_create,"");
+ if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_create,fname);
+ outfile= sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fdo,SF_WRITE);
+ arg = "\n";
+ nflag++;
+ }
+ while(1)
+ {
+ if(nflag==0)
+ sfprintf(outfile,"%d\t",range[flag]);
+ else if(lflag)
+ sfputc(outfile,'\t');
+ hist_list(shp->gd->hist_ptr,outfile,hist_tell(shp->gd->hist_ptr,range[flag]),0,arg);
+ if(lflag)
+ sh_sigcheck(shp);
+ if(range[flag] == range[1-flag])
+ break;
+ range[flag] += incr;
+ }
+ if(lflag)
+ return(0);
+ sfclose(outfile);
+ hist_eof(hp);
+ arg = edit;
+ if(!arg && !(arg=nv_getval(sh_scoped(shp,HISTEDIT))) && !(arg=nv_getval(sh_scoped(shp,FCEDNOD))))
+ {
+ arg = (char*)e_defedit;
+ if(*arg!='/')
+ errormsg(SH_DICT,ERROR_exit(1),"ed not found set FCEDIT");
+ }
+#ifdef apollo
+ /*
+ * Code to support the FC using the pad editor.
+ * Exampled of how to use: HISTEDIT=pad
+ */
+ if (strcmp (arg, "pad") == 0)
+ {
+ extern int pad_create(char*);
+ sh_close(fdo);
+ fdo = pad_create(fname);
+ pad_wait(fdo);
+ unlink(fname);
+ strcat(fname, ".bak");
+ unlink(fname);
+ lseek(fdo,(off_t)0,SEEK_SET);
+ }
+ else
+ {
+#endif /* apollo */
+ if(*arg != '-')
+ {
+ char *com[3];
+ com[0] = arg;
+ com[1] = fname;
+ com[2] = 0;
+ error_info.errors = sh_eval(sh_sfeval(com),0);
+ }
+ fdo = sh_chkopen(fname);
+ unlink(fname);
+ free((void*)fname);
+#ifdef apollo
+ }
+#endif /* apollo */
+ /* don't history fc itself unless forked */
+ error_info.flags |= ERROR_SILENT;
+ if(!sh_isstate(SH_FORKED))
+ hist_cancel(hp);
+ sh_onstate(SH_HISTORY);
+ sh_onstate(SH_VERBOSE); /* echo lines as read */
+ if(replace)
+ hist_subst(error_info.id,fdo,replace);
+ else if(error_info.errors == 0)
+ {
+ char buff[IOBSIZE+1];
+ Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
+ /* read in and run the command */
+ if(shp->hist_depth++ > HIST_RECURSE)
+ errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
+ sh_eval(iop,1);
+ shp->hist_depth--;
+ }
+ else
+ {
+ sh_close(fdo);
+ if(!sh_isoption(SH_VERBOSE))
+ sh_offstate(SH_VERBOSE);
+ sh_offstate(SH_HISTORY);
+ }
+ return(shp->exitval);
+}
+
+
+/*
+ * given a file containing a command and a string of the form old=new,
+ * execute the command with the string old replaced by new
+ */
+
+static void hist_subst(const char *command,int fd,char *replace)
+{
+ register char *newp=replace;
+ register char *sp;
+ register int c;
+ off_t size;
+ char *string;
+ while(*++newp != '='); /* skip to '=' */
+ if((size = lseek(fd,(off_t)0,SEEK_END)) < 0)
+ return;
+ lseek(fd,(off_t)0,SEEK_SET);
+ c = (int)size;
+ string = stakalloc(c+1);
+ if(read(fd,string,c)!=c)
+ return;
+ string[c] = 0;
+ *newp++ = 0;
+ if((sp=sh_substitute(string,replace,newp))==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_subst,command);
+ *(newp-1) = '=';
+ sh_eval(sfopen(NIL(Sfio_t*),sp,"s"),1);
+}
+
diff --git a/src/cmd/ksh93/bltins/misc.c b/src/cmd/ksh93/bltins/misc.c
new file mode 100644
index 0000000..d810a05
--- /dev/null
+++ b/src/cmd/ksh93/bltins/misc.c
@@ -0,0 +1,590 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * exec [arg...]
+ * eval [arg...]
+ * jobs [-lnp] [job...]
+ * login [arg...]
+ * let expr...
+ * . file [arg...]
+ * :, true, false
+ * vpath [top] [base]
+ * vmap [top] [base]
+ * wait [job...]
+ * shift [n]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "variables.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#include "jobs.h"
+
+#define DOTMAX MAXDEPTH /* maximum level of . nesting */
+
+static void noexport(Namval_t*,void*);
+
+struct login
+{
+ Shell_t *sh;
+ int clear;
+ char *arg0;
+};
+
+int b_exec(int argc,char *argv[], Shbltin_t *context)
+{
+ struct login logdata;
+ register int n;
+ logdata.clear = 0;
+ logdata.arg0 = 0;
+ logdata.sh = context->shp;
+ logdata.sh->st.ioset = 0;
+ while (n = optget(argv, sh_optexec)) switch (n)
+ {
+ case 'a':
+ logdata.arg0 = opt_info.arg;
+ argc = 0;
+ break;
+ case 'c':
+ logdata.clear=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*argv)
+ B_login(0,argv,(Shbltin_t*)&logdata);
+ return(0);
+}
+
+static void noexport(register Namval_t* np, void *data)
+{
+ NOT_USED(data);
+ nv_offattr(np,NV_EXPORT);
+}
+
+int B_login(int argc,char *argv[],Shbltin_t *context)
+{
+ struct checkpt *pp;
+ register struct login *logp=0;
+ register Shell_t *shp;
+ const char *pname;
+ if(argc)
+ shp = context->shp;
+ else
+ {
+ logp = (struct login*)context;
+ shp = logp->sh;
+ }
+ pp = (struct checkpt*)shp->jmplist;
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,argv[0]);
+ else
+ {
+ register struct argnod *arg=shp->envlist;
+ register Namval_t* np;
+ register char *cp;
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ if(logp && logp->clear)
+ {
+#ifdef _ENV_H
+ env_close(shp->env);
+ shp->env = env_open((char**)0,3);
+#else
+ nv_scan(shp->var_tree,noexport,0,NV_EXPORT,NV_EXPORT);
+#endif
+ }
+ while(arg)
+ {
+ if((cp=strchr(arg->argval,'=')) &&
+ (*cp=0,np=nv_search(arg->argval,shp->var_tree,0)))
+ {
+ nv_onattr(np,NV_EXPORT);
+ sh_envput(shp->env,np);
+ }
+ if(cp)
+ *cp = '=';
+ arg=arg->argnxt.ap;
+ }
+ pname = argv[0];
+ if(logp && logp->arg0)
+ argv[0] = logp->arg0;
+#ifdef JOBS
+ if(job_close(shp) < 0)
+ return(1);
+#endif /* JOBS */
+ /* force bad exec to terminate shell */
+ pp->mode = SH_JMPEXIT;
+ sh_sigreset(2);
+ sh_freeup(shp);
+ path_exec(shp,pname,argv,NIL(struct argnod*));
+ sh_done(shp,0);
+ }
+ return(1);
+}
+
+int b_let(int argc,char *argv[],Shbltin_t *context)
+{
+ register int r;
+ register char *arg;
+ Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (r = optget(argv,sh_optlet)) switch (r)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors || !*argv)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ while(arg= *argv++)
+ r = !sh_arith(shp,arg);
+ return(r);
+}
+
+int b_eval(int argc,char *argv[], Shbltin_t *context)
+{
+ register int r;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (r = optget(argv,sh_opteval)) switch (r)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(*argv && **argv)
+ {
+ sh_offstate(SH_MONITOR);
+ sh_eval(sh_sfeval(argv),0);
+ }
+ return(shp->exitval);
+}
+
+int b_dot_cmd(register int n,char *argv[],Shbltin_t *context)
+{
+ register char *script;
+ register Namval_t *np;
+ register int jmpval;
+ register Shell_t *shp = context->shp;
+ struct sh_scoped savst, *prevscope = shp->st.self;
+ char *filename=0;
+ int fd;
+ struct dolnod *argsave=0, *saveargfor;
+ struct checkpt buff;
+ Sfio_t *iop=0;
+ short level;
+ while (n = optget(argv,sh_optdot)) switch (n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ script = *argv;
+ if(error_info.errors || !script)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(shp->dot_depth+1 > DOTMAX)
+ errormsg(SH_DICT,ERROR_exit(1),e_toodeep,script);
+ if(!(np=shp->posix_fun))
+ {
+ /* check for KornShell style function first */
+ np = nv_search(script,shp->fun_tree,0);
+ if(np && is_afunction(np) && !nv_isattr(np,NV_FPOSIX))
+ {
+ if(!np->nvalue.ip)
+ {
+ path_search(shp,script,NIL(Pathcomp_t**),0);
+ if(np->nvalue.ip)
+ {
+ if(nv_isattr(np,NV_FPOSIX))
+ np = 0;
+ }
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_found,script);
+ }
+ }
+ else
+ np = 0;
+ if(!np)
+ {
+ if((fd=path_open(shp,script,path_get(shp,script))) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,script);
+ filename = path_fullname(shp,stkptr(shp->stk,PATH_OFFSET));
+ }
+ }
+ *prevscope = shp->st;
+ shp->st.lineno = np?((struct functnod*)nv_funtree(np))->functline:1;
+ shp->st.var_local = shp->st.save_tree = shp->var_tree;
+ if(filename)
+ {
+ shp->st.filename = filename;
+ shp->st.lineno = 1;
+ }
+ level = shp->fn_depth+shp->dot_depth+1;
+ nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
+ shp->st.prevst = prevscope;
+ shp->st.self = &savst;
+ shp->topscope = (Shscope_t*)shp->st.self;
+ prevscope->save_tree = shp->var_tree;
+ if(np)
+ shp->st.filename = np->nvalue.rp->fname;
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ shp->posix_fun = 0;
+ if(np || argv[1])
+ argsave = sh_argnew(shp,argv,&saveargfor);
+ sh_pushcontext(shp,&buff,SH_JMPDOT);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval == 0)
+ {
+ shp->dot_depth++;
+ if(np)
+ sh_exec((Shnode_t*)(nv_funtree(np)),sh_isstate(SH_ERREXIT));
+ else
+ {
+ char buff[IOBSIZE+1];
+ iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fd,SF_READ);
+ sh_offstate(SH_NOFORK);
+ sh_eval(iop,sh_isstate(SH_PROFILE)?SH_FUNEVAL:0);
+ }
+ }
+ sh_popcontext(shp,&buff);
+ if(!np)
+ free((void*)shp->st.filename);
+ shp->dot_depth--;
+ if((np || argv[1]) && jmpval!=SH_JMPSCRIPT)
+ sh_argreset(shp,argsave,saveargfor);
+ else
+ {
+ prevscope->dolc = shp->st.dolc;
+ prevscope->dolv = shp->st.dolv;
+ }
+ if (shp->st.self != &savst)
+ *shp->st.self = shp->st;
+ /* only restore the top Shscope_t portion for posix functions */
+ memcpy((void*)&shp->st, (void*)prevscope, sizeof(Shscope_t));
+ shp->topscope = (Shscope_t*)prevscope;
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ if(jmpval && jmpval!=SH_JMPFUN)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(shp->exitval);
+}
+
+/*
+ * null, true command
+ */
+int b_true(int argc,register char *argv[],Shbltin_t *context)
+{
+ NOT_USED(argc);
+ NOT_USED(argv[0]);
+ NOT_USED(context);
+ return(0);
+}
+
+/*
+ * false command
+ */
+int b_false(int argc,register char *argv[], Shbltin_t *context)
+{
+ NOT_USED(argc);
+ NOT_USED(argv[0]);
+ NOT_USED(context);
+ return(1);
+}
+
+int b_shift(register int n, register char *argv[], Shbltin_t *context)
+{
+ register char *arg;
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optshift))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ n = ((arg= *argv)?(int)sh_arith(shp,arg):1);
+ if(n<0 || shp->st.dolc<n)
+ errormsg(SH_DICT,ERROR_exit(1),e_number,arg);
+ else
+ {
+ shp->st.dolv += n;
+ shp->st.dolc -= n;
+ }
+ return(0);
+}
+
+int b_wait(int n,register char *argv[],Shbltin_t *context)
+{
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optwait))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ job_bwait(argv);
+ return(shp->exitval);
+}
+
+#ifdef JOBS
+# if 0
+ /* for the dictionary generator */
+ int b_fg(int n,char *argv[],Shbltin_t *context){}
+ int b_disown(int n,char *argv[],Shbltin_t *context){}
+# endif
+int b_bg(register int n,register char *argv[],Shbltin_t *context)
+{
+ register int flag = **argv;
+ register Shell_t *shp = context->shp;
+ register const char *optstr = sh_optbg;
+ if(*argv[0]=='f')
+ optstr = sh_optfg;
+ else if(*argv[0]=='d')
+ optstr = sh_optdisown;
+ while((n = optget(argv,optstr))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(!sh_isoption(SH_MONITOR) || !job.jobcontrol)
+ {
+ if(sh_isstate(SH_INTERACTIVE))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_jctl);
+ return(1);
+ }
+ if(flag=='d' && *argv==0)
+ argv = (char**)0;
+ if(job_walk(sfstdout,job_switch,flag,argv))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_job);
+ return(shp->exitval);
+}
+
+int b_jobs(register int n,char *argv[],Shbltin_t *context)
+{
+ register int flag = 0;
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optjobs))) switch(n)
+ {
+ case 'l':
+ flag = JOB_LFLAG;
+ break;
+ case 'n':
+ flag = JOB_NFLAG;
+ break;
+ case 'p':
+ flag = JOB_PFLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*argv==0)
+ argv = (char**)0;
+ if(job_walk(sfstdout,job_list,flag,argv))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_job);
+ job_wait((pid_t)0);
+ return(shp->exitval);
+}
+#endif
+
+#ifdef _cmd_universe
+/*
+ * There are several universe styles that are masked by the getuniv(),
+ * setuniv() calls.
+ */
+int b_universe(int argc, char *argv[],Shbltin_t *context)
+{
+ register char *arg;
+ register int n;
+ NOT_USED(context);
+ while((n = optget(argv,sh_optuniverse))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc>1)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(arg = argv[0])
+ {
+ if(!astconf("UNIVERSE",0,arg))
+ errormsg(SH_DICT,ERROR_exit(1), e_badname,arg);
+ }
+ else
+ {
+ if(!(arg=astconf("UNIVERSE",0,0)))
+ errormsg(SH_DICT,ERROR_exit(1),e_nouniverse);
+ else
+ sfputr(sfstdout,arg,'\n');
+ }
+ return(0);
+}
+#endif /* cmd_universe */
+
+#if SHOPT_FS_3D
+#if _UWIN
+#include <sys/mount.h>
+#endif
+# if 0
+ /* for the dictionary generator */
+ int b_vmap(int argc,char *argv[], Shbltin_t *context){}
+# endif
+ int b_vpath(register int argc,char *argv[], Shbltin_t *context)
+ {
+ register int flag, n;
+ register const char *optstr;
+ register char *vend;
+ register Shell_t *shp = context->shp;
+ if(argv[0][1]=='p')
+ {
+ optstr = sh_optvpath;
+ flag = FS3D_VIEW;
+ }
+ else
+ {
+ optstr = sh_optvmap;
+ flag = FS3D_VERSION;
+ }
+ while(n = optget(argv, optstr)) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+#ifdef MS_3D
+ flag |= MS_3D;
+#else
+ if(!shp->gd->lim.fs3d)
+ goto failed;
+#endif
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ switch(argc)
+ {
+ case 0:
+ case 1:
+ flag |= FS3D_GET;
+ if((n = mount(*argv,(char*)0,flag,0)) >= 0)
+ {
+ vend = stkalloc(shp->stk,++n);
+ n = mount(*argv,vend,flag|FS3D_SIZE(n),0);
+ }
+ if(n < 0)
+ goto failed;
+ if(argc==1)
+ {
+ sfprintf(sfstdout,"%s\n",vend);
+ break;
+ }
+ n = 0;
+ while(flag = *vend++)
+ {
+ if(flag==' ')
+ {
+ flag = e_sptbnl[n+1];
+ n = !n;
+ }
+ sfputc(sfstdout,flag);
+ }
+ if(n)
+ sfputc(sfstdout,'\n');
+ break;
+ default:
+ if((argc&1))
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ /*FALLTHROUGH*/
+ case 2:
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ for(n=0;n<argc;n+=2)
+ if(mount(argv[n+1],argv[n],flag,0)<0)
+ goto failed;
+ }
+ return(0);
+failed:
+ errormsg(SH_DICT,ERROR_exit(1),(argc>1)?e_cantset:e_cantget,(flag&FS3D_VIEW)?e_mapping:e_versions);
+ return(1);
+ }
+#endif /* SHOPT_FS_3D */
+
diff --git a/src/cmd/ksh93/bltins/mkservice.c b/src/cmd/ksh93/bltins/mkservice.c
new file mode 100644
index 0000000..0cbba25
--- /dev/null
+++ b/src/cmd/ksh93/bltins/mkservice.c
@@ -0,0 +1,494 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * mkservice varname pathname
+ * eloop [-t timeout]
+ * Written by David Korn
+ * AT&T Labs
+ */
+
+static const char mkservice_usage[] =
+"[-?\n@(#)$Id: mkservice (AT&T Research) 2001-06-13 $\n]"
+USAGE_LICENSE
+"[+NAME? mkservice - create a shell server ]"
+"[+DESCRIPTION?\bmkservice\b creates a tcp or udp server that is "
+ "implemented by shell functions.]"
+"[+?The \aservice_path\a must be of the form \b/dev/tcp/localhost/\b\aportno\a "
+ "or \b/dev/udp/localhost/\b\aportno\a depending on whether the "
+ "\btcp\b or \budp\b protocol is used. \aportno\a is the port "
+ "number that the service will use.]"
+"[+?The shell variable \avarname\a is associated with the service. This "
+ "variable can have subvariables that keeps the state of all "
+ "active connections. The functions \avarname\a\b.accept\b, "
+ "\avarname\a\b.action\b and \avarname\a\b.close\b implement the "
+ "service as follows:]{"
+ "[+accept?This function is invoked when a client tries to connect "
+ "to the service. It is called with an argument which "
+ "is the file descriptor number associated with the "
+ "accepted connection. If the function returns a non-zero "
+ "value, this connection will be closed.]"
+ "[+action?This function is invoked when there is data waiting "
+ "to be read from one of the active connections. It is "
+ "called with the file descriptor number that has data "
+ "to be read. If the function returns a non-zero "
+ "value, this connection will be closed.]"
+ "[+close?This function is invoked when the connection is closed.]"
+ "}"
+"[+?If \avarname\a is unset, then all active connection, and the service "
+ "itself will be closed.]"
+""
+"\n"
+"\nvarname service_path\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Success.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\beloop\b(1)]"
+;
+
+
+static const char eloop_usage[] =
+"[-?\n@(#)$Id: eloop (AT&T Research) 2001-06-13 $\n]"
+USAGE_LICENSE
+"[+NAME? eloop - process event loop]"
+"[+DESCRIPTION?\beloop\b causes the shell to block waiting for events "
+ "to process. By default, \beloop\b does not return.]"
+"[t]#[timeout?\atimeout\a is the number of milliseconds to wait "
+ "without receiving any events to process.]"
+"\n"
+"\n\n"
+"\n"
+"[+EXIT STATUS?If no timeout is specified, \beloop\b will not return "
+ "unless interrupted. Otherwise]{"
+ "[+0?The specified timeout interval occurred.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bmkservice\b(1)]"
+;
+
+
+#include "defs.h"
+
+#include <cmd.h>
+#include <error.h>
+#include <nval.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#define ACCEPT 0
+#define ACTION 1
+#define CLOSE 2
+
+#ifndef O_SERVICE
+# define O_SERVICE O_NOCTTY
+#endif
+
+static const char* disctab[] =
+{
+ "accept",
+ "action",
+ "close",
+ 0
+};
+
+typedef struct Service_s Service_t;
+
+struct Service_s
+{
+ Namfun_t fun;
+ short fd;
+ int refcount;
+ int (*acceptf)(Service_t*,int);
+ int (*actionf)(Service_t*,int,int);
+ int (*errorf)(Service_t*,int,const char*, ...);
+ void *context;
+ Namval_t* node;
+ Namval_t* disc[elementsof(disctab)-1];
+};
+
+static short *file_list;
+static Sfio_t **poll_list;
+static Service_t **service_list;
+static int npoll;
+static int nready;
+static int ready;
+static int (*covered_fdnotify)(int, int);
+
+static int fdclose(Service_t *sp, register int fd)
+{
+ register int i;
+ service_list[fd] = 0;
+ if(sp->fd==fd)
+ sp->fd = -1;
+ for(i=0; i < npoll; i++)
+ {
+ if(file_list[i]==fd)
+ {
+ file_list[i] = file_list[npoll--];
+ if(sp->actionf)
+ (*sp->actionf)(sp, fd, 1);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+static int fdnotify(int fd1, int fd2)
+{
+ Service_t *sp;
+ if (covered_fdnotify)
+ (*covered_fdnotify)(fd1, fd2);
+ if(fd2!=SH_FDCLOSE)
+ {
+ register int i;
+ service_list[fd2] = service_list[fd1];
+ service_list[fd1] = 0;
+ for(i=0; i < npoll; i++)
+ {
+ if(file_list[i]==fd1)
+ {
+ file_list[i] = fd2;
+ return(0);
+ }
+ }
+ }
+ else if(sp = service_list[fd1])
+ {
+ fdclose(sp,fd1);
+ if(--sp->refcount==0)
+ nv_unset(sp->node);
+ }
+ return(0);
+}
+
+static void process_stream(Sfio_t* iop)
+{
+ int r=0, fd = sffileno(iop);
+ Service_t * sp = service_list[fd];
+ if(fd==sp->fd) /* connection socket */
+ {
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+ fd = accept(fd, &addr, &addrlen);
+ service_list[fd] = sp;
+ sp->refcount++;
+ file_list[npoll++] = fd;
+ if(fd>=0)
+ {
+ if(sp->acceptf)
+ r = (*sp->acceptf)(sp,fd);
+ }
+ }
+ else if(sp->actionf)
+ {
+ service_list[fd] = 0;
+ r = (*sp->actionf)(sp, fd, 0);
+ service_list[fd] = sp;
+ if(r<0)
+ close(fd);
+ }
+}
+
+static int waitnotify(int fd, long timeout, int rw)
+{
+ Sfio_t *special=0, **pstream;
+ register int i;
+
+ if (fd >= 0)
+ special = sh_fd2sfio(fd);
+ while(1)
+ {
+ pstream = poll_list;
+ while(ready < nready)
+ process_stream(pstream[ready++]);
+ if(special)
+ *pstream++ = special;
+ for(i=0; i < npoll; i++)
+ {
+ if(service_list[file_list[i]])
+ *pstream++ = sh_fd2sfio(file_list[i]);
+ }
+#if 1
+ for(i=0; i < pstream-poll_list; i++)
+ sfset(poll_list[i],SF_WRITE,0);
+#endif
+ nready = ready = 0;
+ errno = 0;
+#ifdef DEBUG
+ sfprintf(sfstderr,"before poll npoll=%d",pstream-poll_list);
+ for(i=0; i < pstream-poll_list; i++)
+ sfprintf(sfstderr," %d",sffileno(poll_list[i]));
+ sfputc(sfstderr,'\n');
+#endif
+ nready = sfpoll(poll_list,pstream-poll_list,timeout);
+#ifdef DEBUG
+ sfprintf(sfstderr,"after poll nready=%d",nready);
+ for(i=0; i < nready; i++)
+ sfprintf(sfstderr," %d",sffileno(poll_list[i]));
+ sfputc(sfstderr,'\n');
+#endif
+#if 1
+ for(i=0; i < pstream-poll_list; i++)
+ sfset(poll_list[i],SF_WRITE,1);
+#endif
+ if(nready<=0)
+ return(errno? -1: 0);
+ if(special && poll_list[0]==special)
+ {
+ ready = 1;
+ return(fd);
+ }
+ }
+}
+
+static int service_init(void)
+{
+ file_list = newof(NULL,short,n,0);
+ poll_list = newof(NULL,Sfio_t*,n,0);
+ service_list = newof(NULL,Service_t*,n,0);
+ covered_fdnotify = sh_fdnotify(fdnotify);
+ sh_waitnotify(waitnotify);
+ return(1);
+}
+
+void service_add(Service_t *sp)
+{
+ static int init;
+ if (!init)
+ init = service_init();
+ service_list[sp->fd] = sp;
+ file_list[npoll++] = sp->fd;
+}
+
+static int Accept(register Service_t *sp, int accept_fd)
+{
+ register Namval_t* nq = sp->disc[ACCEPT];
+ int fd;
+
+ fd = fcntl(accept_fd, F_DUPFD, 10);
+ if (fd >= 0)
+ {
+ close(accept_fd);
+ if (nq)
+ {
+ char* av[3];
+ char buff[20];
+
+ av[1] = buff;
+ av[2] = 0;
+ sfsprintf(buff, sizeof(buff), "%d", fd);
+ if (sh_fun(nq, sp->node, av))
+ {
+ close(fd);
+ return -1;
+ }
+ }
+ }
+ sfsync(NiL);
+ return fd;
+}
+
+static int Action(Service_t *sp, int fd, int close)
+{
+ register Namval_t* nq;
+ int r=0;
+
+ if(close)
+ nq = sp->disc[CLOSE];
+ else
+ nq = sp->disc[ACTION];
+ if (nq)
+ {
+ char* av[3];
+ char buff[20];
+
+ av[1] = buff;
+ av[2] = 0;
+ sfsprintf(buff, sizeof(buff), "%d", fd);
+ r=sh_fun(nq, sp->node, av);
+ }
+ sfsync(NiL);
+ return r > 0 ? -1 : 1;
+}
+
+static int Error(Service_t *sp, int level, const char* arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ if(sp->node)
+ nv_unset(sp->node);
+ free((void*)sp);
+ errorv(NiL, ERROR_exit(1), ap);
+ va_end(ap);
+ return 0;
+}
+
+static char* setdisc(Namval_t* np, const char* event, Namval_t* action, Namfun_t* fp)
+{
+ register Service_t* sp = (Service_t*)fp;
+ register const char* cp;
+ register int i;
+ register int n = strlen(event) - 1;
+ register Namval_t* nq;
+
+ for (i = 0; cp = disctab[i]; i++)
+ {
+ if (memcmp(event, cp, n))
+ continue;
+ if (action == np)
+ action = sp->disc[i];
+ else
+ {
+ if (nq = sp->disc[i])
+ free((void*)nq);
+ if (action)
+ sp->disc[i] = action;
+ else
+ sp->disc[i] = 0;
+ }
+ return action ? (char*)action : "";
+ }
+ /* try the next level */
+ return nv_setdisc(np, event, action, fp);
+}
+
+static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ register Service_t* sp = (Service_t*)fp;
+ if (!val)
+ fp = nv_stack(np, NiL);
+ nv_putv(np, val, flag, fp);
+ if (!val)
+ {
+ register int i;
+ for(i=0; i< sh.lim.open_max; i++)
+ {
+ if(service_list[i]==sp)
+ {
+ close(i);
+ if(--sp->refcount<=0)
+ break;
+ }
+ }
+ free((void*)fp);
+ return;
+ }
+}
+
+static const Namdisc_t servdisc =
+{
+ sizeof(Service_t),
+ putval,
+ 0,
+ 0,
+ setdisc
+};
+
+int b_mkservice(int argc, char** argv, Shbltin_t *context)
+{
+ register char* var;
+ register char* path;
+ register Namval_t* np;
+ register Service_t* sp;
+ register int fd;
+
+ NOT_USED(argc);
+ NOT_USED(context);
+ for (;;)
+ {
+ switch (optget(argv, mkservice_usage))
+ {
+ case 0:
+ break;
+ case ':':
+ error(2, opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !(var = *argv++) || !(path = *argv++) || *argv)
+ error(ERROR_usage(2), optusage(NiL));
+ if (!(sp = newof(0, Service_t, 1, 0)))
+ error(ERROR_exit(1), "out of space");
+ sp->acceptf = Accept;
+ sp->actionf = Action;
+ sp->errorf = Error;
+ sp->refcount = 1;
+ sp->context = context;
+ sp->node = 0;
+ sp->fun.disc = &servdisc;
+ if((fd = sh_open(path, O_SERVICE|O_RDWR))<=0)
+ {
+ free((void*)sp);
+ error(ERROR_exit(1), "%s: cannot start service", path);
+ }
+ if((sp->fd = fcntl(fd, F_DUPFD, 10))>=10)
+ close(fd);
+ else
+ sp->fd = fd;
+ np = nv_open(var,sh.var_tree,NV_ARRAY|NV_VARNAME|NV_NOASSIGN);
+ sp->node = np;
+ nv_putval(np, path, 0);
+ nv_stack(np, (Namfun_t*)sp);
+ service_add(sp);
+ return(0);
+}
+
+int b_eloop(int argc, char** argv, Shbltin_t *context)
+{
+ register long timeout = -1;
+ NOT_USED(argc);
+ NOT_USED(context);
+ for (;;)
+ {
+ switch (optget(argv, eloop_usage))
+ {
+ case 0:
+ break;
+ case 't':
+ timeout = opt_info.num;
+ continue;
+ case ':':
+ error(2, opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv)
+ error(ERROR_usage(2), optusage(NiL));
+ while(1)
+ {
+ if(waitnotify(-1, timeout, 0)==0)
+ break;
+ sfprintf(sfstderr,"interrupted\n");
+ }
+ return(errno != 0);
+}
diff --git a/src/cmd/ksh93/bltins/print.c b/src/cmd/ksh93/bltins/print.c
new file mode 100644
index 0000000..011bccd
--- /dev/null
+++ b/src/cmd/ksh93/bltins/print.c
@@ -0,0 +1,1058 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * echo [arg...]
+ * print [-nrps] [-f format] [-u filenum] [arg...]
+ * printf format [arg...]
+ *
+ * David Korn
+ * AT&T Labs
+ */
+
+#include "defs.h"
+#include <error.h>
+#include <stak.h>
+#include "io.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#include "streval.h"
+#include <tmx.h>
+#include <ccode.h>
+
+union types_t
+{
+ unsigned char c;
+ short h;
+ int i;
+ long l;
+ Sflong_t ll;
+ Sfdouble_t ld;
+ double d;
+ float f;
+ char *s;
+ int *ip;
+ char **p;
+};
+
+struct printf
+{
+ Sffmt_t hdr;
+ int argsize;
+ int intvar;
+ char **nextarg;
+ char *lastarg;
+ char cescape;
+ char err;
+ Shell_t *sh;
+};
+
+static int extend(Sfio_t*,void*, Sffmt_t*);
+static const char preformat[] = "";
+static char *genformat(char*);
+static int fmtvecho(const char*, struct printf*);
+static ssize_t fmtbase64(Sfio_t*, char*, int);
+
+struct print
+{
+ Shell_t *sh;
+ const char *options;
+ char raw;
+ char echon;
+};
+
+static char* nullarg[] = { 0, 0 };
+
+#if !SHOPT_ECHOPRINT
+ int B_echo(int argc, char *argv[],Shbltin_t *context)
+ {
+ static char bsd_univ;
+ struct print prdata;
+ prdata.options = sh_optecho+5;
+ prdata.raw = prdata.echon = 0;
+ prdata.sh = context->shp;
+ NOT_USED(argc);
+ /* This mess is because /bin/echo on BSD is different */
+ if(!prdata.sh->universe)
+ {
+ register char *universe;
+ if(universe=astconf("UNIVERSE",0,0))
+ bsd_univ = (strcmp(universe,"ucb")==0);
+ prdata.sh->universe = 1;
+ }
+ if(!bsd_univ)
+ return(b_print(0,argv,(Shbltin_t*)&prdata));
+ prdata.options = sh_optecho;
+ prdata.raw = 1;
+ while(argv[1] && *argv[1]=='-')
+ {
+ if(strcmp(argv[1],"-n")==0)
+ prdata.echon = 1;
+#if !SHOPT_ECHOE
+ else if(strcmp(argv[1],"-e")==0)
+ prdata.raw = 0;
+ else if(strcmp(argv[1],"-ne")==0 || strcmp(argv[1],"-en")==0)
+ {
+ prdata.raw = 0;
+ prdata.echon = 1;
+ }
+#endif /* SHOPT_ECHOE */
+ else
+ break;
+ argv++;
+ }
+ return(b_print(0,argv,(Shbltin_t*)&prdata));
+ }
+#endif /* SHOPT_ECHOPRINT */
+
+int b_printf(int argc, char *argv[],Shbltin_t *context)
+{
+ struct print prdata;
+ NOT_USED(argc);
+ memset(&prdata,0,sizeof(prdata));
+ prdata.sh = context->shp;
+ prdata.options = sh_optprintf;
+ return(b_print(-1,argv,(Shbltin_t*)&prdata));
+}
+
+/*
+ * argc==0 when called from echo
+ * argc==-1 when called from printf
+ */
+
+int b_print(int argc, char *argv[], Shbltin_t *context)
+{
+ register Sfio_t *outfile;
+ register int exitval=0,n, fd = 1;
+ register Shell_t *shp = context->shp;
+ const char *options, *msg = e_file+4;
+ char *format = 0;
+ int sflag = 0, nflag=0, rflag=0, vflag=0;
+ if(argc>0)
+ {
+ options = sh_optprint;
+ nflag = rflag = 0;
+ format = 0;
+ }
+ else
+ {
+ struct print *pp = (struct print*)context;
+ shp = pp->sh;
+ options = pp->options;
+ if(argc==0)
+ {
+ nflag = pp->echon;
+ rflag = pp->raw;
+ argv++;
+ goto skip;
+ }
+ }
+ while((n = optget(argv,options))) switch(n)
+ {
+ case 'n':
+ nflag++;
+ break;
+ case 'p':
+ fd = shp->coutpipe;
+ msg = e_query;
+ break;
+ case 'f':
+ format = opt_info.arg;
+ break;
+ case 's':
+ /* print to history file */
+ if(!sh_histinit((void*)shp))
+ errormsg(SH_DICT,ERROR_system(1),e_history);
+ fd = sffileno(shp->gd->hist_ptr->histfp);
+ sh_onstate(SH_HISTORY);
+ sflag++;
+ break;
+ case 'e':
+ rflag = 0;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'u':
+ fd = (int)strtol(opt_info.arg,&opt_info.arg,10);
+ if(*opt_info.arg)
+ fd = -1;
+ else if(!sh_iovalidfd(shp,fd))
+ fd = -1;
+ else if(!(shp->inuse_bits&(1<<fd)) && (sh_inuse(shp,fd) || (shp->gd->hist_ptr && fd==sffileno(shp->gd->hist_ptr->histfp))))
+
+ fd = -1;
+ break;
+ case 'v':
+ vflag='v';
+ break;
+ case 'C':
+ vflag='C';
+ break;
+ case ':':
+ /* The following is for backward compatibility */
+#if OPT_VERSION >= 19990123
+ if(strcmp(opt_info.name,"-R")==0)
+#else
+ if(strcmp(opt_info.option,"-R")==0)
+#endif
+ {
+ rflag = 1;
+ if(error_info.errors==0)
+ {
+ argv += opt_info.index+1;
+ /* special case test for -Rn */
+ if(strchr(argv[-1],'n'))
+ nflag++;
+ if(*argv && strcmp(*argv,"-n")==0)
+ {
+
+ nflag++;
+ argv++;
+ }
+ goto skip2;
+ }
+ }
+ else
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors || (argc<0 && !(format = *argv++)))
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(vflag && format)
+ errormsg(SH_DICT,ERROR_usage(2),"-%c and -f are mutually exclusive",vflag);
+skip:
+ if(format)
+ format = genformat(format);
+ /* handle special case of '-' operand for print */
+ if(argc>0 && *argv && strcmp(*argv,"-")==0 && strcmp(argv[-1],"--"))
+ argv++;
+skip2:
+ if(fd < 0)
+ {
+ errno = EBADF;
+ n = 0;
+ }
+ else if(!(n=shp->fdstatus[fd]))
+ n = sh_iocheckfd(shp,fd);
+ if(!(n&IOWRITE))
+ {
+ /* don't print error message for stdout for compatibility */
+ if(fd==1)
+ return(1);
+ errormsg(SH_DICT,ERROR_system(1),msg);
+ }
+ if(!(outfile=shp->sftable[fd]))
+ {
+ sh_onstate(SH_NOTRACK);
+ n = SF_WRITE|((n&IOREAD)?SF_READ:0);
+ shp->sftable[fd] = outfile = sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fd,n);
+ sh_offstate(SH_NOTRACK);
+ sfpool(outfile,shp->outpool,SF_WRITE);
+ }
+ /* turn off share to guarantee atomic writes for printf */
+ n = sfset(outfile,SF_SHARE|SF_PUBLIC,0);
+ if(format)
+ {
+ /* printf style print */
+ Sfio_t *pool;
+ struct printf pdata;
+ memset(&pdata, 0, sizeof(pdata));
+ pdata.sh = shp;
+ pdata.hdr.version = SFIO_VERSION;
+ pdata.hdr.extf = extend;
+ pdata.nextarg = argv;
+ sh_offstate(SH_STOPOK);
+ pool=sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
+ do
+ {
+ if(shp->trapnote&SH_SIGSET)
+ break;
+ pdata.hdr.form = format;
+ sfprintf(outfile,"%!",&pdata);
+ } while(*pdata.nextarg && pdata.nextarg!=argv);
+ if(pdata.nextarg == nullarg && pdata.argsize>0)
+ sfwrite(outfile,stakptr(staktell()),pdata.argsize);
+ if(sffileno(outfile)!=sffileno(sfstderr))
+ sfsync(outfile);
+ sfpool(sfstderr,pool,SF_WRITE);
+ exitval = pdata.err;
+ }
+ else if(vflag)
+ {
+ while(*argv)
+ {
+ fmtbase64(outfile,*argv++,vflag=='C');
+ if(!nflag)
+ sfputc(outfile,'\n');
+ }
+ }
+ else
+ {
+ /* echo style print */
+ if(nflag && !argv[0])
+ sfsync((Sfio_t*)0);
+ else if(sh_echolist(shp,outfile,rflag,argv) && !nflag)
+ sfputc(outfile,'\n');
+ }
+ if(sflag)
+ {
+ hist_flush(shp->gd->hist_ptr);
+ sh_offstate(SH_HISTORY);
+ }
+ else if(n&SF_SHARE)
+ {
+ sfset(outfile,SF_SHARE|SF_PUBLIC,1);
+ sfsync(outfile);
+ }
+ return(exitval);
+}
+
+/*
+ * echo the argument list onto <outfile>
+ * if <raw> is non-zero then \ is not a special character.
+ * returns 0 for \c otherwise 1.
+ */
+
+int sh_echolist(Shell_t *shp,Sfio_t *outfile, int raw, char *argv[])
+{
+ register char *cp;
+ register int n;
+ struct printf pdata;
+ pdata.cescape = 0;
+ pdata.err = 0;
+ while(!pdata.cescape && (cp= *argv++))
+ {
+ if(!raw && (n=fmtvecho(cp,&pdata))>=0)
+ {
+ if(n)
+ sfwrite(outfile,stakptr(staktell()),n);
+ }
+ else
+ sfputr(outfile,cp,-1);
+ if(*argv)
+ sfputc(outfile,' ');
+ sh_sigcheck(shp);
+ }
+ return(!pdata.cescape);
+}
+
+/*
+ * modified version of stresc for generating formats
+ */
+static char strformat(char *s)
+{
+ register char* t;
+ register int c;
+ char* b;
+ char* p;
+#if SHOPT_MULTIBYTE && defined(FMT_EXP_WIDE)
+ int w;
+#endif
+
+ b = t = s;
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case '\\':
+ if(*s==0)
+ break;
+#if SHOPT_MULTIBYTE && defined(FMT_EXP_WIDE)
+ c = chrexp(s - 1, &p, &w, FMT_EXP_CHAR|FMT_EXP_LINE|FMT_EXP_WIDE);
+#else
+ c = chresc(s - 1, &p);
+#endif
+ s = p;
+#if SHOPT_MULTIBYTE
+#if defined(FMT_EXP_WIDE)
+ if(w)
+ {
+ t += mbwide() ? mbconv(t, c) : wc2utf8(t, c);
+ continue;
+ }
+#else
+ if(c>UCHAR_MAX && mbwide())
+ {
+ t += mbconv(t, c);
+ continue;
+ }
+#endif /* FMT_EXP_WIDE */
+#endif /* SHOPT_MULTIBYTE */
+ if(c=='%')
+ *t++ = '%';
+ else if(c==0)
+ {
+ *t++ = '%';
+ c = 'Z';
+ }
+ break;
+ case 0:
+ *t = 0;
+ return(t - b);
+ }
+ *t++ = c;
+ }
+}
+
+
+static char *genformat(char *format)
+{
+ register char *fp;
+ stakseek(0);
+ stakputs(preformat);
+ stakputs(format);
+ fp = (char*)stakfreeze(1);
+ strformat(fp+sizeof(preformat)-1);
+ return(fp);
+}
+
+static char *fmthtml(const char *string, int flags)
+{
+ register const char *cp = string;
+ register int c, offset = staktell();
+ if(!(flags&SFFMT_ALTER))
+ {
+ while(c= *(unsigned char*)cp++)
+ {
+#if SHOPT_MULTIBYTE
+ register int s;
+ if((s=mbsize(cp-1)) > 1)
+ {
+ cp += (s-1);
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if(c=='<')
+ stakputs("&lt;");
+ else if(c=='>')
+ stakputs("&gt;");
+ else if(c=='&')
+ stakputs("&amp;");
+ else if(c=='"')
+ stakputs("&quot;");
+ else if(c=='\'')
+ stakputs("&apos;");
+ else if(c==' ')
+ stakputs("&nbsp;");
+ else if(!isprint(c) && c!='\n' && c!='\r')
+ sfprintf(stkstd,"&#%X;",CCMAPC(c,CC_NATIVE,CC_ASCII));
+ else
+ stakputc(c);
+ }
+ }
+ else
+ {
+ while(c= *(unsigned char*)cp++)
+ {
+ if(strchr("!*'();@&+$,#[]<>~.\"{}|\\-`^% ",c) || (!isprint(c) && c!='\n' && c!='\r'))
+ sfprintf(stkstd,"%%%02X",CCMAPC(c,CC_NATIVE,CC_ASCII));
+ else
+ stakputc(c);
+ }
+ }
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+#if 1
+static ssize_t fmtbase64(Sfio_t *iop, char *string, int alt)
+#else
+static void *fmtbase64(char *string, ssize_t *sz, int alt)
+#endif
+{
+ char *cp;
+ Sfdouble_t d;
+ ssize_t size;
+ Namval_t *np = nv_open(string, NiL, NV_VARNAME|NV_NOASSIGN|NV_NOADD);
+ Namarr_t *ap;
+ static union types_t number;
+ if(!np || nv_isnull(np))
+ {
+ if(sh_isoption(SH_NOUNSET))
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,string);
+ return(0);
+ }
+ if(nv_isattr(np,NV_INTEGER))
+ {
+ d = nv_getnum(np);
+ if(nv_isattr(np,NV_DOUBLE))
+ {
+ if(nv_isattr(np,NV_LONG))
+ {
+ size = sizeof(Sfdouble_t);
+ number.ld = d;
+ }
+ else if(nv_isattr(np,NV_SHORT))
+ {
+ size = sizeof(float);
+ number.f = (float)d;
+ }
+ else
+ {
+ size = sizeof(double);
+ number.d = (double)d;
+ }
+ }
+ else
+ {
+ if(nv_isattr(np,NV_LONG))
+ {
+ size = sizeof(Sflong_t);
+ number.ll = (Sflong_t)d;
+ }
+ else if(nv_isattr(np,NV_SHORT))
+ {
+ size = sizeof(short);
+ number.h = (short)d;
+ }
+ else
+ {
+ size = sizeof(short);
+ number.i = (int)d;
+ }
+ }
+#if 1
+ return(sfwrite(iop, (void*)&number, size));
+#else
+ if(sz)
+ *sz = size;
+ return((void*)&number);
+#endif
+ }
+ if(nv_isattr(np,NV_BINARY))
+#if 1
+ {
+ Namfun_t *fp;
+ for(fp=np->nvfun; fp;fp=fp->next)
+ {
+ if(fp->disc && fp->disc->writef)
+ break;
+ }
+ if(fp)
+ return (*fp->disc->writef)(np, iop, 0, fp);
+ else
+ {
+ int n = nv_size(np);
+ if(nv_isarray(np))
+ {
+ nv_onattr(np,NV_RAW);
+ cp = nv_getval(np);
+ nv_offattr(np,NV_RAW);
+ }
+ else
+ cp = (char*)np->nvalue.cp;
+ if((size = n)==0)
+ size = strlen(cp);
+ size = sfwrite(iop, cp, size);
+ return(n?n:size);
+ }
+ }
+ else if(nv_isarray(np) && (ap=nv_arrayptr(np)) && array_elem(ap) && (ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN)))
+ {
+ nv_outnode(np,iop,(alt?-1:0),0);
+ sfputc(iop,')');
+ return(sftell(iop));
+ }
+ else
+ {
+ if(alt && nv_isvtree(np))
+ nv_onattr(np,NV_EXPORT);
+ else
+ alt = 0;
+ cp = nv_getval(np);
+ if(alt)
+ nv_offattr(np,NV_EXPORT);
+ if(!cp)
+ return(0);
+ size = strlen(cp);
+ return(sfwrite(iop,cp,size));
+ }
+#else
+ nv_onattr(np,NV_RAW);
+ cp = nv_getval(np);
+ if(nv_isattr(np,NV_BINARY))
+ nv_offattr(np,NV_RAW);
+ if((size = nv_size(np))==0)
+ size = strlen(cp);
+ if(sz)
+ *sz = size;
+ return((void*)cp);
+#endif
+}
+
+static int varname(const char *str, int n)
+{
+ register int c,dot=1,len=1;
+ if(n < 0)
+ {
+ if(*str=='.')
+ str++;
+ n = strlen(str);
+ }
+ for(;n > 0; n-=len)
+ {
+#ifdef SHOPT_MULTIBYTE
+ len = mbsize(str);
+ c = mbchar(str);
+#else
+ c = *(unsigned char*)str++;
+#endif
+ if(dot && !(isalpha(c)||c=='_'))
+ break;
+ else if(dot==0 && !(isalnum(c) || c=='_' || c == '.'))
+ break;
+ dot = (c=='.');
+ }
+ return(n==0);
+}
+
+static int extend(Sfio_t* sp, void* v, Sffmt_t* fe)
+{
+ char* lastchar = "";
+ register int neg = 0;
+ Sfdouble_t d;
+ Sfdouble_t longmin = LDBL_LLONG_MIN;
+ Sfdouble_t longmax = LDBL_LLONG_MAX;
+ int format = fe->fmt;
+ int n;
+ int fold = fe->base;
+ union types_t* value = (union types_t*)v;
+ struct printf* pp = (struct printf*)fe;
+ Shell_t *shp = pp->sh;
+ register char* argp = *pp->nextarg;
+ char *w,*s;
+
+ if(fe->n_str>0 && varname(fe->t_str,fe->n_str) && (!argp || varname(argp,-1)))
+ {
+ if(argp)
+ pp->lastarg = argp;
+ else
+ argp = pp->lastarg;
+ if(argp)
+ {
+ sfprintf(pp->sh->strbuf,"%s.%.*s%c",argp,fe->n_str,fe->t_str,0);
+ argp = sfstruse(pp->sh->strbuf);
+ }
+ }
+ else
+ pp->lastarg = 0;
+ fe->flags |= SFFMT_VALUE;
+ if(!argp || format=='Z')
+ {
+ switch(format)
+ {
+ case 'c':
+ value->c = 0;
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'q':
+ format = 's';
+ /* FALL THROUGH */
+ case 's':
+ case 'H':
+ case 'B':
+ case 'P':
+ case 'R':
+ case 'Z':
+ case 'b':
+ fe->fmt = 's';
+ fe->size = -1;
+ fe->base = -1;
+ value->s = "";
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'a':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'A':
+ case 'E':
+ case 'F':
+ case 'G':
+ if(SFFMT_LDOUBLE)
+ value->ld = 0.;
+ else
+ value->d = 0.;
+ break;
+ case 'n':
+ value->ip = &pp->intvar;
+ break;
+ case 'Q':
+ value->ll = 0;
+ break;
+ case 'T':
+ fe->fmt = 'd';
+ value->ll = tmxgettime();
+ break;
+ default:
+ if(!strchr("DdXxoUu",format))
+ errormsg(SH_DICT,ERROR_exit(1),e_formspec,format);
+ fe->fmt = 'd';
+ value->ll = 0;
+ break;
+ }
+ }
+ else
+ {
+ switch(format)
+ {
+ case 'p':
+ value->p = (char**)strtol(argp,&lastchar,10);
+ break;
+ case 'n':
+ {
+ Namval_t *np;
+ np = nv_open(argp,shp->var_tree,NV_VARNAME|NV_NOASSIGN|NV_NOARRAY);
+ _nv_unset(np,0);
+ nv_onattr(np,NV_INTEGER);
+ if (np->nvalue.lp = new_of(int32_t,0))
+ *np->nvalue.lp = 0;
+ nv_setsize(np,10);
+ if(sizeof(int)==sizeof(int32_t))
+ value->ip = (int*)np->nvalue.lp;
+ else
+ {
+ int32_t sl = 1;
+ value->ip = (int*)(((char*)np->nvalue.lp) + (*((char*)&sl) ? 0 : sizeof(int)));
+ }
+ nv_close(np);
+ break;
+ }
+ case 'q':
+ case 'b':
+ case 's':
+ case 'B':
+ case 'H':
+ case 'P':
+ case 'R':
+ fe->fmt = 's';
+ fe->size = -1;
+ if(format=='s' && fe->base>=0)
+ {
+ value->p = pp->nextarg;
+ pp->nextarg = nullarg;
+ }
+ else
+ {
+ fe->base = -1;
+ value->s = argp;
+ }
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'c':
+ if(mbwide() && (n = mbsize(argp)) > 1)
+ {
+ fe->fmt = 's';
+ fe->size = n;
+ value->s = argp;
+ }
+ else if(fe->base >=0)
+ value->s = argp;
+ else
+ value->c = *argp;
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'u':
+ case 'U':
+ longmax = LDBL_ULLONG_MAX;
+ case '.':
+ if(fe->size==2 && strchr("bcsqHPRQTZ",*fe->form))
+ {
+ value->ll = ((unsigned char*)argp)[0];
+ break;
+ }
+ case 'd':
+ case 'D':
+ case 'i':
+ switch(*argp)
+ {
+ case '\'':
+ case '"':
+ w = argp + 1;
+ if(mbwide() && mbsize(w) > 1)
+ value->ll = mbchar(w);
+ else
+ value->ll = *(unsigned char*)w++;
+ if(w[0] && (w[0] != argp[0] || w[1]))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_charconst,argp);
+ pp->err = 1;
+ }
+ break;
+ default:
+ d = sh_strnum(argp,&lastchar,0);
+ if(d<longmin)
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_overflow,argp);
+ pp->err = 1;
+ d = longmin;
+ }
+ else if(d>longmax)
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_overflow,argp);
+ pp->err = 1;
+ d = longmax;
+ }
+ value->ll = (Sflong_t)d;
+ if(lastchar == *pp->nextarg)
+ {
+ value->ll = *argp;
+ lastchar = "";
+ }
+ break;
+ }
+ if(neg)
+ value->ll = -value->ll;
+ fe->size = sizeof(value->ll);
+ break;
+ case 'a':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'A':
+ case 'E':
+ case 'F':
+ case 'G':
+ d = sh_strnum(*pp->nextarg,&lastchar,0);
+ switch(*argp)
+ {
+ case '\'':
+ case '"':
+ d = ((unsigned char*)argp)[1];
+ if(argp[2] && (argp[2] != argp[0] || argp[3]))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_charconst,argp);
+ pp->err = 1;
+ }
+ break;
+ default:
+ d = sh_strnum(*pp->nextarg,&lastchar,0);
+ break;
+ }
+ if(SFFMT_LDOUBLE)
+ {
+ value->ld = d;
+ fe->size = sizeof(value->ld);
+ }
+ else
+ {
+ value->d = d;
+ fe->size = sizeof(value->d);
+ }
+ break;
+ case 'Q':
+ value->ll = (Sflong_t)strelapsed(*pp->nextarg,&lastchar,1);
+ break;
+ case 'T':
+ value->ll = (Sflong_t)tmxdate(*pp->nextarg,&lastchar,TMX_NOW);
+ break;
+ default:
+ value->ll = 0;
+ fe->fmt = 'd';
+ fe->size = sizeof(value->ll);
+ errormsg(SH_DICT,ERROR_exit(1),e_formspec,format);
+ break;
+ }
+ if (format == '.')
+ value->i = value->ll;
+ if(*lastchar)
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_argtype,format);
+ pp->err = 1;
+ }
+ pp->nextarg++;
+ }
+ switch(format)
+ {
+ case 'Z':
+ fe->fmt = 'c';
+ fe->base = -1;
+ value->c = 0;
+ break;
+ case 'b':
+ if((n=fmtvecho(value->s,pp))>=0)
+ {
+ if(pp->nextarg == nullarg)
+ {
+ pp->argsize = n;
+ return -1;
+ }
+ value->s = stakptr(staktell());
+ fe->size = n;
+ }
+ break;
+ case 'B':
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ fe->size = fmtbase64(shp->strbuf2,value->s, fe->flags&SFFMT_ALTER);
+ value->s = sfstruse(shp->strbuf2);
+ fe->flags |= SFFMT_SHORT;
+ break;
+ case 'H':
+ value->s = fmthtml(value->s, fe->flags);
+ break;
+ case 'q':
+ value->s = sh_fmtqf(value->s, !!(fe->flags & SFFMT_ALTER), fold);
+ break;
+ case 'P':
+ s = fmtmatch(value->s);
+ if(!s || *s==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_badregexp,value->s);
+ value->s = s;
+ break;
+ case 'R':
+ s = fmtre(value->s);
+ if(!s || *s==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_badregexp,value->s);
+ value->s = s;
+ break;
+ case 'Q':
+ if (fe->n_str>0)
+ {
+ fe->fmt = 'd';
+ fe->size = sizeof(value->ll);
+ }
+ else
+ {
+ value->s = fmtelapsed(value->ll, 1);
+ fe->fmt = 's';
+ fe->size = -1;
+ }
+ break;
+ case 'T':
+ if(fe->n_str>0)
+ {
+ n = fe->t_str[fe->n_str];
+ fe->t_str[fe->n_str] = 0;
+ value->s = fmttmx(fe->t_str, value->ll);
+ fe->t_str[fe->n_str] = n;
+ }
+ else value->s = fmttmx(NIL(char*), value->ll);
+ fe->fmt = 's';
+ fe->size = -1;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * construct System V echo string out of <cp>
+ * If there are not escape sequences, returns -1
+ * Otherwise, puts null terminated result on stack, but doesn't freeze it
+ * returns length of output.
+ */
+
+static int fmtvecho(const char *string, struct printf *pp)
+{
+ register const char *cp = string, *cpmax;
+ register int c;
+ register int offset = staktell();
+#if SHOPT_MULTIBYTE
+ int chlen;
+ if(mbwide())
+ {
+ while(1)
+ {
+ if ((chlen = mbsize(cp)) > 1)
+ /* Skip over multibyte characters */
+ cp += chlen;
+ else if((c= *cp++)==0 || c == '\\')
+ break;
+ }
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((c= *cp++) && (c!='\\'));
+ if(c==0)
+ return(-1);
+ c = --cp - string;
+ if(c>0)
+ stakwrite((void*)string,c);
+ for(; c= *cp; cp++)
+ {
+#if SHOPT_MULTIBYTE
+ if (mbwide() && ((chlen = mbsize(cp)) > 1))
+ {
+ stakwrite(cp,chlen);
+ cp += (chlen-1);
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if( c=='\\') switch(*++cp)
+ {
+ case 'E':
+ c = ('a'==97?'\033':39); /* ASCII/EBCDIC */
+ break;
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'c':
+ pp->cescape++;
+ pp->nextarg = nullarg;
+ goto done;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ case '0':
+ c = 0;
+ cpmax = cp + 4;
+ while(++cp<cpmax && *cp>='0' && *cp<='7')
+ {
+ c <<= 3;
+ c |= (*cp-'0');
+ }
+ default:
+ cp--;
+ }
+ stakputc(c);
+ }
+done:
+ c = staktell()-offset;
+ stakputc(0);
+ stakseek(offset);
+ return(c);
+}
diff --git a/src/cmd/ksh93/bltins/read.c b/src/cmd/ksh93/bltins/read.c
new file mode 100644
index 0000000..75fc478
--- /dev/null
+++ b/src/cmd/ksh93/bltins/read.c
@@ -0,0 +1,802 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * read [-ACprs] [-d delim] [-u filenum] [-t timeout] [-n n] [-N n] [name...]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <error.h>
+#include "defs.h"
+#include "variables.h"
+#include "lexstates.h"
+#include "io.h"
+#include "name.h"
+#include "builtins.h"
+#include "history.h"
+#include "terminal.h"
+#include "edit.h"
+
+#define R_FLAG 1 /* raw mode */
+#define S_FLAG 2 /* save in history file */
+#define A_FLAG 4 /* read into array */
+#define N_FLAG 8 /* fixed size read at most */
+#define NN_FLAG 0x10 /* fixed size read exact */
+#define V_FLAG 0x20 /* use default value */
+#define C_FLAG 0x40 /* read into compound variable */
+#define D_FLAG 8 /* must be number of bits for all flags */
+#define SS_FLAG 0x80 /* read .csv format file */
+
+struct read_save
+{
+ char **argv;
+ char *prompt;
+ short fd;
+ short plen;
+ int flags;
+ long timeout;
+};
+
+int b_read(int argc,char *argv[], Shbltin_t *context)
+{
+ Sfdouble_t sec;
+ register char *name;
+ register int r, flags=0, fd=0;
+ register Shell_t *shp = context->shp;
+ long timeout = 1000*shp->st.tmout;
+ int save_prompt, fixargs=context->invariant;
+ struct read_save *rp;
+ static char default_prompt[3] = {ESC,ESC};
+ rp = (struct read_save*)(context->data);
+ if(argc==0)
+ {
+ if(rp)
+ free((void*)rp);
+ return(0);
+ }
+ if(rp)
+ {
+ flags = rp->flags;
+ timeout = rp->timeout;
+ fd = rp->fd;
+ argv = rp->argv;
+ name = rp->prompt;
+ r = rp->plen;
+ goto bypass;
+ }
+ while((r = optget(argv,sh_optread))) switch(r)
+ {
+ case 'A':
+ flags |= A_FLAG;
+ break;
+ case 'C':
+ flags |= C_FLAG;
+ break;
+ case 't':
+ sec = sh_strnum(opt_info.arg, (char**)0,1);
+ timeout = sec ? 1000*sec : 1;
+ break;
+ case 'd':
+ if(opt_info.arg && *opt_info.arg!='\n')
+ {
+ char *cp = opt_info.arg;
+ flags &= ~((1<<D_FLAG)-1);
+ flags |= (mbchar(cp)<< D_FLAG);
+ }
+ break;
+ case 'p':
+ if((fd = shp->cpipe[0])<=0)
+ errormsg(SH_DICT,ERROR_exit(1),e_query);
+ break;
+ case 'n': case 'N':
+ flags &= ((1<<D_FLAG)-1);
+ flags |= (r=='n'?N_FLAG:NN_FLAG);
+ r = (int)opt_info.num;
+ if((unsigned)r > (1<<((8*sizeof(int))-D_FLAG))-1)
+ errormsg(SH_DICT,ERROR_exit(1),e_overlimit,opt_info.name);
+ flags |= (r<< D_FLAG);
+ break;
+ case 'r':
+ flags |= R_FLAG;
+ break;
+ case 's':
+ /* save in history file */
+ flags |= S_FLAG;
+ break;
+ case 'S':
+ flags |= SS_FLAG;
+ break;
+ case 'u':
+ fd = (int)opt_info.num;
+ if(sh_inuse(shp,fd))
+ fd = -1;
+ break;
+ case 'v':
+ flags |= V_FLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
+ if(!((r=shp->fdstatus[fd])&IOREAD) || !(r&(IOSEEK|IONOSEEK)))
+ r = sh_iocheckfd(shp,fd);
+ if(fd<0 || !(r&IOREAD))
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ /* look for prompt */
+ if((name = *argv) && (name=strchr(name,'?')) && (r&IOTTY))
+ r = strlen(name++);
+ else
+ r = 0;
+ if(argc==fixargs && (rp=newof(NIL(struct read_save*),struct read_save,1,0)))
+ {
+ context->data = (void*)rp;
+ rp->fd = fd;
+ rp->flags = flags;
+ rp->timeout = timeout;
+ rp->argv = argv;
+ rp->prompt = name;
+ rp->plen = r;
+ }
+bypass:
+ shp->prompt = default_prompt;
+ if(r && (shp->prompt=(char*)sfreserve(sfstderr,r,SF_LOCKR)))
+ {
+ memcpy(shp->prompt,name,r);
+ sfwrite(sfstderr,shp->prompt,r-1);
+ }
+ shp->timeout = 0;
+ save_prompt = shp->nextprompt;
+ shp->nextprompt = 0;
+ r=sh_readline(shp,argv,fd,flags,timeout);
+ shp->nextprompt = save_prompt;
+ if(r==0 && (r=(sfeof(shp->sftable[fd])||sferror(shp->sftable[fd]))))
+ {
+ if(fd == shp->cpipe[0] && errno!=EINTR)
+ sh_pclose(shp->cpipe);
+ }
+ return(r);
+}
+
+/*
+ * here for read timeout
+ */
+static void timedout(void *handle)
+{
+ sfclrlock((Sfio_t*)handle);
+ sh_exit(1);
+}
+
+/*
+ * This is the code to read a line and to split it into tokens
+ * <names> is an array of variable names
+ * <fd> is the file descriptor
+ * <flags> is union of -A, -r, -s, and contains delimiter if not '\n'
+ * <timeout> is number of milli-seconds until timeout
+ */
+
+int sh_readline(register Shell_t *shp,char **names, int fd, int flags,long timeout)
+{
+ register ssize_t c;
+ register unsigned char *cp;
+ register Namval_t *np;
+ register char *name, *val;
+ register Sfio_t *iop;
+ Namfun_t *nfp;
+ char *ifs;
+ unsigned char *cpmax;
+ unsigned char *del;
+ char was_escape = 0;
+ char use_stak = 0;
+ volatile char was_write = 0;
+ volatile char was_share = 1;
+ int rel, wrd, keytrap;
+ long array_index = 0;
+ void *timeslot=0;
+ int delim = '\n';
+ int jmpval=0;
+ ssize_t size = 0;
+ int binary;
+ int oflags=NV_ASSIGN|NV_VARNAME;
+ char inquote = 0;
+ struct checkpt buff;
+ Edit_t *ep = (struct edit*)shp->gd->ed_context;
+ if(!(iop=shp->sftable[fd]) && !(iop=sh_iostream(shp,fd)))
+ return(1);
+ sh_stats(STAT_READS);
+ if(names && (name = *names))
+ {
+ Namval_t *mp;
+ if(val= strchr(name,'?'))
+ *val = 0;
+ if(flags&C_FLAG)
+ oflags |= NV_ARRAY;
+ np = nv_open(name,shp->var_tree,oflags);
+ if(np && nv_isarray(np) && (mp=nv_opensub(np)))
+ np = mp;
+ if((flags&V_FLAG) && shp->gd->ed_context)
+ ((struct edit*)shp->gd->ed_context)->e_default = np;
+ if(flags&A_FLAG)
+ {
+ flags &= ~A_FLAG;
+ array_index = 1;
+ nv_unset(np);
+ nv_putsub(np,NIL(char*),0L);
+ }
+ else if(flags&C_FLAG)
+ {
+ char *sp = np->nvenv;
+ delim = -1;
+ nv_unset(np);
+ if(!nv_isattr(np,NV_MINIMAL))
+ np->nvenv = sp;
+ nv_setvtree(np);
+ }
+ else
+ name = *++names;
+ if(val)
+ *val = '?';
+ }
+ else
+ {
+ name = 0;
+ if(dtvnext(shp->var_tree) || shp->namespace)
+ np = nv_open(nv_name(REPLYNOD),shp->var_tree,0);
+ else
+ np = REPLYNOD;
+ }
+ keytrap = ep?ep->e_keytrap:0;
+ if(flags>>D_FLAG) /* delimiter not new-line or fixed size read */
+ {
+ if(flags&(N_FLAG|NN_FLAG))
+ size = ((unsigned)flags)>>D_FLAG;
+ else
+ delim = ((unsigned)flags)>>D_FLAG;
+ if((shp->fdstatus[fd]&IOTTY) && !keytrap)
+ tty_raw(fd,1);
+ }
+ binary = nv_isattr(np,NV_BINARY);
+ if(!binary && !(flags&(N_FLAG|NN_FLAG)))
+ {
+ Namval_t *mp;
+ /* set up state table based on IFS */
+ ifs = nv_getval(mp=sh_scoped(shp,IFSNOD));
+ if((flags&R_FLAG) && shp->ifstable['\\']==S_ESC)
+ shp->ifstable['\\'] = 0;
+ else if(!(flags&R_FLAG) && shp->ifstable['\\']==0)
+ shp->ifstable['\\'] = S_ESC;
+ if(delim>0)
+ shp->ifstable[delim] = S_NL;
+ if(delim!='\n')
+ {
+ shp->ifstable['\n'] = 0;
+ nv_putval(mp, ifs, NV_RDONLY);
+ }
+ shp->ifstable[0] = S_EOF;
+ if((flags&SS_FLAG))
+ {
+ shp->ifstable['"'] = S_QUOTE;
+ shp->ifstable['\r'] = S_ERR;
+ }
+ }
+ sfclrerr(iop);
+ for(nfp=np->nvfun; nfp; nfp = nfp->next)
+ {
+ if(nfp->disc && nfp->disc->readf)
+ {
+ Namval_t *mp = nv_open(name,shp->var_tree,oflags|NV_NOREF);
+ if((c=(*nfp->disc->readf)(mp,iop,delim,nfp))>=0)
+ return(c);
+ }
+ }
+ if(binary && !(flags&(N_FLAG|NN_FLAG)))
+ {
+ flags |= NN_FLAG;
+ size = nv_size(np);
+ }
+ was_write = (sfset(iop,SF_WRITE,0)&SF_WRITE)!=0;
+ if(fd==0)
+ was_share = (sfset(iop,SF_SHARE,shp->redir0!=2)&SF_SHARE)!=0;
+ if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
+ {
+ sh_pushcontext(shp,&buff,1);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval)
+ goto done;
+ if(timeout)
+ timeslot = (void*)sh_timeradd(timeout,0,timedout,(void*)iop);
+ }
+ if(flags&(N_FLAG|NN_FLAG))
+ {
+ char buf[256],*var=buf,*cur,*end,*up,*v;
+ /* reserved buffer */
+ if((c=size)>=sizeof(buf))
+ {
+ if(!(var = (char*)malloc(c+1)))
+ sh_exit(1);
+ end = var + c;
+ }
+ else
+ end = var + sizeof(buf) - 1;
+ up = cur = var;
+ if((sfset(iop,SF_SHARE,1)&SF_SHARE) && fd!=0)
+ was_share = 1;
+ if(size==0)
+ {
+ cp = sfreserve(iop,0,0);
+ c = 0;
+ }
+ else
+ {
+ ssize_t m;
+ int f;
+ for (;;)
+ {
+ c = size;
+ if(keytrap)
+ {
+ cp = 0;
+ f = 0;
+ m = 0;
+ while(c-->0 && (buf[m]=ed_getchar(ep,0)))
+ m++;
+ if(m>0)
+ cp = (unsigned char*)buf;
+ }
+ else
+ {
+ f = 1;
+ if(cp = sfreserve(iop,c,SF_LOCKR))
+ m = sfvalue(iop);
+ else if(flags&NN_FLAG)
+ {
+ c = size;
+ m = (cp = sfreserve(iop,c,0)) ? sfvalue(iop) : 0;
+ f = 0;
+ }
+ else
+ {
+ c = sfvalue(iop);
+ m = (cp = sfreserve(iop,c,SF_LOCKR)) ? sfvalue(iop) : 0;
+ }
+ }
+ if(m>0 && (flags&N_FLAG) && !binary && (v=memchr(cp,'\n',m)))
+ {
+ *v++ = 0;
+ m = v-(char*)cp;
+ }
+ if((c=m)>size)
+ c = size;
+ if(c>0)
+ {
+ if(c > (end-cur))
+ {
+ ssize_t cx = cur - var, ux = up - var;
+ m = (end - var) + (c - (end - cur));
+ if (var == buf)
+ {
+ v = (char*)malloc(m+1);
+ var = memcpy(v, var, cur - var);
+ }
+ else
+ var = newof(var, char, m, 1);
+ end = var + m;
+ cur = var + cx;
+ up = var + ux;
+ }
+ if(cur!=(char*)cp)
+ memcpy((void*)cur,cp,c);
+ if(f)
+ sfread(iop,cp,c);
+ cur += c;
+#if SHOPT_MULTIBYTE
+ if(!binary && mbwide())
+ {
+ int x;
+ int z;
+
+ mbinit();
+ *cur = 0;
+ x = z = 0;
+ while (up < cur && (z = mbsize(up)) > 0)
+ {
+ up += z;
+ x++;
+ }
+ if((size -= x) > 0 && (up >= cur || z < 0) && ((flags & NN_FLAG) || z < 0 || m > c))
+ continue;
+ }
+#endif
+ }
+#if SHOPT_MULTIBYTE
+ if(!binary && mbwide() && (up == var || (flags & NN_FLAG) && size))
+ cur = var;
+#endif
+ *cur = 0;
+ if(c>=size || (flags&N_FLAG) || m==0)
+ {
+ if(m)
+ sfclrerr(iop);
+ break;
+ }
+ size -= c;
+ }
+ }
+ if(timeslot)
+ timerdel(timeslot);
+ if(binary && !((size=nv_size(np)) && nv_isarray(np) && c!=size))
+ {
+ if((c==size) && np->nvalue.cp && !nv_isarray(np))
+ memcpy((char*)np->nvalue.cp,var,c);
+ else
+ {
+ Namval_t *mp;
+ if(var==buf)
+ var = memdup(var,c+1);
+ nv_putval(np,var,NV_RAW);
+ nv_setsize(np,c);
+ if(!nv_isattr(np,NV_IMPORT|NV_EXPORT) && (mp=(Namval_t*)np->nvenv))
+ nv_setsize(mp,c);
+ }
+ }
+ else
+ {
+ nv_putval(np,var,0);
+ if(var!=buf)
+ free((void*)var);
+ }
+ goto done;
+ }
+ else if(cp = (unsigned char*)sfgetr(iop,delim,0))
+ c = sfvalue(iop);
+ else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
+ {
+ c = sfvalue(iop)+1;
+ if(!sferror(iop) && sfgetc(iop) >=0)
+ errormsg(SH_DICT,ERROR_exit(1),e_overlimit,"line length");
+ }
+ if(timeslot)
+ timerdel(timeslot);
+ if((flags&S_FLAG) && !shp->gd->hist_ptr)
+ {
+ sh_histinit((void*)shp);
+ if(!shp->gd->hist_ptr)
+ flags &= ~S_FLAG;
+ }
+ if(cp)
+ {
+ cpmax = cp + c;
+#if SHOPT_CRNL
+ if(delim=='\n' && c>=2 && cpmax[-2]=='\r')
+ cpmax--;
+#endif /* SHOPT_CRNL */
+ if(*(cpmax-1) != delim)
+ *(cpmax-1) = delim;
+ if(flags&S_FLAG)
+ sfwrite(shp->gd->hist_ptr->histfp,(char*)cp,c);
+ c = shp->ifstable[*cp++];
+#if !SHOPT_MULTIBYTE
+ if(!name && (flags&R_FLAG)) /* special case single argument */
+ {
+ /* skip over leading blanks */
+ while(c==S_SPACE)
+ c = shp->ifstable[*cp++];
+ /* strip trailing delimiters */
+ if(cpmax[-1] == '\n')
+ cpmax--;
+ if(cpmax>cp)
+ {
+ while((c=shp->ifstable[*--cpmax])==S_DELIM || c==S_SPACE);
+ cpmax[1] = 0;
+ }
+ else
+ *cpmax =0;
+ if(nv_isattr(np, NV_RDONLY))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ jmpval = 1;
+ }
+ else
+ nv_putval(np,(char*)cp-1,0);
+ goto done;
+ }
+#endif /* !SHOPT_MULTIBYTE */
+ }
+ else
+ c = S_NL;
+ shp->nextprompt = 2;
+ rel= staktell();
+ /* val==0 at the start of a field */
+ val = 0;
+ del = 0;
+ while(1)
+ {
+ switch(c)
+ {
+#if SHOPT_MULTIBYTE
+ case S_MBYTE:
+ if(val==0)
+ val = (char*)(cp-1);
+ if(sh_strchr(ifs,(char*)cp-1)>=0)
+ {
+ c = mbsize((char*)cp-1);
+ if(name)
+ cp[-1] = 0;
+ if(c>1)
+ cp += (c-1);
+ c = S_DELIM;
+ }
+ else
+ c = 0;
+ continue;
+#endif /*SHOPT_MULTIBYTE */
+ case S_QUOTE:
+ c = shp->ifstable[*cp++];
+ inquote = !inquote;
+ goto skip;
+ case S_ESC:
+ /* process escape character */
+ if((c = shp->ifstable[*cp++]) == S_NL)
+ was_escape = 1;
+ else
+ c = 0;
+ skip:
+ if(val)
+ {
+ stakputs(val);
+ use_stak = 1;
+ *val = 0;
+ }
+ continue;
+
+ case S_ERR:
+ cp++;
+ case S_EOF:
+ /* check for end of buffer */
+ if(val && *val)
+ {
+ stakputs(val);
+ use_stak = 1;
+ }
+ val = 0;
+ if(cp>=cpmax)
+ {
+ c = S_NL;
+ break;
+ }
+ /* eliminate null bytes */
+ c = shp->ifstable[*cp++];
+ if(!name && val && (c==S_SPACE||c==S_DELIM||c==S_MBYTE))
+ c = 0;
+ continue;
+ case S_NL:
+ if(was_escape)
+ {
+ was_escape = 0;
+ if(cp = (unsigned char*)sfgetr(iop,delim,0))
+ c = sfvalue(iop);
+ else if(cp=(unsigned char*)sfgetr(iop,delim,-1))
+ c = sfvalue(iop)+1;
+ if(cp)
+ {
+ if(flags&S_FLAG)
+ sfwrite(shp->gd->hist_ptr->histfp,(char*)cp,c);
+ cpmax = cp + c;
+ c = shp->ifstable[*cp++];
+ val=0;
+ if(!name && (c==S_SPACE || c==S_DELIM || c==S_MBYTE))
+ c = 0;
+ continue;
+ }
+ }
+ c = S_NL;
+ break;
+
+ case S_SPACE:
+ /* skip over blanks */
+ while((c=shp->ifstable[*cp++])==S_SPACE);
+ if(!val)
+ continue;
+#if SHOPT_MULTIBYTE
+ if(c==S_MBYTE)
+ {
+ if(sh_strchr(ifs,(char*)cp-1)>=0)
+ {
+ if((c = mbsize((char*)cp-1))>1)
+ cp += (c-1);
+ c = S_DELIM;
+ }
+ else
+ c = 0;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if(c!=S_DELIM)
+ break;
+ /* FALL THRU */
+
+ case S_DELIM:
+ if(!del)
+ del = cp - 1;
+ if(name)
+ {
+ /* skip over trailing blanks */
+ while((c=shp->ifstable[*cp++])==S_SPACE);
+ break;
+ }
+ /* FALL THRU */
+
+ case 0:
+ if(val==0 || was_escape)
+ {
+ val = (char*)(cp-1);
+ was_escape = 0;
+ }
+ /* skip over word characters */
+ wrd = -1;
+ while(1)
+ {
+ while((c=shp->ifstable[*cp++])==0)
+ if(!wrd)
+ wrd = 1;
+ if(inquote)
+ {
+ if(c==S_QUOTE)
+ {
+ if(shp->ifstable[*cp]==S_QUOTE)
+ {
+ if(val)
+ {
+ stakwrite(val,cp-(unsigned char*)val);
+ use_stak = 1;
+ }
+ val = (char*)++cp;
+ }
+ else
+ break;
+ }
+ if(c && c!=S_EOF)
+ {
+ if(c==S_NL)
+ {
+ if(val)
+ {
+ stakwrite(val,cp-(unsigned char*)val);
+ use_stak=1;
+ }
+ if(cp = (unsigned char*)sfgetr(iop,delim,0))
+ c = sfvalue(iop);
+ else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
+ c = sfvalue(iop)+1;
+ val = (char*)cp;
+ }
+ continue;
+ }
+ }
+ if(!del&&c==S_DELIM)
+ del = cp - 1;
+ if(name || c==S_NL || c==S_ESC || c==S_EOF || c==S_MBYTE)
+ break;
+ if(wrd<0)
+ wrd = 0;
+ }
+ if(wrd>0)
+ del = (unsigned char*)"";
+ if(c!=S_MBYTE)
+ cp[-1] = 0;
+ continue;
+ }
+ /* assign value and advance to next variable */
+ if(!val)
+ val = "";
+ if(use_stak)
+ {
+ stakputs(val);
+ stakputc(0);
+ val = stakptr(rel);
+ }
+ if(!name && *val)
+ {
+ /* strip off trailing space delimiters */
+ register unsigned char *vp = (unsigned char*)val + strlen(val);
+ while(shp->ifstable[*--vp]==S_SPACE);
+ if(vp==del)
+ {
+ if(vp==(unsigned char*)val)
+ vp--;
+ else
+ while(shp->ifstable[*--vp]==S_SPACE);
+ }
+ vp[1] = 0;
+ }
+ if(nv_isattr(np, NV_RDONLY))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ jmpval = 1;
+ }
+ else
+ nv_putval(np,val,0);
+ val = 0;
+ del = 0;
+ if(use_stak)
+ {
+ stakseek(rel);
+ use_stak = 0;
+ }
+ if(array_index)
+ {
+ nv_putsub(np, NIL(char*), array_index++);
+ if(c!=S_NL)
+ continue;
+ name = *++names;
+ }
+ while(1)
+ {
+ if(sh_isoption(SH_ALLEXPORT)&&!strchr(nv_name(np),'.') && !nv_isattr(np,NV_EXPORT))
+ {
+ nv_onattr(np,NV_EXPORT);
+ sh_envput(shp->env,np);
+ }
+ if(name)
+ {
+ nv_close(np);
+ np = nv_open(name,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
+ name = *++names;
+ }
+ else
+ np = 0;
+ if(c!=S_NL)
+ break;
+ if(!np)
+ goto done;
+ if(nv_isattr(np, NV_RDONLY))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ jmpval = 1;
+ }
+ else
+ nv_putval(np, "", 0);
+ }
+ }
+done:
+ if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
+ sh_popcontext(shp,&buff);
+ if(was_write)
+ sfset(iop,SF_WRITE,1);
+ if(!was_share)
+ sfset(iop,SF_SHARE,0);
+ nv_close(np);
+ if((shp->fdstatus[fd]&IOTTY) && !keytrap)
+ tty_cooked(fd);
+ if(flags&S_FLAG)
+ hist_flush(shp->gd->hist_ptr);
+ if(jmpval > 1)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(jmpval);
+}
+
diff --git a/src/cmd/ksh93/bltins/regress.c b/src/cmd/ksh93/bltins/regress.c
new file mode 100644
index 0000000..25f3c25
--- /dev/null
+++ b/src/cmd/ksh93/bltins/regress.c
@@ -0,0 +1,343 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * regression test intercept control
+ * enable with SHOPT_REGRESS==1 in Makefile
+ * not for production use
+ * see --man for details
+ * all string constants inline here instead of in data/...
+ *
+ * David Korn
+ * at&t research
+ */
+
+#include "defs.h"
+
+#if SHOPT_REGRESS
+
+#include <error.h>
+#include <ls.h>
+#include "io.h"
+#include "builtins.h"
+#include <tmx.h>
+
+#define REGRESS_HEADER "ksh:REGRESS:"
+
+#define TRACE(r,i,f) sh_regress(REGRESS_##r, i, sfprints f, __LINE__, __FILE__)
+
+static const char usage[] =
+"[-1p0?\n@(#)$Id: __regress__ (AT&T Research) 2009-03-29 $\n]"
+USAGE_LICENSE
+"[+NAME?__regress__ - shell regression test intercept control]"
+"[+DESCRIPTION?\b__regress__\b controls the regression test intercepts "
+ "for shells compiled with SHOPT_REGRESS==1. Shells compiled this way are "
+ "for testing only. In addition to \b__regress__\b and the \b--regress\b "
+ "command line option, these shells may contain system library function "
+ "intercepts that behave different from the native counterparts.]"
+"[+?Each option controls a different test and possibly a different set "
+ "of intercepts. The options are interpreted \bdd\b(1) style -- '-' or "
+ "'--' prefix not required. This simplifies the specification of the "
+ "command line \b--regress\b=\avalue\a option, where \avalue\a is passed "
+ "as an option to the \b__regress__\b builtin. Typically regression test "
+ "intercepts are enabled with one or more command line \b--regress\b "
+ "options, with optional specific calls to \b__regress__\b in test "
+ "scripts to enable/disable intercepts as the test progresses.]"
+"[+?Each enabled intercept may result in trace lines of the form \b" REGRESS_HEADER
+ "\aoption\a:\aintercept\a:\ainfo\a on the standard error, where "
+ "\aoption\a is one of the options below, \aintercept\a is the name of "
+ "the specific intercept for \aoption\a, and \ainfo\a is \aoption\a "
+ "specific information. Unless noted otherwise, one regression test trace "
+ "line is produced each time an enabled intercept is called.]"
+"[101:egid?The intercept effective gid is set to \aoriginal-egid\a. The "
+ "effective gid of the underlying system process is not affected. The "
+ "trace line info is either \begid==rgid\b or \begid!=rgid\b. The "
+ "intercepts are:]#?[original-egid:=1]"
+ "{"
+ "[+getegid()?The intercept effecive gid is returned. The "
+ "\bsetgid\b() intercept may change this between the real gid and "
+ "\aoriginal-egid\a.]"
+ "[+setgid(gid)?Sets the intercept effective gid to \agid\a. "
+ "Fails if \agid\a is neither the real gid nor "
+ "\aoriginal-egid\a.]"
+ "}"
+"[102:euid?The intercept effective uid is set to \aoriginal-euid\a. The "
+ "effective uid of the underlying system process is not affected. The "
+ "trace line info is either \beuid==ruid\b or \beuid!=ruid\b. The "
+ "intercepts are:]#?[original-euid:=1]"
+ "{"
+ "[+geteuid()?The intercept effecive uid is returned. The "
+ "\bsetuid\b() intercept may change this between the real uid and "
+ "\aoriginal-euid\a.]"
+ "[+setuid(uid)?Sets the intercept effective uid to \auid\a. "
+ "Fails if \auid\a is neither the real uid nor "
+ "\aoriginal-euid\a.]"
+ "}"
+"[103:p_suid?Specifies a value for SHOPT_P_SUID. Effective uids greater "
+ "than the non-privileged-uid disable the priveleged mode. The intercepts "
+ "are:]#?[non-privileged-uid:=1]"
+ "{"
+ "[+SHOPT_P_SUID?The SHOPT_P_SUID macro value is overridden by "
+ "\bp_suid\b. A trace line is output for each SHOPT_P_SUID "
+ "access.]"
+ "}"
+"[104:source?The intercepts are:]"
+ "{"
+ "[+sh_source()?The trace line info is the path of the script "
+ "being sourced. Used to trace shell startup scripts.]"
+ "}"
+"[105:etc?Map file paths matching \b/etc/\b* to \aetc-dir\a/*. The "
+ "intercepts are:]:[etc-dir:=/etc]"
+ "{"
+ "[+sh_open()?Paths matching \b/etc/\b* are changed to "
+ "\aetc-dir\a/*.]"
+ "}"
+"[+SEE ALSO?\bksh\b(1), \bregress\b(1), \brt\b(1)]"
+;
+
+static const char* regress_options[] =
+{
+ "ERROR",
+ "egid",
+ "euid",
+ "p_suid",
+ "source",
+ "etc",
+};
+
+void sh_regress_init(Shell_t* shp)
+{
+ static Regress_t state;
+
+ shp->regress = &state;
+}
+
+/*
+ * regress info trace output
+ */
+
+void sh_regress(unsigned int index, const char* intercept, const char* info, unsigned int line, const char* file)
+{
+ char* name;
+ char buf[16];
+
+ if (index >= 1 && index <= elementsof(regress_options))
+ name = (char*)regress_options[index];
+ else
+ sfsprintf(name = buf, sizeof(buf), "%u", index);
+ sfprintf(sfstderr, REGRESS_HEADER "%s:%s:%s\n", name, intercept, fmtesc(info));
+}
+
+/*
+ * egid intercepts
+ */
+
+static gid_t intercept_sgid = 0;
+static gid_t intercept_egid = -1;
+static gid_t intercept_rgid = -1;
+
+gid_t getegid(void)
+{
+ if (intercept_rgid == -1)
+ intercept_rgid = getgid();
+ if (sh_isregress(REGRESS_egid))
+ {
+ TRACE(egid, "getegid", ("%s", intercept_egid == intercept_rgid ? "egid==rgid" : "egid!=rgid"));
+ return intercept_egid;
+ }
+ return intercept_rgid;
+}
+
+int setgid(gid_t gid)
+{
+ if (intercept_rgid == -1)
+ intercept_rgid = getgid();
+ if (sh_isregress(REGRESS_egid))
+ {
+ if (gid != intercept_rgid && gid != intercept_sgid)
+ {
+ TRACE(egid, "setgid", ("%s", "EPERM"));
+ errno = EPERM;
+ return -1;
+ }
+ intercept_egid = gid;
+ TRACE(egid, "setgid", ("%s", intercept_egid == intercept_rgid ? "egid==rgid" : "egid!=rgid"));
+ }
+ else if (gid != intercept_rgid)
+ {
+ errno = EPERM;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * euid intercepts
+ */
+
+static uid_t intercept_suid = 0;
+static uid_t intercept_euid = -1;
+static uid_t intercept_ruid = -1;
+
+uid_t geteuid(void)
+{
+ if (intercept_ruid == -1)
+ intercept_ruid = getuid();
+ if (sh_isregress(REGRESS_euid))
+ {
+ TRACE(euid, "geteuid", ("%s", intercept_euid == intercept_ruid ? "euid==ruid" : "euid!=ruid"));
+ return intercept_euid;
+ }
+ return intercept_ruid;
+}
+
+int setuid(uid_t uid)
+{
+ if (intercept_ruid == -1)
+ intercept_ruid = getuid();
+ if (sh_isregress(REGRESS_euid))
+ {
+ if (uid != intercept_ruid && uid != intercept_suid)
+ {
+ TRACE(euid, "setuid", ("%s", "EPERM"));
+ errno = EPERM;
+ return -1;
+ }
+ intercept_euid = uid;
+ TRACE(euid, "setuid", ("%s", intercept_euid == intercept_ruid ? "euid==ruid" : "euid!=ruid"));
+ }
+ else if (uid != intercept_ruid)
+ {
+ errno = EPERM;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * p_suid intercept
+ */
+
+static uid_t intercept_p_suid = 0x7fffffff;
+
+uid_t sh_regress_p_suid(unsigned int line, const char* file)
+{
+ REGRESS(p_suid, "SHOPT_P_SUID", ("%d", intercept_p_suid));
+ return intercept_p_suid;
+}
+
+/*
+ * p_suid intercept
+ */
+
+static char* intercept_etc = 0;
+
+char* sh_regress_etc(const char* path, unsigned int line, const char* file)
+{
+ REGRESS(etc, "sh_open", ("%s => %s%s", path, intercept_etc, path+4));
+ return intercept_etc;
+}
+
+/*
+ * __regress__ builtin
+ */
+
+int b___regress__(int argc, char** argv, Shbltin_t *context)
+{
+ register Shell_t* shp = context->shp;
+ int n;
+
+ for (;;)
+ {
+ switch (n = optget(argv, usage))
+ {
+ case '?':
+ errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ case ':':
+ errormsg(SH_DICT, 2, "%s", opt_info.arg);
+ break;
+ case 0:
+ break;
+ default:
+ if (n < -100)
+ {
+ n = -(n + 100);
+ if (opt_info.arg || opt_info.number)
+ sh_onregress(n);
+ else
+ sh_offregress(n);
+ switch (n)
+ {
+ case REGRESS_egid:
+ if (sh_isregress(n))
+ {
+ intercept_egid = intercept_sgid = (gid_t)opt_info.number;
+ TRACE(egid, argv[0], ("%d", intercept_egid));
+ }
+ else
+ TRACE(egid, argv[0], ("%s", "off"));
+ break;
+ case REGRESS_euid:
+ if (sh_isregress(n))
+ {
+ intercept_euid = intercept_suid = (uid_t)opt_info.number;
+ TRACE(euid, argv[0], ("%d", intercept_euid));
+ }
+ else
+ TRACE(euid, argv[0], ("%s", "off"));
+ break;
+ case REGRESS_p_suid:
+ if (sh_isregress(n))
+ {
+ intercept_p_suid = (uid_t)opt_info.number;
+ TRACE(p_suid, argv[0], ("%d", intercept_p_suid));
+ }
+ else
+ TRACE(p_suid, argv[0], ("%s", "off"));
+ break;
+ case REGRESS_source:
+ TRACE(source, argv[0], ("%s", sh_isregress(n) ? "on" : "off"));
+ break;
+ case REGRESS_etc:
+ if (sh_isregress(n))
+ {
+ intercept_etc = opt_info.arg;
+ TRACE(etc, argv[0], ("%s", intercept_etc));
+ }
+ else
+ TRACE(etc, argv[0], ("%s", "off"));
+ break;
+ }
+ }
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors || *(argv + opt_info.index))
+ errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NiL));
+ return 0;
+}
+
+#else
+
+NoN(regress)
+
+#endif
diff --git a/src/cmd/ksh93/bltins/sleep.c b/src/cmd/ksh93/bltins/sleep.c
new file mode 100644
index 0000000..ca9d055
--- /dev/null
+++ b/src/cmd/ksh93/bltins/sleep.c
@@ -0,0 +1,235 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * sleep delay
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#define sleep ______sleep
+#include "defs.h"
+#undef sleep
+#include <error.h>
+#include <errno.h>
+#include <tmx.h>
+#include "builtins.h"
+#include "FEATURE/time"
+#include "FEATURE/poll"
+#ifdef _NEXT_SOURCE
+# define sleep _ast_sleep
+#endif /* _NEXT_SOURCE */
+#ifdef _lib_poll_notimer
+# undef _lib_poll
+#endif /* _lib_poll_notimer */
+
+int b_sleep(register int argc,char *argv[],Shbltin_t *context)
+{
+ register char *cp;
+ register double d=0;
+ register Shell_t *shp = context->shp;
+ int sflag=0;
+ time_t tloc = 0;
+ char *last;
+ if(!(shp->sigflag[SIGALRM]&(SH_SIGFAULT|SH_SIGOFF)))
+ sh_sigtrap(SIGALRM);
+ while((argc = optget(argv,sh_optsleep))) switch(argc)
+ {
+ case 's':
+ sflag=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(cp = *argv)
+ {
+ d = strtod(cp, &last);
+ if(*last)
+ {
+ Time_t now,ns;
+ char* pp;
+ now = TMX_NOW;
+ if(*cp == 'P' || *cp == 'p')
+ ns = tmxdate(cp, &last, now);
+ else if(*last=='.' && shp->decomma && d==(unsigned long)d)
+ {
+ *(pp=last) = ',';
+ if(!strchr(cp,'.'))
+ d = strtod(cp,&last);
+ *pp = '.';
+ if(*last==0)
+ goto skip;
+ }
+ else if(*last!='.' && *last!=',')
+ {
+ if(pp = sfprints("exact %s", cp))
+ ns = tmxdate(pp, &last, now);
+ if(*last && (pp = sfprints("p%s", cp)))
+ ns = tmxdate(pp, &last, now);
+ }
+ if(*last)
+ errormsg(SH_DICT,ERROR_exit(1),e_number,*argv);
+ d = ns - now;
+ d /= TMX_RESOLUTION;
+ }
+skip:
+ if(argv[1])
+ errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
+ }
+ else if(!sflag)
+ errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
+ if(d > .10)
+ {
+ time(&tloc);
+ tloc += (time_t)(d+.5);
+ }
+ if(sflag && d==0)
+ pause();
+ else while(1)
+ {
+ time_t now;
+ errno = 0;
+ shp->lastsig=0;
+ sh_delay(d);
+ if(sflag || tloc==0 || errno!=EINTR || shp->lastsig)
+ break;
+ sh_sigcheck(shp);
+ if(tloc < (now=time(NIL(time_t*))))
+ break;
+ d = (double)(tloc-now);
+ if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
+ sh_timetraps(shp);
+ }
+ return(0);
+}
+
+static void completed(void * handle)
+{
+ char *expired = (char*)handle;
+ *expired = 1;
+}
+
+unsigned int sleep(unsigned int sec)
+{
+ Shell_t *shp = sh_getinterp();
+ pid_t newpid, curpid=getpid();
+ void *tp;
+ char expired = 0;
+ shp->lastsig = 0;
+ tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
+ do
+ {
+ if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,-1L,0)==0)
+ pause();
+ if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
+ sh_timetraps(shp);
+ if((newpid=getpid()) != curpid)
+ {
+ curpid = newpid;
+ shp->lastsig = 0;
+ shp->trapnote &= ~SH_SIGSET;
+ if(expired)
+ expired = 0;
+ else
+ timerdel(tp);
+ tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
+ }
+ }
+ while(!expired && shp->lastsig==0);
+ if(!expired)
+ timerdel(tp);
+ sh_sigcheck(shp);
+ return(0);
+}
+
+/*
+ * delay execution for time <t>
+ */
+
+void sh_delay(double t)
+{
+ register int n = (int)t;
+ Shell_t *shp = sh_getinterp();
+#ifdef _lib_poll
+ struct pollfd fd;
+ if(t<=0)
+ return;
+ else if(n > 30)
+ {
+ sleep(n);
+ t -= n;
+ }
+ if(n=(int)(1000*t))
+ {
+ if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
+ poll(&fd,0,n);
+ }
+#else
+# if defined(_lib_select) && defined(_mem_tv_usec_timeval)
+ struct timeval timeloc;
+ if(t<=0)
+ return;
+ if(n=(int)(1000*t) && shp->gd->waitevent && (*shp->gd->waitevent)(-1,(long)n,0))
+ return;
+ n = (int)t;
+ timeloc.tv_sec = n;
+ timeloc.tv_usec = 1000000*(t-(double)n);
+ select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc);
+# else
+# ifdef _lib_select
+ /* for 9th edition machines */
+ if(t<=0)
+ return;
+ if(n > 30)
+ {
+ sleep(n);
+ t -= n;
+ }
+ if(n=(int)(1000*t))
+ {
+ if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
+ select(0,(fd_set*)0,(fd_set*)0,n);
+ }
+# else
+ struct tms tt;
+ if(t<=0)
+ return;
+ sleep(n);
+ t -= n;
+ if(t)
+ {
+ clock_t begin = times(&tt);
+ if(begin==0)
+ return;
+ t *= shp->gd->lim.clk_tck;
+ n += (t+.5);
+ while((times(&tt)-begin) < n);
+ }
+# endif
+# endif
+#endif /* _lib_poll */
+}
diff --git a/src/cmd/ksh93/bltins/test.c b/src/cmd/ksh93/bltins/test.c
new file mode 100644
index 0000000..52cb7cd
--- /dev/null
+++ b/src/cmd/ksh93/bltins/test.c
@@ -0,0 +1,667 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * test expression
+ * [ expression ]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+
+#include "defs.h"
+#include <error.h>
+#include <ls.h>
+#include "io.h"
+#include "terminal.h"
+#include "test.h"
+#include "builtins.h"
+#include "FEATURE/externs"
+#include "FEATURE/poll"
+#include <tmx.h>
+
+#if !_lib_setregid
+# undef _lib_setreuid
+#endif /* _lib_setregid */
+
+#ifdef S_ISSOCK
+# if _pipe_socketpair
+# if _socketpair_shutdown_mode
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino&&((p)->st_mode&(S_IRUSR|S_IWUSR))!=(S_IRUSR|S_IWUSR))
+# else
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino)
+# endif
+# else
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino)
+# endif
+# define isasock(f,p) (test_stat(f,p)>=0&&S_ISSOCK((p)->st_mode))
+#else
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode))
+# define isasock(f,p) (0)
+#endif
+
+#define permission(a,f) (sh_access(a,f)==0)
+static time_t test_time(const char*, const char*);
+static int test_stat(const char*, struct stat*);
+static int test_mode(const char*);
+
+/* single char string compare */
+#define c_eq(a,c) (*a==c && *(a+1)==0)
+/* two character string compare */
+#define c2_eq(a,c1,c2) (*a==c1 && *(a+1)==c2 && *(a+2)==0)
+
+struct test
+{
+ Shell_t *sh;
+ int ap;
+ int ac;
+ char **av;
+};
+
+static char *nxtarg(struct test*,int);
+static int expr(struct test*,int);
+static int e3(struct test*);
+
+static int test_strmatch(Shell_t *shp,const char *str, const char *pat)
+{
+ int match[2*(MATCH_MAX+1)],n;
+ register int c, m=0;
+ register const char *cp=pat;
+ while(c = *cp++)
+ {
+ if(c=='(')
+ m++;
+ if(c=='\\' && *cp)
+ cp++;
+ }
+ if(m)
+ m++;
+ else
+ match[0] = 0;
+ if(m > elementsof(match)/2)
+ m = elementsof(match)/2;
+ n = strgrpmatch(str, pat, match, m, STR_GROUP|STR_MAXIMAL|STR_LEFT|STR_RIGHT);
+ if(m==0 && n==1)
+ match[1] = strlen(str);
+ if(n)
+ sh_setmatch(shp, str, -1, n, match, 0);
+ return(n);
+}
+
+int b_test(int argc, char *argv[],Shbltin_t *context)
+{
+ struct test tdata;
+ register char *cp = argv[0];
+ register int not;
+ tdata.sh = context->shp;
+ tdata.av = argv;
+ tdata.ap = 1;
+ if(c_eq(cp,'['))
+ {
+ cp = argv[--argc];
+ if(!c_eq(cp, ']'))
+ errormsg(SH_DICT,ERROR_exit(2),e_missing,"']'");
+ }
+ if(argc <= 1)
+ return(1);
+ cp = argv[1];
+ if(c_eq(cp,'(') && argc<=6 && c_eq(argv[argc-1],')'))
+ {
+ /* special case ( binop ) to conform with standard */
+ if(!(argc==4 && (not=sh_lookup(cp=argv[2],shtab_testops))))
+ {
+ cp = (++argv)[1];
+ argc -= 2;
+ }
+ }
+ not = c_eq(cp,'!');
+ /* posix portion for test */
+ switch(argc)
+ {
+ case 5:
+ if(!not)
+ break;
+ argv++;
+ /* fall through */
+ case 4:
+ {
+ register int op = sh_lookup(cp=argv[2],shtab_testops);
+ if(op&TEST_BINOP)
+ break;
+ if(!op)
+ {
+ if(argc==5)
+ break;
+ if(not && cp[0]=='-' && cp[2]==0)
+ return(test_unop(tdata.sh,cp[1],argv[3])!=0);
+ else if(argv[1][0]=='-' && argv[1][2]==0)
+ return(!test_unop(tdata.sh,argv[1][1],cp));
+ errormsg(SH_DICT,ERROR_exit(2),e_badop,cp);
+ }
+ return(test_binop(tdata.sh,op,argv[1],argv[3])^(argc!=5));
+ }
+ case 3:
+ if(not)
+ return(*argv[2]!=0);
+ if(cp[0] != '-' || cp[2] || cp[1]=='?')
+ {
+ if(cp[0]=='-' && (cp[1]=='-' || cp[1]=='?') &&
+ strcmp(argv[2],"--")==0)
+ {
+ char *av[3];
+ av[0] = argv[0];
+ av[1] = argv[1];
+ av[2] = 0;
+ optget(av,sh_opttest);
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ return(2);
+ }
+ break;
+ }
+ return(!test_unop(tdata.sh,cp[1],argv[2]));
+ case 2:
+ return(*cp==0);
+ }
+ tdata.ac = argc;
+ return(!expr(&tdata,0));
+}
+
+/*
+ * evaluate a test expression.
+ * flag is 0 on outer level
+ * flag is 1 when in parenthesis
+ * flag is 2 when evaluating -a
+ */
+static int expr(struct test *tp,register int flag)
+{
+ register int r;
+ register char *p;
+ r = e3(tp);
+ while(tp->ap < tp->ac)
+ {
+ p = nxtarg(tp,0);
+ /* check for -o and -a */
+ if(flag && c_eq(p,')'))
+ {
+ tp->ap--;
+ break;
+ }
+ if(*p=='-' && *(p+2)==0)
+ {
+ if(*++p == 'o')
+ {
+ if(flag==2)
+ {
+ tp->ap--;
+ break;
+ }
+ r |= expr(tp,3);
+ continue;
+ }
+ else if(*p == 'a')
+ {
+ r &= expr(tp,2);
+ continue;
+ }
+ }
+ if(flag==0)
+ break;
+ errormsg(SH_DICT,ERROR_exit(2),e_badsyntax);
+ }
+ return(r);
+}
+
+static char *nxtarg(struct test *tp,int mt)
+{
+ if(tp->ap >= tp->ac)
+ {
+ if(mt)
+ {
+ tp->ap++;
+ return(0);
+ }
+ errormsg(SH_DICT,ERROR_exit(2),e_argument);
+ }
+ return(tp->av[tp->ap++]);
+}
+
+
+static int e3(struct test *tp)
+{
+ register char *arg, *cp;
+ register int op;
+ char *binop;
+ arg=nxtarg(tp,0);
+ if(arg && c_eq(arg, '!'))
+ return(!e3(tp));
+ if(c_eq(arg, '('))
+ {
+ op = expr(tp,1);
+ cp = nxtarg(tp,0);
+ if(!cp || !c_eq(cp, ')'))
+ errormsg(SH_DICT,ERROR_exit(2),e_missing,"')'");
+ return(op);
+ }
+ cp = nxtarg(tp,1);
+ if(cp!=0 && (c_eq(cp,'=') || c2_eq(cp,'!','=')))
+ goto skip;
+ if(c2_eq(arg,'-','t'))
+ {
+ if(cp)
+ {
+ op = strtol(cp,&binop, 10);
+ return(*binop?0:tty_check(op));
+ }
+ else
+ {
+ /* test -t with no arguments */
+ tp->ap--;
+ return(tty_check(1));
+ }
+ }
+ if(*arg=='-' && arg[2]==0)
+ {
+ op = arg[1];
+ if(!cp)
+ {
+ /* for backward compatibility with new flags */
+ if(op==0 || !strchr(test_opchars+10,op))
+ return(1);
+ errormsg(SH_DICT,ERROR_exit(2),e_argument);
+ }
+ if(strchr(test_opchars,op))
+ return(test_unop(tp->sh,op,cp));
+ }
+ if(!cp)
+ {
+ tp->ap--;
+ return(*arg!=0);
+ }
+skip:
+ op = sh_lookup(binop=cp,shtab_testops);
+ if(!(op&TEST_BINOP))
+ cp = nxtarg(tp,0);
+ if(!op)
+ errormsg(SH_DICT,ERROR_exit(2),e_badop,binop);
+ if(op==TEST_AND || op==TEST_OR)
+ tp->ap--;
+ return(test_binop(tp->sh,op,arg,cp));
+}
+
+int test_unop(Shell_t *shp,register int op,register const char *arg)
+{
+ struct stat statb;
+ int f;
+ switch(op)
+ {
+ case 'r':
+ return(permission(arg, R_OK));
+ case 'w':
+ return(permission(arg, W_OK));
+ case 'x':
+ return(permission(arg, X_OK));
+ case 'V':
+#if SHOPT_FS_3D
+ {
+ register int offset = staktell();
+ if(stat(arg,&statb)<0 || !S_ISREG(statb.st_mode))
+ return(0);
+ /* add trailing / */
+ stakputs(arg);
+ stakputc('/');
+ stakputc(0);
+ arg = (const char*)stakptr(offset);
+ stakseek(offset);
+ /* FALL THRU */
+ }
+#else
+ return(0);
+#endif /* SHOPT_FS_3D */
+ case 'd':
+ return(test_stat(arg,&statb)>=0 && S_ISDIR(statb.st_mode));
+ case 'c':
+ return(test_stat(arg,&statb)>=0 && S_ISCHR(statb.st_mode));
+ case 'b':
+ return(test_stat(arg,&statb)>=0 && S_ISBLK(statb.st_mode));
+ case 'f':
+ return(test_stat(arg,&statb)>=0 && S_ISREG(statb.st_mode));
+ case 'u':
+ return(test_mode(arg)&S_ISUID);
+ case 'g':
+ return(test_mode(arg)&S_ISGID);
+ case 'k':
+#ifdef S_ISVTX
+ return(test_mode(arg)&S_ISVTX);
+#else
+ return(0);
+#endif /* S_ISVTX */
+#if SHOPT_TEST_L
+ case 'l':
+#endif
+ case 'L':
+ case 'h': /* undocumented, and hopefully will disappear */
+ if(*arg==0 || arg[strlen(arg)-1]=='/' || lstat(arg,&statb)<0)
+ return(0);
+ return(S_ISLNK(statb.st_mode));
+
+ case 'C':
+#ifdef S_ISCTG
+ return(test_stat(arg,&statb)>=0 && S_ISCTG(statb.st_mode));
+#else
+ return(0);
+#endif /* S_ISCTG */
+ case 'H':
+#ifdef S_ISCDF
+ {
+ register int offset = staktell();
+ if(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode))
+ return(1);
+ stakputs(arg);
+ stakputc('+');
+ stakputc(0);
+ arg = (const char*)stakptr(offset);
+ stakseek(offset);
+ return(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode));
+ }
+#else
+ return(0);
+#endif /* S_ISCDF */
+
+ case 'S':
+ return(isasock(arg,&statb));
+ case 'N':
+ return(test_stat(arg,&statb)>=0 && tmxgetmtime(&statb) > tmxgetatime(&statb));
+ case 'p':
+ return(isapipe(arg,&statb));
+ case 'n':
+ return(*arg != 0);
+ case 'z':
+ return(*arg == 0);
+ case 's':
+ sfsync(sfstdout);
+ case 'O':
+ case 'G':
+ if(*arg==0 || test_stat(arg,&statb)<0)
+ return(0);
+ if(op=='s')
+ return(statb.st_size>0);
+ else if(op=='O')
+ return(statb.st_uid==shp->gd->userid);
+ return(statb.st_gid==shp->gd->groupid);
+ case 'a':
+ case 'e':
+ if(memcmp(arg,"/dev/",5)==0 && sh_open(arg,O_NONBLOCK))
+ return(1);
+ return(permission(arg, F_OK));
+ case 'o':
+ f=1;
+ if(*arg=='?')
+ return(sh_lookopt(arg+1,&f)>0);
+ op = sh_lookopt(arg,&f);
+ return(op && (f==(sh_isoption(op)!=0)));
+ case 't':
+ {
+ char *last;
+ op = strtol(arg,&last, 10);
+ return(*last?0:tty_check(op));
+ }
+ case 'v':
+ case 'R':
+ {
+ Namval_t *np;
+ Namarr_t *ap;
+ int isref;
+ if(!(np = nv_open(arg,shp->var_tree,NV_VARNAME|NV_NOFAIL|NV_NOADD|NV_NOREF)))
+ return(0);
+ isref = nv_isref(np);
+ if(op=='R')
+ return(isref);
+ if(isref)
+ {
+ if(np->nvalue.cp)
+ np = nv_refnode(np);
+ else
+ return(0);
+
+ }
+ if(ap = nv_arrayptr(np))
+ return(nv_arrayisset(np,ap));
+ return(!nv_isnull(np) || nv_isattr(np,NV_INTEGER));
+ }
+ default:
+ {
+ static char a[3] = "-?";
+ a[1]= op;
+ errormsg(SH_DICT,ERROR_exit(2),e_badop,a);
+ /* NOTREACHED */
+ return(0);
+ }
+ }
+}
+
+int test_binop(Shell_t *shp,register int op,const char *left,const char *right)
+{
+ register double lnum,rnum;
+ if(op&TEST_ARITH)
+ {
+ while(*left=='0')
+ left++;
+ while(*right=='0')
+ right++;
+ lnum = sh_arith(shp,left);
+ rnum = sh_arith(shp,right);
+ }
+ switch(op)
+ {
+ /* op must be one of the following values */
+ case TEST_AND:
+ case TEST_OR:
+ return(*left!=0);
+ case TEST_PEQ:
+ return(test_strmatch(shp, left, right));
+ case TEST_PNE:
+ return(!test_strmatch(shp, left, right));
+ case TEST_SGT:
+ return(strcoll(left, right)>0);
+ case TEST_SLT:
+ return(strcoll(left, right)<0);
+ case TEST_SEQ:
+ return(strcmp(left, right)==0);
+ case TEST_SNE:
+ return(strcmp(left, right)!=0);
+ case TEST_EF:
+ return(test_inode(left,right));
+ case TEST_NT:
+ return(test_time(left,right)>0);
+ case TEST_OT:
+ return(test_time(left,right)<0);
+ case TEST_EQ:
+ return(lnum==rnum);
+ case TEST_NE:
+ return(lnum!=rnum);
+ case TEST_GT:
+ return(lnum>rnum);
+ case TEST_LT:
+ return(lnum<rnum);
+ case TEST_GE:
+ return(lnum>=rnum);
+ case TEST_LE:
+ return(lnum<=rnum);
+ }
+ /* NOTREACHED */
+ return(0);
+}
+
+/*
+ * returns the modification time of f1 - modification time of f2
+ */
+
+static time_t test_time(const char *file1,const char *file2)
+{
+ Time_t t1, t2;
+ struct stat statb1,statb2;
+ int r=test_stat(file2,&statb2);
+ if(test_stat(file1,&statb1)<0)
+ return(r<0?0:-1);
+ if(r<0)
+ return(1);
+ t1 = tmxgetmtime(&statb1);
+ t2 = tmxgetmtime(&statb2);
+ if (t1 > t2)
+ return(1);
+ if (t1 < t2)
+ return(-1);
+ return(0);
+}
+
+/*
+ * return true if inode of two files are the same
+ */
+
+int test_inode(const char *file1,const char *file2)
+{
+ struct stat stat1,stat2;
+ if(test_stat(file1,&stat1)>=0 && test_stat(file2,&stat2)>=0)
+ if(stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino)
+ return(1);
+ return(0);
+}
+
+
+/*
+ * This version of access checks against effective uid/gid
+ * The static buffer statb is shared with test_mode.
+ */
+
+int sh_access(register const char *name, register int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ struct stat statb;
+ if(*name==0)
+ return(-1);
+ if(sh_isdevfd(name))
+ return(sh_ioaccess((int)strtol(name+8, (char**)0, 10),mode));
+ /* can't use access function for execute permission with root */
+ if(mode==X_OK && shp->gd->euserid==0)
+ goto skip;
+ if(shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid)
+ return(access(name,mode));
+#ifdef _lib_setreuid
+ /* swap the real uid to effective, check access then restore */
+ /* first swap real and effective gid, if different */
+ if(shp->gd->groupid==shp->gd->euserid || setregid(shp->gd->egroupid,shp->gd->groupid)==0)
+ {
+ /* next swap real and effective uid, if needed */
+ if(shp->gd->userid==shp->gd->euserid || setreuid(shp->gd->euserid,shp->gd->userid)==0)
+ {
+ mode = access(name,mode);
+ /* restore ids */
+ if(shp->gd->userid!=shp->gd->euserid)
+ setreuid(shp->gd->userid,shp->gd->euserid);
+ if(shp->gd->groupid!=shp->gd->egroupid)
+ setregid(shp->gd->groupid,shp->gd->egroupid);
+ return(mode);
+ }
+ else if(shp->gd->groupid!=shp->gd->egroupid)
+ setregid(shp->gd->groupid,shp->gd->egroupid);
+ }
+#endif /* _lib_setreuid */
+skip:
+ if(test_stat(name, &statb) == 0)
+ {
+ if(mode == F_OK)
+ return(mode);
+ else if(shp->gd->euserid == 0)
+ {
+ if(!S_ISREG(statb.st_mode) || mode!=X_OK)
+ return(0);
+ /* root needs execute permission for someone */
+ mode = (S_IXUSR|S_IXGRP|S_IXOTH);
+ }
+ else if(shp->gd->euserid == statb.st_uid)
+ mode <<= 6;
+ else if(shp->gd->egroupid == statb.st_gid)
+ mode <<= 3;
+#ifdef _lib_getgroups
+ /* on some systems you can be in several groups */
+ else
+ {
+ static int maxgroups;
+ gid_t *groups;
+ register int n;
+ if(maxgroups==0)
+ {
+ /* first time */
+ if((maxgroups=getgroups(0,(gid_t*)0)) <= 0)
+ {
+ /* pre-POSIX system */
+ maxgroups=NGROUPS_MAX;
+ }
+ }
+ groups = (gid_t*)stakalloc((maxgroups+1)*sizeof(gid_t));
+ n = getgroups(maxgroups,groups);
+ while(--n >= 0)
+ {
+ if(groups[n] == statb.st_gid)
+ {
+ mode <<= 3;
+ break;
+ }
+ }
+ }
+# endif /* _lib_getgroups */
+ if(statb.st_mode & mode)
+ return(0);
+ }
+ return(-1);
+}
+
+/*
+ * Return the mode bits of file <file>
+ * If <file> is null, then the previous stat buffer is used.
+ * The mode bits are zero if the file doesn't exist.
+ */
+
+static int test_mode(register const char *file)
+{
+ struct stat statb;
+ statb.st_mode = 0;
+ if(file && (*file==0 || test_stat(file,&statb)<0))
+ return(0);
+ return(statb.st_mode);
+}
+
+/*
+ * do an fstat() for /dev/fd/n, otherwise stat()
+ */
+static int test_stat(const char *name,struct stat *buff)
+{
+ if(*name==0)
+ {
+ errno = ENOENT;
+ return(-1);
+ }
+ if(sh_isdevfd(name))
+ return(fstat((int)strtol(name+8, (char**)0, 10),buff));
+ else
+ return(stat(name,buff));
+}
diff --git a/src/cmd/ksh93/bltins/trap.c b/src/cmd/ksh93/bltins/trap.c
new file mode 100644
index 0000000..f5dbedc
--- /dev/null
+++ b/src/cmd/ksh93/bltins/trap.c
@@ -0,0 +1,420 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * trap [-p] action sig...
+ * kill [-l] [sig...]
+ * kill [-s sig] pid...
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include "defs.h"
+#include "jobs.h"
+#include "builtins.h"
+
+#define L_FLAG 1
+#define S_FLAG 2
+
+static const char trapfmt[] = "trap -- %s %s\n";
+
+static int sig_number(Shell_t*,const char*);
+static void sig_list(Shell_t*,int);
+
+int b_trap(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *arg = argv[1];
+ register int sig, clear = 0, dflag = 0, pflag = 0;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (sig = optget(argv, sh_opttrap)) switch (sig)
+ {
+ case 'p':
+ pflag=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
+ if(arg = *argv)
+ {
+ char *action = arg;
+ if(!dflag && !pflag)
+ {
+ /* first argument all digits or - means clear */
+ while(isdigit(*arg))
+ arg++;
+ clear = (arg!=action && *arg==0);
+ if(!clear)
+ {
+ ++argv;
+ if(*action=='-' && action[1]==0)
+ clear++;
+ /*
+ * NOTE: 2007-11-26: workaround for tests/signal.sh
+ * if function semantics can be worked out then it
+ * may merit a -d,--default option
+ */
+ else if(*action=='+' && action[1]==0 && shp->st.self == &shp->global)
+ {
+ clear++;
+ dflag++;
+ }
+ }
+ if(!argv[0])
+ errormsg(SH_DICT,ERROR_exit(1),e_condition);
+ }
+ while(arg = *argv++)
+ {
+ sig = sig_number(shp,arg);
+ if(sig<0)
+ {
+ errormsg(SH_DICT,2,e_trap,arg);
+ return(1);
+ }
+ /* internal traps */
+ if(sig&SH_TRAP)
+ {
+ sig &= ~SH_TRAP;
+ if(sig>SH_DEBUGTRAP)
+ {
+ errormsg(SH_DICT,2,e_trap,arg);
+ return(1);
+ }
+ if(pflag)
+ {
+ if(arg=shp->st.trap[sig])
+ sfputr(sfstdout,sh_fmtq(arg),'\n');
+ continue;
+ }
+ if(shp->st.trap[sig])
+ free(shp->st.trap[sig]);
+ shp->st.trap[sig] = 0;
+ if(!clear && *action)
+ shp->st.trap[sig] = strdup(action);
+ if(sig == SH_DEBUGTRAP)
+ {
+ if(shp->st.trap[sig])
+ shp->trapnote |= SH_SIGTRAP;
+ else
+ shp->trapnote = 0;
+ }
+ continue;
+ }
+ if(sig>shp->gd->sigmax)
+ {
+ errormsg(SH_DICT,2,e_trap,arg);
+ return(1);
+ }
+ else if(pflag)
+ {
+ char **trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
+ if(arg=trapcom[sig])
+ sfputr(sfstdout,arg,'\n');
+ }
+ else if(clear)
+ {
+ sh_sigclear(sig);
+ if(dflag)
+ signal(sig,SIG_DFL);
+ }
+ else
+ {
+ if(sig >= shp->st.trapmax)
+ shp->st.trapmax = sig+1;
+ arg = shp->st.trapcom[sig];
+ sh_sigtrap(sig);
+ shp->st.trapcom[sig] = (shp->sigflag[sig]&SH_SIGOFF) ? Empty : strdup(action);
+ if(arg && arg != Empty)
+ free(arg);
+ }
+ }
+ }
+ else /* print out current traps */
+ sig_list(shp,-1);
+ return(0);
+}
+
+int b_kill(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *signame;
+ register int sig=SIGTERM, flag=0, n;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while((n = optget(argv,sh_optkill))) switch(n)
+ {
+ case ':':
+ if((signame=argv[opt_info.index++]) && (sig=sig_number(shp,signame+1))>=0)
+ goto endopts;
+ opt_info.index--;
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case 'n':
+ sig = (int)opt_info.num;
+ goto endopts;
+ case 's':
+ flag |= S_FLAG;
+ signame = opt_info.arg;
+ goto endopts;
+ case 'l':
+ flag |= L_FLAG;
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+endopts:
+ argv += opt_info.index;
+ if(*argv && strcmp(*argv,"--")==0 && strcmp(*(argv-1),"--")!=0)
+ argv++;
+ if(error_info.errors || flag==(L_FLAG|S_FLAG) || (!(*argv) && !(flag&L_FLAG)))
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
+ /* just in case we send a kill -9 $$ */
+ sfsync(sfstderr);
+ if(flag&L_FLAG)
+ {
+ if(!(*argv))
+ sig_list(shp,0);
+ else while(signame = *argv++)
+ {
+ if(isdigit(*signame))
+ sig_list(shp,((int)strtol(signame, (char**)0, 10)&0177)+1);
+ else
+ {
+ if((sig=sig_number(shp,signame))<0)
+ {
+ shp->exitval = 2;
+ errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
+ }
+ sfprintf(sfstdout,"%d\n",sig);
+ }
+ }
+ return(shp->exitval);
+ }
+ if(flag&S_FLAG)
+ {
+ if((sig=sig_number(shp,signame)) < 0 || sig > shp->gd->sigmax)
+ errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
+ }
+ if(job_walk(sfstdout,job_kill,sig,argv))
+ shp->exitval = 1;
+ return(shp->exitval);
+}
+
+/*
+ * Given the name or number of a signal return the signal number
+ */
+
+static int sig_number(Shell_t *shp,const char *string)
+{
+ const Shtable_t *tp;
+ register int n,o,sig=0;
+ char *last, *name;
+ if(isdigit(*string))
+ {
+ n = strtol(string,&last,10);
+ if(*last)
+ n = -1;
+ }
+ else
+ {
+ register int c;
+ o = staktell();
+ do
+ {
+ c = *string++;
+ if(islower(c))
+ c = toupper(c);
+ stakputc(c);
+ }
+ while(c);
+ stakseek(o);
+ if(memcmp(stakptr(o),"SIG",3)==0)
+ {
+ sig = 1;
+ o += 3;
+ if(isdigit(*stakptr(o)))
+ {
+ n = strtol(stakptr(o),&last,10);
+ if(!*last)
+ return(n);
+ }
+ }
+ tp = sh_locate(stakptr(o),(const Shtable_t*)shtab_signals,sizeof(*shtab_signals));
+ n = tp->sh_number;
+ if(sig==1 && (n>=(SH_TRAP-1) && n < (1<<SH_SIGBITS)))
+ {
+ /* sig prefix cannot match internal traps */
+ n = 0;
+ tp = (Shtable_t*)((char*)tp + sizeof(*shtab_signals));
+ if(strcmp(stakptr(o),tp->sh_name)==0)
+ n = tp->sh_number;
+ }
+ if((n>>SH_SIGBITS)&SH_SIGRUNTIME)
+ n = shp->gd->sigruntime[(n&((1<<SH_SIGBITS)-1))-1];
+ else
+ {
+ n &= (1<<SH_SIGBITS)-1;
+ if(n < SH_TRAP)
+ n--;
+ }
+ if(n<0 && shp->gd->sigruntime[1] && (name=stakptr(o)) && *name++=='R' && *name++=='T')
+ {
+ if(name[0]=='M' && name[1]=='I' && name[2]=='N' && name[3]=='+')
+ {
+ if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
+ n = shp->gd->sigruntime[SH_SIGRTMIN] + sig;
+ }
+ else if(name[0]=='M' && name[1]=='A' && name[2]=='X' && name[3]=='-')
+ {
+ if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
+ n = shp->gd->sigruntime[SH_SIGRTMAX] - sig;
+ }
+ else if((sig=(int)strtol(name,&name,10)) > 0 && !*name)
+ n = shp->gd->sigruntime[SH_SIGRTMIN] + sig - 1;
+ if(n<shp->gd->sigruntime[SH_SIGRTMIN] || n>shp->gd->sigruntime[SH_SIGRTMAX])
+ n = -1;
+ }
+ }
+ return(n);
+}
+
+/*
+ * synthesize signal name for sig in buf
+ * pfx!=0 prepends SIG to default signal number
+ */
+static char* sig_name(Shell_t *shp,int sig, char* buf, int pfx)
+{
+ register int i;
+
+ i = 0;
+ if(sig>shp->gd->sigruntime[SH_SIGRTMIN] && sig<shp->gd->sigruntime[SH_SIGRTMAX])
+ {
+ buf[i++] = 'R';
+ buf[i++] = 'T';
+ buf[i++] = 'M';
+ if(sig>shp->gd->sigruntime[SH_SIGRTMIN]+(shp->gd->sigruntime[SH_SIGRTMAX]-shp->gd->sigruntime[SH_SIGRTMIN])/2)
+ {
+ buf[i++] = 'A';
+ buf[i++] = 'X';
+ buf[i++] = '-';
+ sig = shp->gd->sigruntime[SH_SIGRTMAX]-sig;
+ }
+ else
+ {
+ buf[i++] = 'I';
+ buf[i++] = 'N';
+ buf[i++] = '+';
+ sig = sig-shp->gd->sigruntime[SH_SIGRTMIN];
+ }
+ }
+ else if(pfx)
+ {
+ buf[i++] = 'S';
+ buf[i++] = 'I';
+ buf[i++] = 'G';
+ }
+ i += sfsprintf(buf+i, 8, "%d", sig);
+ buf[i] = 0;
+ return buf;
+}
+
+/*
+ * if <flag> is positive, then print signal name corresponding to <flag>
+ * if <flag> is zero, then print all signal names
+ * if <flag> is negative, then print all traps
+ */
+static void sig_list(register Shell_t *shp,register int flag)
+{
+ register const struct shtable2 *tp;
+ register int sig;
+ register char *sname;
+ char name[10];
+ const char *names[SH_TRAP];
+ const char *traps[SH_DEBUGTRAP+1];
+ tp=shtab_signals;
+ if(flag<=0)
+ {
+ /* not all signals may be defined, so initialize */
+ for(sig=shp->gd->sigmax; sig>=0; sig--)
+ names[sig] = 0;
+ for(sig=SH_DEBUGTRAP; sig>=0; sig--)
+ traps[sig] = 0;
+ }
+ for(; *tp->sh_name; tp++)
+ {
+ sig = tp->sh_number&((1<<SH_SIGBITS)-1);
+ if (((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) && (sig = shp->gd->sigruntime[sig-1]+1) == 1)
+ continue;
+ if(sig==flag)
+ {
+ sfprintf(sfstdout,"%s\n",tp->sh_name);
+ return;
+ }
+ else if(sig&SH_TRAP)
+ traps[sig&~SH_TRAP] = (char*)tp->sh_name;
+ else if(sig-- && sig < elementsof(names))
+ names[sig] = (char*)tp->sh_name;
+ }
+ if(flag > 0)
+ sfputr(sfstdout, sig_name(shp,flag-1,name,0), '\n');
+ else if(flag<0)
+ {
+ /* print the traps */
+ register char *trap,**trapcom;
+ sig = shp->st.trapmax;
+ /* use parent traps if otrapcom is set (for $(trap) */
+ trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
+ while(--sig >= 0)
+ {
+ if(!(trap=trapcom[sig]))
+ continue;
+ if(sig > shp->gd->sigmax || !(sname=(char*)names[sig]))
+ sname = sig_name(shp,sig,name,1);
+ sfprintf(sfstdout,trapfmt,sh_fmtq(trap),sname);
+ }
+ for(sig=SH_DEBUGTRAP; sig>=0; sig--)
+ {
+ if(!(trap=shp->st.trap[sig]))
+ continue;
+ sfprintf(sfstdout,trapfmt,sh_fmtq(trap),traps[sig]);
+ }
+ }
+ else
+ {
+ /* print all the signal names */
+ for(sig=1; sig <= shp->gd->sigmax; sig++)
+ {
+ if(!(sname=(char*)names[sig]))
+ sname = sig_name(shp,sig,name,1);
+ sfputr(sfstdout,sname,'\n');
+ }
+ }
+}
diff --git a/src/cmd/ksh93/bltins/typeset.c b/src/cmd/ksh93/bltins/typeset.c
new file mode 100644
index 0000000..f5618a1
--- /dev/null
+++ b/src/cmd/ksh93/bltins/typeset.c
@@ -0,0 +1,1471 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * export [-p] [arg...]
+ * readonly [-p] [arg...]
+ * typeset [options] [arg...]
+ * alias [-ptx] [arg...]
+ * unalias [arg...]
+ * builtin [-sd] [-f file] [name...]
+ * set [options] [name...]
+ * unset [-fnv] [name...]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <error.h>
+#include "path.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#include "variables.h"
+#include "FEATURE/dynamic"
+
+struct tdata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ const char *wctname;
+ Sfio_t *outfile;
+ char *prefix;
+ char *tname;
+ char *help;
+ short aflag;
+ short pflag;
+ int argnum;
+ int scanmask;
+ Dt_t *scanroot;
+ char **argnam;
+ int indent;
+ int noref;
+};
+
+
+static int print_namval(Sfio_t*, Namval_t*, int, struct tdata*);
+static void print_attribute(Namval_t*,void*);
+static void print_all(Sfio_t*, Dt_t*, struct tdata*);
+static void print_scan(Sfio_t*, int, Dt_t*, int, struct tdata*);
+static int unall(int, char**, Dt_t*, Shell_t*);
+static int setall(char**, int, Dt_t*, struct tdata*);
+static void pushname(Namval_t*,void*);
+static void(*nullscan)(Namval_t*,void*);
+
+static Namval_t *load_class(const char *name)
+{
+ errormsg(SH_DICT,ERROR_exit(1),"%s: type not loadable",name);
+ return(0);
+}
+
+/*
+ * Note export and readonly are the same
+ */
+#if 0
+ /* for the dictionary generator */
+ int b_export(int argc,char *argv[],Shbltin_t *context){}
+#endif
+int b_readonly(int argc,char *argv[],Shbltin_t *context)
+{
+ register int flag;
+ char *command = argv[0];
+ struct tdata tdata;
+ NOT_USED(argc);
+ memset((void*)&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ tdata.aflag = '-';
+ while((flag = optget(argv,*command=='e'?sh_optexport:sh_optreadonly))) switch(flag)
+ {
+ case 'p':
+ tdata.prefix = command;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
+ argv += (opt_info.index-1);
+ if(*command=='r')
+ flag = (NV_ASSIGN|NV_RDONLY|NV_VARNAME);
+#ifdef _ENV_H
+ else if(!argv[1])
+ {
+ char *cp,**env=env_get(tdata.sh->env);
+ while(cp = *env++)
+ {
+ if(tdata.prefix)
+ sfputr(sfstdout,tdata.prefix,' ');
+ sfprintf(sfstdout,"%s\n",sh_fmtq(cp));
+ }
+ return(0);
+ }
+#endif
+ else
+ {
+ flag = (NV_ASSIGN|NV_EXPORT|NV_IDENT);
+ if(!tdata.sh->prefix)
+ tdata.sh->prefix = "";
+ }
+ return(setall(argv,flag,tdata.sh->var_tree, &tdata));
+}
+
+
+int b_alias(int argc,register char *argv[],Shbltin_t *context)
+{
+ register unsigned flag = NV_NOARRAY|NV_NOSCOPE|NV_ASSIGN;
+ register Dt_t *troot;
+ register int n;
+ struct tdata tdata;
+ NOT_USED(argc);
+ memset((void*)&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ troot = tdata.sh->alias_tree;
+ if(*argv[0]=='h')
+ flag = NV_TAGGED;
+ if(argv[1])
+ {
+ opt_info.offset = 0;
+ opt_info.index = 1;
+ *opt_info.option = 0;
+ tdata.argnum = 0;
+ tdata.aflag = *argv[1];
+ while((n = optget(argv,sh_optalias))) switch(n)
+ {
+ case 'p':
+ tdata.prefix = argv[0];
+ break;
+ case 't':
+ flag |= NV_TAGGED;
+ break;
+ case 'x':
+ flag |= NV_EXPORT;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ argv += (opt_info.index-1);
+ if(flag&NV_TAGGED)
+ {
+ /* hacks to handle hash -r | -- */
+ if(argv[1] && argv[1][0]=='-')
+ {
+ if(argv[1][1]=='r' && argv[1][2]==0)
+ {
+ Namval_t *np = nv_search((char*)PATHNOD,tdata.sh->var_tree,HASH_BUCKET);
+ nv_putval(np,nv_getval(np),NV_RDONLY);
+ argv++;
+ if(!argv[1])
+ return(0);
+ }
+ if(argv[1][0]=='-')
+ {
+ if(argv[1][1]=='-' && argv[1][2]==0)
+ argv++;
+ else
+ errormsg(SH_DICT, ERROR_exit(1), e_option, argv[1]);
+ }
+ }
+ troot = tdata.sh->track_tree;
+ }
+ }
+ return(setall(argv,flag,troot,&tdata));
+}
+
+
+#if 0
+ /* for the dictionary generator */
+ int b_local(int argc,char *argv[],Shbltin_t *context){}
+#endif
+int b_typeset(int argc,register char *argv[],Shbltin_t *context)
+{
+ register int n, flag = NV_VARNAME|NV_ASSIGN;
+ struct tdata tdata;
+ const char *optstring = sh_opttypeset;
+ Namdecl_t *ntp = (Namdecl_t*)context->ptr;
+ Dt_t *troot;
+ int isfloat=0, shortint=0, sflag=0;
+ NOT_USED(argc);
+ memset((void*)&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ if(ntp)
+ {
+ tdata.tp = ntp->tp;
+ opt_info.disc = (Optdisc_t*)ntp->optinfof;
+ optstring = ntp->optstring;
+ }
+ troot = tdata.sh->var_tree;
+ while((n = optget(argv,optstring)))
+ {
+ if(tdata.aflag==0)
+ tdata.aflag = *opt_info.option;
+ switch(n)
+ {
+ case 'a':
+ flag |= NV_IARRAY;
+ if(opt_info.arg && *opt_info.arg!='[')
+ {
+ opt_info.index--;
+ goto endargs;
+ }
+ tdata.tname = opt_info.arg;
+ break;
+ case 'A':
+ flag |= NV_ARRAY;
+ break;
+ case 'C':
+ flag |= NV_COMVAR;
+ break;
+ case 'E':
+ /* The following is for ksh88 compatibility */
+ if(opt_info.offset && !strchr(argv[opt_info.index],'E'))
+ {
+ tdata.argnum = (int)opt_info.num;
+ break;
+ }
+ case 'F':
+ case 'X':
+ if(!opt_info.arg || (tdata.argnum = opt_info.num) <0)
+ tdata.argnum = (n=='X'?2*sizeof(Sfdouble_t):10);
+ isfloat = 1;
+ if(n=='E')
+ {
+ flag &= ~NV_HEXFLOAT;
+ flag |= NV_EXPNOTE;
+ }
+ else if(n=='X')
+ {
+ flag &= ~NV_EXPNOTE;
+ flag |= NV_HEXFLOAT;
+ }
+ break;
+ case 'b':
+ flag |= NV_BINARY;
+ break;
+ case 'm':
+ flag |= NV_MOVE;
+ break;
+ case 'n':
+ flag &= ~NV_VARNAME;
+ flag |= (NV_REF|NV_IDENT);
+ break;
+ case 'H':
+ flag |= NV_HOST;
+ break;
+ case 'T':
+ flag |= NV_TYPE;
+ tdata.prefix = opt_info.arg;
+ break;
+ case 'L': case 'Z': case 'R':
+ if(tdata.argnum==0)
+ tdata.argnum = (int)opt_info.num;
+ if(tdata.argnum < 0)
+ errormsg(SH_DICT,ERROR_exit(1), e_badfield, tdata.argnum);
+ if(n=='Z')
+ flag |= NV_ZFILL;
+ else
+ {
+ flag &= ~(NV_LJUST|NV_RJUST);
+ flag |= (n=='L'?NV_LJUST:NV_RJUST);
+ }
+ break;
+ case 'M':
+ if((tdata.wctname = opt_info.arg) && !nv_mapchar((Namval_t*)0,tdata.wctname))
+ errormsg(SH_DICT, ERROR_exit(1),e_unknownmap, tdata.wctname);
+ if(tdata.wctname && strcmp(tdata.wctname,e_tolower)==0)
+ flag |= NV_UTOL;
+ else
+ flag |= NV_LTOU;
+ if(!tdata.wctname)
+ flag |= NV_UTOL;
+ break;
+ case 'f':
+ flag &= ~(NV_VARNAME|NV_ASSIGN);
+ troot = tdata.sh->fun_tree;
+ break;
+ case 'i':
+ if(!opt_info.arg || (tdata.argnum = opt_info.num) <0)
+ tdata.argnum = 10;
+ flag |= NV_INTEGER;
+ break;
+ case 'l':
+ tdata.wctname = e_tolower;
+ flag |= NV_UTOL;
+ break;
+ case 'p':
+ tdata.prefix = argv[0];
+ tdata.pflag = 1;
+ flag &= ~NV_ASSIGN;
+ break;
+ case 'r':
+ flag |= NV_RDONLY;
+ break;
+#ifdef SHOPT_TYPEDEF
+ case 'S':
+ sflag=1;
+ break;
+ case 'h':
+ tdata.help = opt_info.arg;
+ break;
+#endif /*SHOPT_TYPEDEF*/
+ case 's':
+ shortint=1;
+ break;
+ case 't':
+ flag |= NV_TAGGED;
+ break;
+ case 'u':
+ tdata.wctname = e_toupper;
+ flag |= NV_LTOU;
+ break;
+ case 'x':
+ flag &= ~NV_VARNAME;
+ flag |= (NV_EXPORT|NV_IDENT);
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ opt_info.disc = 0;
+ return(2);
+ }
+ }
+endargs:
+ argv += opt_info.index;
+ opt_info.disc = 0;
+ /* handle argument of + and - specially */
+ if(*argv && argv[0][1]==0 && (*argv[0]=='+' || *argv[0]=='-'))
+ tdata.aflag = *argv[0];
+ else
+ argv--;
+ if((flag&NV_ZFILL) && !(flag&NV_LJUST))
+ flag |= NV_RJUST;
+ if((flag&NV_INTEGER) && (flag&(NV_LJUST|NV_RJUST|NV_ZFILL)))
+ error_info.errors++;
+ if((flag&NV_BINARY) && (flag&(NV_LJUST|NV_UTOL|NV_LTOU)))
+ error_info.errors++;
+ if((flag&NV_MOVE) && (flag&~(NV_MOVE|NV_VARNAME|NV_ASSIGN)))
+ error_info.errors++;
+ if((flag&NV_REF) && (flag&~(NV_REF|NV_IDENT|NV_ASSIGN)))
+ error_info.errors++;
+ if((flag&NV_TYPE) && (flag&~(NV_TYPE|NV_VARNAME|NV_ASSIGN)))
+ error_info.errors++;
+ if(troot==tdata.sh->fun_tree && ((isfloat || flag&~(NV_FUNCT|NV_TAGGED|NV_EXPORT|NV_LTOU))))
+ error_info.errors++;
+ if(sflag && troot==tdata.sh->fun_tree)
+ {
+ /* static function */
+ sflag = 0;
+ flag |= NV_STATICF;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage(NIL(char*)));
+ if(isfloat)
+ flag |= NV_DOUBLE;
+ if(shortint)
+ {
+ flag &= ~NV_LONG;
+ flag |= NV_SHORT|NV_INTEGER;
+ }
+ if(sflag)
+ {
+ if(tdata.sh->mktype)
+ flag |= NV_REF|NV_TAGGED;
+ else if(!tdata.sh->typeinit)
+ flag |= NV_STATIC|NV_IDENT;
+ }
+ if(tdata.sh->fn_depth && !tdata.pflag)
+ flag |= NV_NOSCOPE;
+ if(tdata.help)
+ tdata.help = strdup(tdata.help);
+ if(flag&NV_TYPE)
+ {
+ Stk_t *stkp = tdata.sh->stk;
+ int off=0,offset = stktell(stkp);
+ if(!tdata.prefix)
+ return(sh_outtype(tdata.sh,sfstdout));
+ sfputr(stkp,NV_CLASS,-1);
+#if SHOPT_NAMESPACE
+ if(tdata.sh->namespace)
+ {
+ off = stktell(stkp)+1;
+ sfputr(stkp,nv_name(tdata.sh->namespace),'.');
+ }
+ else
+#endif /* SHOPT_NAMESPACE */
+ if(NV_CLASS[sizeof(NV_CLASS)-2]!='.')
+ sfputc(stkp,'.');
+ sfputr(stkp,tdata.prefix,0);
+ tdata.tp = nv_open(stkptr(stkp,offset),tdata.sh->var_tree,NV_VARNAME|NV_NOARRAY|NV_NOASSIGN);
+#if SHOPT_NAMESPACE
+ if(!tdata.tp && off)
+ {
+ *stkptr(stkp,off)=0;
+ tdata.tp = nv_open(stkptr(stkp,offset),tdata.sh->var_tree,NV_VARNAME|NV_NOARRAY|NV_NOASSIGN);
+ }
+#endif /* SHOPT_NAMESPACE */
+ stkseek(stkp,offset);
+ if(!tdata.tp)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: unknown type",tdata.prefix);
+ else if(nv_isnull(tdata.tp))
+ nv_newtype(tdata.tp);
+ tdata.tp->nvenv = tdata.help;
+ flag &= ~NV_TYPE;
+ }
+ else if(tdata.aflag==0 && ntp && ntp->tp)
+ tdata.aflag = '-';
+ if(!tdata.sh->mktype)
+ tdata.help = 0;
+ if(tdata.aflag=='+' && (flag&(NV_ARRAY|NV_IARRAY|NV_COMVAR)))
+ errormsg(SH_DICT,ERROR_exit(1),e_nounattr);
+ return(setall(argv,flag,troot,&tdata));
+}
+
+static void print_value(Sfio_t *iop, Namval_t *np, struct tdata *tp)
+{
+ char *name;
+ int aflag=tp->aflag;
+ if(nv_isnull(np))
+ {
+ if(!np->nvflag)
+ return;
+ aflag = '+';
+ }
+ else if(nv_istable(np))
+ {
+ Dt_t *root = tp->sh->last_root;
+ Namval_t *nsp = tp->sh->namespace;
+ char *cp = name = nv_name(np);
+ if(*name=='.')
+ name++;
+ if(tp->indent)
+ sfnputc(iop,'\t',tp->indent);
+ sfprintf(iop,"namespace %s\n", name);
+ if(tp->indent)
+ sfnputc(iop,'\t',tp->indent);
+ sfprintf(iop,"{\n", name);
+ tp->indent++;
+ /* output types from namespace */
+ tp->sh->namespace = 0;
+ tp->sh->prefix = nv_name(np)+1;
+ sh_outtype(tp->sh,iop);
+ tp->sh->prefix = 0;
+ tp->sh->namespace = np;
+ tp->sh->last_root = root;
+ /* output variables from namespace */
+ print_scan(iop,NV_NOSCOPE,nv_dict(np),aflag=='+',tp);
+ tp->wctname = cp;
+ tp->sh->namespace = 0;
+ /* output functions from namespace */
+ print_scan(iop,NV_FUNCTION|NV_NOSCOPE,tp->sh->fun_tree,aflag=='+',tp);
+ tp->wctname = 0;
+ tp->sh->namespace = nsp;
+ if(--tp->indent)
+ sfnputc(iop,'\t',tp->indent);
+ sfwrite(iop,"}\n",2);
+ return;
+ }
+ sfputr(iop,nv_name(np),aflag=='+'?'\n':'=');
+ if(aflag=='+')
+ return;
+ if(nv_isarray(np) && nv_arrayptr(np))
+ {
+ nv_outnode(np,iop,-1,0);
+ sfwrite(iop,")\n",2);
+ }
+ else
+ {
+ if(nv_isvtree(np))
+ nv_onattr(np,NV_EXPORT);
+ if(!(name = nv_getval(np)))
+ name = Empty;
+ if(!nv_isvtree(np))
+ name = sh_fmtq(name);
+ sfputr(iop,name,'\n');
+ }
+}
+
+static int setall(char **argv,register int flag,Dt_t *troot,struct tdata *tp)
+{
+ register char *name;
+ char *last = 0;
+ int nvflags=(flag&(NV_ARRAY|NV_NOARRAY|NV_VARNAME|NV_IDENT|NV_ASSIGN|NV_STATIC|NV_MOVE));
+ int r=0, ref=0, comvar=(flag&NV_COMVAR),iarray=(flag&NV_IARRAY);
+ Shell_t *shp =tp->sh;
+ if(!shp->prefix)
+ {
+ if(!tp->pflag)
+ nvflags |= NV_NOSCOPE;
+ }
+ else if(*shp->prefix==0)
+ shp->prefix = 0;
+ if(*argv[0]=='+')
+ nvflags |= NV_NOADD;
+ flag &= ~(NV_NOARRAY|NV_NOSCOPE|NV_VARNAME|NV_IDENT|NV_STATIC|NV_COMVAR|NV_IARRAY);
+ if(argv[1])
+ {
+ if(flag&NV_REF)
+ {
+ flag &= ~NV_REF;
+ ref=1;
+ if(tp->aflag!='-')
+ nvflags |= NV_NOREF;
+ }
+ if(tp->pflag)
+ nvflags |= NV_NOREF;
+ while(name = *++argv)
+ {
+ register unsigned newflag;
+ register Namval_t *np;
+ Namarr_t *ap;
+ Namval_t *mp;
+ unsigned curflag;
+ if(troot == shp->fun_tree)
+ {
+ /*
+ *functions can be exported or
+ * traced but not set
+ */
+ flag &= ~NV_ASSIGN;
+ if(flag&NV_LTOU)
+ {
+ /* Function names cannot be special builtin */
+ if((np=nv_search(name,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC))
+ errormsg(SH_DICT,ERROR_exit(1),e_badfun,name);
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ np = sh_fsearch(shp,name,NV_ADD|HASH_NOSCOPE);
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE);
+ }
+ else
+ {
+ if(shp->prefix)
+ {
+ sfprintf(shp->strbuf,"%s.%s%c",shp->prefix,name,0);
+ name = sfstruse(shp->strbuf);
+ }
+#if SHOPT_NAMESPACE
+ np = 0;
+ if(shp->namespace)
+ np = sh_fsearch(shp,name,HASH_NOSCOPE);
+ if(!np)
+#endif /* SHOPT_NAMESPACE */
+ if(np=nv_search(name,troot,0))
+ {
+ if(!is_afunction(np))
+ np = 0;
+ }
+ else if(memcmp(name,".sh.math.",9)==0 && sh_mathstd(name+9))
+ continue;
+ }
+ if(np && ((flag&NV_LTOU) || !nv_isnull(np) || nv_isattr(np,NV_LTOU)))
+ {
+ if(flag==0 && !tp->help)
+ {
+ print_namval(sfstdout,np,tp->aflag=='+',tp);
+ continue;
+ }
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ if(tp->aflag=='-')
+ nv_onattr(np,flag|NV_FUNCTION);
+ else if(tp->aflag=='+')
+ nv_offattr(np,flag);
+ }
+ else
+ r++;
+ if(tp->help)
+ {
+ int offset = stktell(shp->stk);
+ if(!np)
+ {
+ sfputr(shp->stk,shp->prefix,'.');
+ sfputr(shp->stk,name,0);
+ np = nv_search(stkptr(shp->stk,offset),troot,0);
+ stkseek(shp->stk,offset);
+ }
+ if(np && np->nvalue.cp)
+ np->nvalue.rp->help = tp->help;
+ }
+ continue;
+ }
+ /* tracked alias */
+ if(troot==shp->track_tree && tp->aflag=='-')
+ {
+ np = nv_search(name,troot,NV_ADD);
+ path_alias(np,path_absolute(shp,nv_name(np),NIL(Pathcomp_t*)));
+ continue;
+ }
+ np = nv_open(name,troot,nvflags|((nvflags&NV_ASSIGN)?0:NV_ARRAY)|((iarray|(nvflags&NV_REF))?NV_FARRAY:0));
+ if(!np)
+ continue;
+ if(nv_isnull(np) && !nv_isarray(np) && nv_isattr(np,NV_NOFREE))
+ nv_offattr(np,NV_NOFREE);
+ else if(tp->tp && !nv_isattr(np,NV_MINIMAL|NV_EXPORT) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)) && (ap->nelem&ARRAY_TREE))
+#if 0
+ errormsg(SH_DICT,ERROR_exit(1),e_typecompat,nv_name(np));
+#else
+ errormsg(SH_DICT,ERROR_exit(1),"%s: typecompat",nv_name(np));
+#endif
+ else if((ap=nv_arrayptr(np)) && nv_aindex(np)>0 && ap->nelem==1 && nv_getval(np)==Empty)
+ {
+ ap->nelem++;
+ _nv_unset(np,0);
+ ap->nelem--;
+ }
+ if(tp->pflag)
+ {
+ if(!nv_istable(np))
+ nv_attribute(np,sfstdout,tp->prefix,1);
+ print_value(sfstdout,np,tp);
+ continue;
+ }
+ if(flag==NV_ASSIGN && !ref && tp->aflag!='-' && !strchr(name,'='))
+ {
+ if(troot!=shp->var_tree && (nv_isnull(np) || !print_namval(sfstdout,np,0,tp)))
+ {
+ sfprintf(sfstderr,sh_translate(e_noalias),name);
+ r++;
+ }
+ if(!comvar && !iarray)
+ continue;
+ }
+ if(!nv_isarray(np) && !strchr(name,'=') && !(shp->envlist && nv_onlist(shp->envlist,name)))
+ {
+ if(comvar || (shp->last_root==shp->var_tree && (tp->tp || (!shp->st.real_fun && (nvflags&NV_STATIC)) || (!(flag&(NV_EXPORT|NV_RDONLY)) && nv_isattr(np,(NV_EXPORT|NV_IMPORT))==(NV_EXPORT|NV_IMPORT)))))
+{
+ _nv_unset(np,0);
+}
+ }
+ if(troot==shp->var_tree)
+ {
+ if(iarray)
+ {
+ if(tp->tname)
+ nv_atypeindex(np,tp->tname+1);
+ else if(nv_isnull(np))
+ nv_onattr(np,NV_ARRAY|(comvar?NV_NOFREE:0));
+ else
+ {
+ if(ap && comvar)
+ ap->nelem |= ARRAY_TREE;
+ nv_putsub(np, (char*)0, 0);
+ }
+ }
+ else if(nvflags&NV_ARRAY)
+ {
+ if(comvar)
+ {
+ Namarr_t *ap=nv_arrayptr(np);
+ if(ap)
+ ap->nelem |= ARRAY_TREE;
+ else
+ {
+ _nv_unset(np,NV_RDONLY);
+ nv_onattr(np,NV_NOFREE);
+ }
+ }
+ nv_setarray(np,nv_associative);
+ }
+ else if(comvar && !nv_isvtree(np) && !nv_rename(np,flag|NV_COMVAR))
+ nv_setvtree(np);
+ }
+ if(flag&NV_MOVE)
+ {
+ nv_rename(np, flag);
+ nv_close(np);
+ continue;
+ }
+ if(tp->tp && nv_type(np)!=tp->tp)
+ {
+ nv_settype(np,tp->tp,tp->aflag=='-'?0:NV_APPEND);
+ flag = (np->nvflag&NV_NOCHANGE);
+ }
+ flag &= ~NV_ASSIGN;
+ if(last=strchr(name,'='))
+ *last = 0;
+ if (shp->typeinit)
+ continue;
+ curflag = np->nvflag;
+ if(!(flag&NV_INTEGER) && (flag&(NV_LTOU|NV_UTOL)))
+ {
+ Namfun_t *fp;
+ char *cp;
+ if(!tp->wctname)
+ errormsg(SH_DICT,ERROR_exit(1),e_mapchararg,nv_name(np));
+ cp = (char*)nv_mapchar(np,0);
+ if(fp=nv_mapchar(np,tp->wctname))
+ {
+ if(tp->aflag=='+')
+ {
+ if(cp && strcmp(cp,tp->wctname)==0)
+ {
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ nv_offattr(np,flag&(NV_LTOU|NV_UTOL));
+ }
+ }
+ else if(!cp || strcmp(cp,tp->wctname))
+ {
+ nv_disc(np,fp,NV_LAST);
+ nv_onattr(np,flag&(NV_LTOU|NV_UTOL));
+ }
+ }
+ }
+ if (tp->aflag == '-')
+ {
+ if((flag&NV_EXPORT) && (strchr(name,'.') || nv_isvtree(np)))
+ errormsg(SH_DICT,ERROR_exit(1),e_badexport,name);
+#if SHOPT_BSH
+ if(flag&NV_EXPORT)
+ nv_offattr(np,NV_IMPORT);
+#endif /* SHOPT_BSH */
+ newflag = curflag;
+ if(flag&~NV_NOCHANGE)
+ newflag &= NV_NOCHANGE;
+ newflag |= flag;
+ if (flag & (NV_LJUST|NV_RJUST))
+ {
+ if(!(flag&NV_RJUST))
+ newflag &= ~NV_RJUST;
+
+ else if(!(flag&NV_LJUST))
+ newflag &= ~NV_LJUST;
+ }
+ }
+ else
+ {
+ if((flag&NV_RDONLY) && (curflag&NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly,nv_name(np));
+ newflag = curflag & ~flag;
+ }
+ if (tp->aflag && (tp->argnum>0 || (curflag!=newflag)))
+ {
+ if(shp->subshell)
+ sh_assignok(np,1);
+ if(troot!=shp->var_tree)
+ nv_setattr(np,newflag&~NV_ASSIGN);
+ else
+ {
+ char *oldname=0;
+ int len=strlen(name);
+ if(tp->argnum==1 && newflag==NV_INTEGER && nv_isattr(np,NV_INTEGER))
+ tp->argnum = 10;
+ /* use reference name for export */
+ if((newflag^curflag)&NV_EXPORT)
+ {
+ oldname = np->nvname;
+ np->nvname = name;
+ }
+ if(np->nvfun && !nv_isarray(np) && name[len-1]=='.')
+ newflag |= NV_NODISC;
+ nv_newattr (np, newflag&~NV_ASSIGN,tp->argnum);
+ if(oldname)
+ np->nvname = oldname;
+ }
+ }
+ if(tp->help && !nv_isattr(np,NV_MINIMAL|NV_EXPORT))
+ {
+ np->nvenv = tp->help;
+ nv_onattr(np,NV_EXPORT);
+ }
+ if(last)
+ *last = '=';
+ /* set or unset references */
+ if(ref)
+ {
+ if(tp->aflag=='-')
+ {
+ Dt_t *hp=0;
+ if(nv_isattr(np,NV_PARAM) && shp->st.prevst)
+ {
+ if(!(hp=(Dt_t*)shp->st.prevst->save_tree))
+ hp = dtvnext(shp->var_tree);
+ }
+ if(tp->sh->mktype)
+ nv_onattr(np,NV_REF|NV_FUNCT);
+ else
+ nv_setref(np,hp,NV_VARNAME);
+ }
+ else
+ nv_unref(np);
+ }
+ nv_close(np);
+ }
+ }
+ else
+ {
+ if(shp->prefix)
+ errormsg(SH_DICT,2, e_subcomvar,shp->prefix);
+ if(tp->aflag)
+ {
+ if(troot==shp->fun_tree)
+ {
+ flag |= NV_FUNCTION;
+ tp->prefix = 0;
+ }
+ else if(troot==shp->var_tree)
+ {
+ flag |= (nvflags&NV_ARRAY);
+ if(flag&NV_IARRAY)
+ flag |= NV_ARRAY;
+ if(!(flag&~NV_ASSIGN))
+ tp->noref = 1;
+ }
+ if((flag&(NV_UTOL|NV_LTOU)) ==(NV_UTOL|NV_LTOU))
+ {
+ print_scan(sfstdout,flag&~NV_UTOL,troot,tp->aflag=='+',tp);
+ flag &= ~NV_LTOU;
+ }
+ print_scan(sfstdout,flag,troot,tp->aflag=='+',tp);
+ if(tp->noref)
+ {
+ tp->noref = 0;
+ print_scan(sfstdout,flag|NV_REF,troot,tp->aflag=='+',tp);
+ }
+ }
+ else if(troot==shp->alias_tree)
+ print_scan(sfstdout,0,troot,0,tp);
+ else
+ print_all(sfstdout,troot,tp);
+ sfsync(sfstdout);
+ }
+ return(r);
+}
+
+typedef void (*Iptr_t)(int,void*);
+
+#define GROWLIB 4
+
+static void **liblist;
+static unsigned short *libattr;
+static int nlib;
+static int maxlib;
+
+/*
+ * This allows external routines to load from the same library */
+void **sh_getliblist(void)
+{
+ return(liblist);
+}
+
+/*
+ * add library to loaded list
+ * call (*lib_init)() on first load if defined
+ * always move to head of search list
+ * return: 0: already loaded 1: first load
+ */
+#if SHOPT_DYNAMIC
+int sh_addlib(Shell_t *shp,void* library)
+{
+ register int n;
+ register int r;
+ Iptr_t initfn;
+ Shbltin_t *sp = &shp->bltindata;
+
+ sp->nosfio = 0;
+ for (n = r = 0; n < nlib; n++)
+ {
+ if (r)
+ {
+ liblist[n-1] = liblist[n];
+ libattr[n-1] = libattr[n];
+ }
+ else if (liblist[n] == library)
+ r++;
+ }
+ if (r)
+ nlib--;
+ else if ((initfn = (Iptr_t)dlllook(library, "lib_init")))
+ (*initfn)(0,sp);
+ if (nlib >= maxlib)
+ {
+ maxlib += GROWLIB;
+ if (liblist)
+ {
+ liblist = (void**)realloc((void*)liblist, (maxlib+1)*sizeof(void*));
+ libattr = (unsigned short*)realloc((void*)libattr, (maxlib+1)*sizeof(unsigned short));
+ }
+ else
+ {
+ liblist = (void**)malloc((maxlib+1)*sizeof(void*));
+ libattr = (unsigned short*)malloc((maxlib+1)*sizeof(unsigned short));
+ }
+ }
+ libattr[nlib] = (sp->nosfio?BLT_NOSFIO:0);
+ liblist[nlib++] = library;
+ liblist[nlib] = 0;
+ return !r;
+}
+#else
+int sh_addlib(Shell_t *shp,void* library)
+{
+ return 0;
+}
+#endif /* SHOPT_DYNAMIC */
+
+/*
+ * add change or list built-ins
+ * adding builtins requires dlopen() interface
+ */
+int b_builtin(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *arg=0, *name;
+ register int n, r=0, flag=0;
+ register Namval_t *np;
+ long dlete=0;
+ struct tdata tdata;
+ Shbltin_f addr;
+ Stk_t *stkp;
+ void *library=0;
+ char *errmsg;
+#ifdef SH_PLUGIN_VERSION
+ unsigned long ver;
+ int list = 0;
+ char path[1024];
+#endif
+ NOT_USED(argc);
+ memset(&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ stkp = tdata.sh->stk;
+ if(!tdata.sh->pathlist)
+ path_absolute(tdata.sh,argv[0],NIL(Pathcomp_t*));
+ while (n = optget(argv,sh_optbuiltin)) switch (n)
+ {
+ case 's':
+ flag = BLT_SPC;
+ break;
+ case 'd':
+ dlete=1;
+ break;
+ case 'f':
+#if SHOPT_DYNAMIC
+ arg = opt_info.arg;
+#else
+ errormsg(SH_DICT,2, "adding built-ins not supported");
+ error_info.errors++;
+#endif /* SHOPT_DYNAMIC */
+ break;
+ case 'l':
+#ifdef SH_PLUGIN_VERSION
+ list = 1;
+#endif
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage(NIL(char*)));
+ if(arg || *argv)
+ {
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,argv[-opt_info.index]);
+ if(sh_isoption(SH_PFSH))
+ errormsg(SH_DICT,ERROR_exit(1),e_pfsh,argv[-opt_info.index]);
+ if(tdata.sh->subshell && !tdata.sh->subshare)
+ sh_subfork();
+ }
+#if SHOPT_DYNAMIC
+ if(arg)
+ {
+#ifdef SH_PLUGIN_VERSION
+ if(!(library = dllplugin(SH_ID, arg, NiL, SH_PLUGIN_VERSION, &ver, RTLD_LAZY, path, sizeof(path))))
+ {
+ errormsg(SH_DICT,ERROR_exit(0),"%s: %s",arg,dllerror(0));
+ return(1);
+ }
+ if(list)
+ sfprintf(sfstdout, "%s %08lu %s\n", arg, ver, path);
+#else
+#if (_AST_VERSION>=20040404)
+ if(!(library = dllplug(SH_ID,arg,NIL(char*),RTLD_LAZY,NIL(char*),0)))
+#else
+ if(!(library = dllfind(arg,NIL(char*),RTLD_LAZY,NIL(char*),0)))
+#endif
+ {
+ errormsg(SH_DICT,ERROR_exit(0),"%s: %s",arg,dlerror());
+ return(1);
+ }
+#endif
+ sh_addlib(tdata.sh,library);
+ }
+ else
+#endif /* SHOPT_DYNAMIC */
+ if(*argv==0 && !dlete)
+ {
+ print_scan(sfstdout, flag, tdata.sh->bltin_tree, 1, &tdata);
+ return(0);
+ }
+ r = 0;
+ flag = stktell(stkp);
+ while(arg = *argv)
+ {
+ name = path_basename(arg);
+ sfwrite(stkp,"b_",2);
+ sfputr(stkp,name,0);
+ errmsg = 0;
+ addr = 0;
+ for(n=(nlib?nlib:dlete); --n>=0;)
+ {
+ /* (char*) added for some sgi-mips compilers */
+#if SHOPT_DYNAMIC
+ if(dlete || (addr = (Shbltin_f)dlllook(liblist[n],stkptr(stkp,flag))))
+#else
+ if(dlete)
+#endif /* SHOPT_DYNAMIC */
+ {
+ if(np = sh_addbuiltin(arg, addr,pointerof(dlete)))
+ {
+ if(dlete || nv_isattr(np,BLT_SPC))
+ errmsg = "restricted name";
+ else
+ nv_onattr(np,libattr[n]);
+ }
+ break;
+ }
+ }
+ if(!dlete && !addr)
+ {
+ np = sh_addbuiltin(arg, 0 ,0);
+ if(np && nv_isattr(np,BLT_SPC))
+ errmsg = "restricted name";
+ else if(!np)
+ errmsg = "not found";
+ }
+ if(errmsg)
+ {
+ errormsg(SH_DICT,ERROR_exit(0),"%s: %s",*argv,errmsg);
+ r = 1;
+ }
+ stkseek(stkp,flag);
+ argv++;
+ }
+ return(r);
+}
+
+int b_set(int argc,register char *argv[],Shbltin_t *context)
+{
+ struct tdata tdata;
+ int was_monitor = sh_isoption(SH_MONITOR);
+ memset(&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ tdata.prefix=0;
+ if(argv[1])
+ {
+ if(sh_argopts(argc,argv,tdata.sh) < 0)
+ return(2);
+ if(sh_isoption(SH_VERBOSE))
+ sh_onstate(SH_VERBOSE);
+ else
+ sh_offstate(SH_VERBOSE);
+ if(sh_isoption(SH_MONITOR) && !was_monitor)
+ sh_onstate(SH_MONITOR);
+ else if(!sh_isoption(SH_MONITOR) && was_monitor)
+ sh_offstate(SH_MONITOR);
+ }
+ else
+ /*scan name chain and print*/
+ print_scan(sfstdout,0,tdata.sh->var_tree,0,&tdata);
+ return(0);
+}
+
+/*
+ * The removing of Shell variable names, aliases, and functions
+ * is performed here.
+ * Unset functions with unset -f
+ * Non-existent items being deleted give non-zero exit status
+ */
+
+int b_unalias(int argc,register char *argv[],Shbltin_t *context)
+{
+ Shell_t *shp = context->shp;
+ return(unall(argc,argv,shp->alias_tree,shp));
+}
+
+int b_unset(int argc,register char *argv[],Shbltin_t *context)
+{
+ Shell_t *shp = context->shp;
+ return(unall(argc,argv,shp->var_tree,shp));
+}
+
+static int unall(int argc, char **argv, register Dt_t *troot, Shell_t* shp)
+{
+ register Namval_t *np;
+ register const char *name;
+ register int r;
+ Dt_t *dp;
+ int nflag=0,all=0,isfun,jmpval;
+ struct checkpt buff;
+ NOT_USED(argc);
+ if(troot==shp->alias_tree)
+ {
+ name = sh_optunalias;
+ if(shp->subshell)
+ troot = sh_subaliastree(0);
+ }
+ else
+ name = sh_optunset;
+ while(r = optget(argv,name)) switch(r)
+ {
+ case 'f':
+ troot = sh_subfuntree(1);
+ break;
+ case 'a':
+ all=1;
+ break;
+ case 'n':
+ nflag = NV_NOREF;
+ case 'v':
+ troot = shp->var_tree;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ if(error_info.errors || (*argv==0 &&!all))
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ if(!troot)
+ return(1);
+ r = 0;
+ if(troot==shp->var_tree)
+ nflag |= NV_VARNAME;
+ else
+ nflag = NV_NOSCOPE;
+ if(all)
+ {
+ dtclear(troot);
+ return(r);
+ }
+ sh_pushcontext(shp,&buff,1);
+ while(name = *argv++)
+ {
+ jmpval = sigsetjmp(buff.buff,0);
+ np = 0;
+ if(jmpval==0)
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace && troot!=shp->var_tree)
+ np = sh_fsearch(shp,name,nflag?HASH_NOSCOPE:0);
+ if(!np)
+#endif /* SHOPT_NAMESPACE */
+ np=nv_open(name,troot,NV_NOADD|nflag);
+ }
+ else
+ {
+ r = 1;
+ continue;
+ }
+ if(np)
+ {
+ if(is_abuiltin(np) || nv_isattr(np,NV_RDONLY))
+ {
+ if(nv_isattr(np,NV_RDONLY))
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ r = 1;
+ continue;
+ }
+ isfun = is_afunction(np);
+ if(troot==shp->var_tree)
+ {
+ Namarr_t *ap;
+#if SHOPT_FIXEDARRAY
+ if((ap=nv_arrayptr(np)) && !ap->fixed && name[strlen(name)-1]==']' && !nv_getsub(np))
+#else
+ if(nv_isarray(np) && name[strlen(name)-1]==']' && !nv_getsub(np))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ r=1;
+ continue;
+ }
+
+ if(shp->subshell)
+ np=sh_assignok(np,0);
+ }
+ if(!nv_isnull(np))
+ _nv_unset(np,0);
+ if(troot==shp->var_tree && shp->st.real_fun && (dp=shp->var_tree->walk) && dp==shp->st.real_fun->sdict)
+ nv_delete(np,dp,NV_NOFREE);
+ else if(isfun)
+ nv_delete(np,troot,NV_NOFREE);
+#if 0
+ /* causes unsetting local variable to expose global */
+ else if(shp->var_tree==troot && shp->var_tree!=shp->var_base && nv_search((char*)np,shp->var_tree,HASH_BUCKET|HASH_NOSCOPE))
+ nv_delete(np,shp->var_tree,0);
+#endif
+ else
+ nv_close(np);
+
+ }
+ else if(troot==shp->alias_tree)
+ r = 1;
+ }
+ sh_popcontext(shp,&buff);
+ return(r);
+}
+
+/*
+ * print out the name and value of a name-value pair <np>
+ */
+
+static int print_namval(Sfio_t *file,register Namval_t *np,register int flag, struct tdata *tp)
+{
+ register char *cp;
+ int indent=tp->indent, outname=0, isfun;
+ sh_sigcheck(tp->sh);
+ if(flag)
+ flag = '\n';
+ if(tp->noref && nv_isref(np))
+ return(0);
+ if(nv_istable(np))
+ {
+ print_value(file,np,tp);
+ return(0);
+ }
+ if(nv_isattr(np,NV_NOPRINT|NV_INTEGER)==NV_NOPRINT)
+ {
+ if(is_abuiltin(np))
+ sfputr(file,nv_name(np),'\n');
+ return(0);
+ }
+ isfun = is_afunction(np);
+ if(tp->prefix)
+ {
+ outname = (*tp->prefix=='t' && (!nv_isnull(np) || nv_isattr(np,NV_FLOAT|NV_RDONLY|NV_BINARY|NV_RJUST|NV_NOPRINT)));
+ if(indent && (isfun || outname || *tp->prefix!='t'))
+ {
+ sfnputc(file,'\t',indent);
+ indent = 0;
+ }
+ if(!isfun)
+ {
+ if(*tp->prefix=='t')
+ nv_attribute(np,tp->outfile,tp->prefix,tp->aflag);
+ else
+ sfputr(file,tp->prefix,' ');
+ }
+ }
+ if(isfun)
+ {
+ Sfio_t *iop=0;
+ char *fname=0;
+ if(nv_isattr(np,NV_NOFREE))
+ return(0);
+ if(!flag && !np->nvalue.ip)
+ sfputr(file,"typeset -fu",' ');
+ else if(!flag && !nv_isattr(np,NV_FPOSIX))
+ sfputr(file,"function",' ');
+ cp = nv_name(np);
+ if(tp->wctname)
+ cp += strlen(tp->wctname)+1;
+ sfputr(file,cp,-1);
+ if(nv_isattr(np,NV_FPOSIX))
+ sfwrite(file,"()",2);
+ if(np->nvalue.ip && np->nvalue.rp->hoffset>=0)
+ fname = np->nvalue.rp->fname;
+ else
+ flag = '\n';
+ if(flag)
+ {
+ if(tp->pflag && np->nvalue.ip && np->nvalue.rp->hoffset>=0)
+ sfprintf(file," #line %d %s\n",np->nvalue.rp->lineno,fname?sh_fmtq(fname):"");
+ else
+ sfputc(file, '\n');
+ }
+ else
+ {
+ if(nv_isattr(np,NV_FTMP))
+ {
+ fname = 0;
+ iop = tp->sh->heredocs;
+ }
+ else if(fname)
+ iop = sfopen(iop,fname,"r");
+ else if(tp->sh->gd->hist_ptr)
+ iop = (tp->sh->gd->hist_ptr)->histfp;
+ if(iop && sfseek(iop,(Sfoff_t)np->nvalue.rp->hoffset,SEEK_SET)>=0)
+ sfmove(iop,file, nv_size(np), -1);
+ else
+ flag = '\n';
+ if(fname)
+ sfclose(iop);
+ }
+ return(nv_size(np)+1);
+ }
+ if(nv_arrayptr(np))
+ {
+ if(indent)
+ sfnputc(file,'\t',indent);
+ print_value(file,np,tp);
+ return(0);
+ }
+ if(nv_isvtree(np))
+ nv_onattr(np,NV_EXPORT);
+ if(cp=nv_getval(np))
+ {
+ if(indent)
+ sfnputc(file,'\t',indent);
+ sfputr(file,nv_name(np),-1);
+ if(!flag)
+ flag = '=';
+ sfputc(file,flag);
+ if(flag != '\n')
+ {
+ if(nv_isref(np) && nv_refsub(np))
+ {
+ sfputr(file,sh_fmtq(cp),-1);
+ sfprintf(file,"[%s]\n", sh_fmtq(nv_refsub(np)));
+ }
+ else
+#if SHOPT_TYPEDEF
+ sfputr(file,nv_isvtree(np)?cp:sh_fmtq(cp),'\n');
+#else
+ sfputr(file,sh_fmtq(cp),'\n');
+#endif /* SHOPT_TYPEDEF */
+ }
+ return(1);
+ }
+ else if(outname || (tp->scanmask && tp->scanroot==tp->sh->var_tree))
+ sfputr(file,nv_name(np),'\n');
+ return(0);
+}
+
+/*
+ * print attributes at all nodes
+ */
+static void print_all(Sfio_t *file,Dt_t *root, struct tdata *tp)
+{
+ tp->outfile = file;
+ nv_scan(root, print_attribute, (void*)tp, 0, 0);
+}
+
+/*
+ * print the attributes of name value pair give by <np>
+ */
+static void print_attribute(register Namval_t *np,void *data)
+{
+ register struct tdata *dp = (struct tdata*)data;
+ nv_attribute(np,dp->outfile,dp->prefix,dp->aflag);
+}
+
+/*
+ * print the nodes in tree <root> which have attributes <flag> set
+ * of <option> is non-zero, no subscript or value is printed.
+ */
+
+static void print_scan(Sfio_t *file, int flag, Dt_t *root, int option,struct tdata *tp)
+{
+ register char **argv;
+ register Namval_t *np;
+ register int namec;
+ Namval_t *onp = 0;
+ char *name=0;
+ int len;
+ tp->sh->last_table=0;
+ flag &= ~NV_ASSIGN;
+ tp->scanmask = flag&~NV_NOSCOPE;
+ tp->scanroot = root;
+ tp->outfile = file;
+#if SHOPT_TYPEDEF
+ if(!tp->prefix && tp->tp)
+ tp->prefix = nv_name(tp->tp);
+#endif /* SHOPT_TYPEDEF */
+ if(flag&NV_INTEGER)
+ tp->scanmask |= (NV_DOUBLE|NV_EXPNOTE);
+ if(flag==NV_LTOU || flag==NV_UTOL)
+ tp->scanmask |= NV_UTOL|NV_LTOU;
+ namec = nv_scan(root,nullscan,(void*)tp,tp->scanmask,flag);
+ argv = tp->argnam = (char**)stkalloc(tp->sh->stk,(namec+1)*sizeof(char*));
+ namec = nv_scan(root, pushname, (void*)tp, tp->scanmask, flag&~NV_IARRAY);
+ if(mbcoll())
+ strsort(argv,namec,strcoll);
+ if(namec==0 && tp->sh->namespace && nv_dict(tp->sh->namespace)==root)
+ {
+ sfnputc(file,'\t',tp->indent);
+ sfwrite(file,":\n",2);
+ }
+ else while(namec--)
+ {
+ if((np=nv_search(*argv++,root,0)) && np!=onp && (!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)))
+ {
+ onp = np;
+ if(name)
+ {
+ char *newname = nv_name(np);
+ if(memcmp(name,newname,len)==0 && newname[len]== '.')
+ continue;
+ name = 0;
+ }
+ if(flag&NV_ARRAY)
+ {
+ if(nv_aindex(np)>=0)
+ {
+ if(!(flag&NV_IARRAY))
+ continue;
+ }
+ else if((flag&NV_IARRAY))
+ continue;
+
+ }
+ tp->scanmask = flag&~NV_NOSCOPE;
+ tp->scanroot = root;
+ print_namval(file,np,option,tp);
+ if(nv_isvtree(np))
+ {
+ name = nv_name(np);
+ len = strlen(name);
+ }
+ }
+ }
+}
+
+/*
+ * add the name of the node to the argument list argnam
+ */
+
+static void pushname(Namval_t *np,void *data)
+{
+ struct tdata *tp = (struct tdata*)data;
+ *tp->argnam++ = nv_name(np);
+}
+
diff --git a/src/cmd/ksh93/bltins/ulimit.c b/src/cmd/ksh93/bltins/ulimit.c
new file mode 100644
index 0000000..c537a81
--- /dev/null
+++ b/src/cmd/ksh93/bltins/ulimit.c
@@ -0,0 +1,216 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * ulimit [-HSacdfmnstuv] [limit]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include "defs.h"
+#include "builtins.h"
+#include "name.h"
+#include "ulimit.h"
+#ifndef SH_DICT
+# define SH_DICT "libshell"
+#endif
+
+#ifdef _no_ulimit
+ int b_ulimit(int argc,char *argv[],Shbltin_t *context)
+ {
+ NOT_USED(argc);
+ NOT_USED(argv);
+ NOT_USED(context);
+ errormsg(SH_DICT,ERROR_exit(2),e_nosupport);
+ return(0);
+ }
+#else
+
+static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+ register const Limit_t* tp;
+
+ for (tp = shtab_limits; tp->option; tp++)
+ {
+ sfprintf(sp, "[%c=%d:%s?The %s", tp->option, tp - shtab_limits + 1, tp->name, tp->description);
+ if(tp->type != LIM_COUNT)
+ sfprintf(sp, " in %ss", e_units[tp->type]);
+ sfprintf(sp, ".]");
+ }
+ return(1);
+}
+
+#define HARD 2
+#define SOFT 4
+
+int b_ulimit(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *limit;
+ register int mode=0, n;
+ register unsigned long hit = 0;
+ Shell_t *shp = context->shp;
+#ifdef _lib_getrlimit
+ struct rlimit rlp;
+#endif /* _lib_getrlimit */
+ const Limit_t* tp;
+ char* conf;
+ int label, unit, nosupport;
+ rlim_t i;
+ char tmp[32];
+ Optdisc_t disc;
+ memset(&disc, 0, sizeof(disc));
+ disc.version = OPT_VERSION;
+ disc.infof = infof;
+ opt_info.disc = &disc;
+ while((n = optget(argv,sh_optulimit))) switch(n)
+ {
+ case 'H':
+ mode |= HARD;
+ continue;
+ case 'S':
+ mode |= SOFT;
+ continue;
+ case 'a':
+ hit = ~0;
+ break;
+ default:
+ if(n < 0)
+ hit |= (1L<<(-(n+1)));
+ else
+ errormsg(SH_DICT,2, e_notimp, opt_info.name);
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ opt_info.disc = 0;
+ /* default to -f */
+ limit = argv[opt_info.index];
+ if(hit==0)
+ for(n=0; shtab_limits[n].option; n++)
+ if(shtab_limits[n].index == RLIMIT_FSIZE)
+ {
+ hit |= (1L<<n);
+ break;
+ }
+ /* only one option at a time for setting */
+ label = (hit&(hit-1));
+ if(error_info.errors || (limit && label) || argc>opt_info.index+1)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ if(mode==0)
+ mode = (HARD|SOFT);
+ for(tp = shtab_limits; tp->option && hit; tp++,hit>>=1)
+ {
+ if(!(hit&1))
+ continue;
+ nosupport = (n = tp->index) == RLIMIT_UNKNOWN;
+ unit = shtab_units[tp->type];
+ if(limit)
+ {
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ if(strcmp(limit,e_unlimited)==0)
+ i = INFINITY;
+ else
+ {
+ char *last;
+ /* an explicit suffix unit overrides the default */
+ if((i=strtol(limit,&last,0))!=INFINITY && !*last)
+ i *= unit;
+ else if((i=strton(limit,&last,NiL,0))==INFINITY || *last)
+ {
+ if((i=sh_strnum(limit,&last,2))==INFINITY || *last)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+ i *= unit;
+ }
+ }
+ if(nosupport)
+ errormsg(SH_DICT,ERROR_system(1),e_readonly,tp->name);
+ else
+ {
+#ifdef _lib_getrlimit
+ if(getrlimit(n,&rlp) <0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+ if(mode&HARD)
+ rlp.rlim_max = i;
+ if(mode&SOFT)
+ rlp.rlim_cur = i;
+ if(setrlimit(n,&rlp) <0)
+ errormsg(SH_DICT,ERROR_system(1),e_overlimit,limit);
+#else
+ if((i=vlimit(n,i)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+#endif /* _lib_getrlimit */
+ }
+ }
+ else
+ {
+ if(!nosupport)
+ {
+#ifdef _lib_getrlimit
+ if(getrlimit(n,&rlp) <0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+ if(mode&HARD)
+ i = rlp.rlim_max;
+ if(mode&SOFT)
+ i = rlp.rlim_cur;
+#else
+# ifdef _lib_ulimit
+ n--;
+# endif /* _lib_ulimit */
+ i = -1;
+ if((i=vlimit(n,i)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+#endif /* _lib_getrlimit */
+ }
+ if(label)
+ {
+ if(tp->type != LIM_COUNT)
+ sfsprintf(tmp,sizeof(tmp),"%s (%ss)", tp->description, e_units[tp->type]);
+ else
+ sfsprintf(tmp,sizeof(tmp),"%s", tp->name);
+ sfprintf(sfstdout,"%-30s (-%c) ",tmp,tp->option);
+ }
+ if(nosupport)
+ {
+ if(!tp->conf || !*(conf = astconf(tp->conf, NiL, NiL)))
+ conf = (char*)e_nosupport;
+ sfputr(sfstdout,conf,'\n');
+ }
+ else if(i!=INFINITY)
+ {
+ i += (unit-1);
+ sfprintf(sfstdout,"%I*d\n",sizeof(i),i/unit);
+ }
+ else
+ sfputr(sfstdout,e_unlimited,'\n');
+ }
+ }
+ return(0);
+}
+#endif /* _no_ulimit */
diff --git a/src/cmd/ksh93/bltins/umask.c b/src/cmd/ksh93/bltins/umask.c
new file mode 100644
index 0000000..19978ac
--- /dev/null
+++ b/src/cmd/ksh93/bltins/umask.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * umask [-S] [mask]
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include <ctype.h>
+#include <ls.h>
+#include <shell.h>
+#include "builtins.h"
+#ifndef SH_DICT
+# define SH_DICT "libshell"
+#endif
+
+int b_umask(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *mask;
+ register int flag = 0, sflag = 0;
+ NOT_USED(context);
+ while((argc = optget(argv,sh_optumask))) switch(argc)
+ {
+ case 'S':
+ sflag++;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(mask = *argv)
+ {
+ register int c;
+ if(isdigit(*mask))
+ {
+ while(c = *mask++)
+ {
+ if (c>='0' && c<='7')
+ flag = (flag<<3) + (c-'0');
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_number,*argv);
+ }
+ }
+ else
+ {
+ char *cp = mask;
+ flag = umask(0);
+ c = strperm(cp,&cp,~flag&0777);
+ if(*cp)
+ {
+ umask(flag);
+ errormsg(SH_DICT,ERROR_exit(1),e_format,mask);
+ }
+ flag = (~c&0777);
+ }
+ umask(flag);
+ }
+ else
+ {
+ umask(flag=umask(0));
+ if(sflag)
+ sfprintf(sfstdout,"%s\n",fmtperm(~flag&0777));
+ else
+ sfprintf(sfstdout,"%0#4o\n",flag);
+ }
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/whence.c b/src/cmd/ksh93/bltins/whence.c
new file mode 100644
index 0000000..7843ca7
--- /dev/null
+++ b/src/cmd/ksh93/bltins/whence.c
@@ -0,0 +1,294 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * command [-pvVx] name [arg...]
+ * whence [-afvp] name...
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <error.h>
+#include "shtable.h"
+#include "name.h"
+#include "path.h"
+#include "shlex.h"
+#include "builtins.h"
+
+#define P_FLAG 1
+#define V_FLAG 2
+#define A_FLAG 4
+#define F_FLAG 010
+#define X_FLAG 020
+#define Q_FLAG 040
+
+static int whence(Shell_t *,char**, int);
+
+/*
+ * command is called with argc==0 when checking for -V or -v option
+ * In this case return 0 when -v or -V or unknown option, otherwise
+ * the shift count to the command is returned
+ */
+int b_command(register int argc,char *argv[],Shbltin_t *context)
+{
+ register int n, flags=0;
+ register Shell_t *shp = context->shp;
+ opt_info.index = opt_info.offset = 0;
+ while((n = optget(argv,sh_optcommand))) switch(n)
+ {
+ case 'p':
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,"-p");
+ sh_onstate(SH_DEFPATH);
+ break;
+ case 'v':
+ flags |= X_FLAG;
+ break;
+ case 'V':
+ flags |= V_FLAG;
+ break;
+ case 'x':
+ shp->xargexit = 1;
+ break;
+ case ':':
+ if(argc==0)
+ return(0);
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ if(argc==0)
+ return(0);
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ if(argc==0)
+ return(flags?0:opt_info.index);
+ argv += opt_info.index;
+ if(error_info.errors || !*argv)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
+ return(whence(shp,argv, flags));
+}
+
+/*
+ * for the whence command
+ */
+int b_whence(int argc,char *argv[],Shbltin_t *context)
+{
+ register int flags=0, n;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ if(*argv[0]=='t')
+ flags = V_FLAG;
+ while((n = optget(argv,sh_optwhence))) switch(n)
+ {
+ case 'a':
+ flags |= A_FLAG;
+ /* FALL THRU */
+ case 'v':
+ flags |= V_FLAG;
+ break;
+ case 'f':
+ flags |= F_FLAG;
+ break;
+ case 'p':
+ flags |= P_FLAG;
+ flags &= ~V_FLAG;
+ break;
+ case 'q':
+ flags |= Q_FLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors || !*argv)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ return(whence(shp, argv, flags));
+}
+
+static int whence(Shell_t *shp,char **argv, register int flags)
+{
+ register const char *name;
+ register Namval_t *np;
+ register const char *cp;
+ register int aflag,r=0;
+ register const char *msg;
+ int tofree;
+ Dt_t *root;
+ Namval_t *nq;
+ char *notused;
+ Pathcomp_t *pp=0;
+ int notrack = 1;
+ if(flags&Q_FLAG)
+ flags &= ~A_FLAG;
+ while(name= *argv++)
+ {
+ tofree=0;
+ aflag = ((flags&A_FLAG)!=0);
+ cp = 0;
+ np = 0;
+ if(flags&P_FLAG)
+ goto search;
+ if(flags&Q_FLAG)
+ goto bltins;
+ /* reserved words first */
+ if(sh_lookup(name,shtab_reserved))
+ {
+ sfprintf(sfstdout,"%s%s\n",name,(flags&V_FLAG)?sh_translate(is_reserved):"");
+ if(!aflag)
+ continue;
+ aflag++;
+ }
+ /* non-tracked aliases */
+ if((np=nv_search(name,shp->alias_tree,0))
+ && !nv_isnull(np) && !(notrack=nv_isattr(np,NV_TAGGED))
+ && (cp=nv_getval(np)))
+ {
+ if(flags&V_FLAG)
+ {
+ if(nv_isattr(np,NV_EXPORT))
+ msg = sh_translate(is_xalias);
+ else
+ msg = sh_translate(is_alias);
+ sfprintf(sfstdout,msg,name);
+ }
+ sfputr(sfstdout,sh_fmtq(cp),'\n');
+ if(!aflag)
+ continue;
+ cp = 0;
+ aflag++;
+ }
+ /* built-ins and functions next */
+ bltins:
+ root = (flags&F_FLAG)?shp->bltin_tree:shp->fun_tree;
+ if(np= nv_bfsearch(name, root, &nq, &notused))
+ {
+ if(is_abuiltin(np) && nv_isnull(np))
+ goto search;
+ cp = "";
+ if(flags&V_FLAG)
+ {
+ if(nv_isnull(np))
+ cp = sh_translate(is_ufunction);
+ else if(is_abuiltin(np))
+ {
+ if(nv_isattr(np,BLT_SPC))
+ cp = sh_translate(is_spcbuiltin);
+ else
+ cp = sh_translate(is_builtin);
+ }
+ else
+ cp = sh_translate(is_function);
+ }
+ if(flags&Q_FLAG)
+ continue;
+ sfprintf(sfstdout,"%s%s\n",name,cp);
+ if(!aflag)
+ continue;
+ cp = 0;
+ aflag++;
+ }
+ search:
+ if(sh_isstate(SH_DEFPATH))
+ {
+ cp=0;
+ notrack=1;
+ }
+ do
+ {
+ if(path_search(shp,name,&pp,2+(aflag>1)))
+ {
+ cp = name;
+ if((flags&P_FLAG) && *cp!='/')
+ cp = 0;
+ }
+ else
+ {
+ cp = stakptr(PATH_OFFSET);
+ if(*cp==0)
+ cp = 0;
+ else if(*cp!='/')
+ {
+ cp = path_fullname(shp,cp);
+ tofree=1;
+ }
+ }
+ if(flags&Q_FLAG)
+ {
+ pp = 0;
+ r |= !cp;
+ }
+ else if(cp)
+ {
+ if(flags&V_FLAG)
+ {
+ if(*cp!= '/')
+ {
+ if(!np && (np=nv_search(name,shp->track_tree,0)))
+ sfprintf(sfstdout,"%s %s %s/%s\n",name,sh_translate(is_talias),path_pwd(shp,0),cp);
+ else if(!np || nv_isnull(np))
+ sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction));
+ continue;
+ }
+ sfputr(sfstdout,sh_fmtq(name),' ');
+ /* built-in version of program */
+ if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0)))
+ msg = sh_translate(is_builtver);
+ /* tracked aliases next */
+ else if(aflag>1 || !notrack || strchr(name,'/'))
+ msg = sh_translate("is");
+ else
+ msg = sh_translate(is_talias);
+ sfputr(sfstdout,msg,' ');
+ }
+ sfputr(sfstdout,sh_fmtq(cp),'\n');
+ if(aflag)
+ {
+ if(aflag<=1)
+ aflag++;
+ if (pp)
+ pp = pp->next;
+ }
+ else
+ pp = 0;
+ if(tofree)
+ {
+ free((char*)cp);
+ tofree = 0;
+ }
+ }
+ else if(aflag<=1)
+ {
+ r |= 1;
+ if(flags&V_FLAG)
+ errormsg(SH_DICT,ERROR_exit(0),e_found,sh_fmtq(name));
+ }
+ } while(pp);
+ }
+ return(r);
+}
+
diff --git a/src/cmd/ksh93/builtins.mm b/src/cmd/ksh93/builtins.mm
new file mode 100644
index 0000000..0a4ef7c
--- /dev/null
+++ b/src/cmd/ksh93/builtins.mm
@@ -0,0 +1,648 @@
+.fp 5 CW
+.ds DT January 9, 2012 \" use troff -mm
+.nr C 3
+.nr N 2
+.SA 1 \" right justified
+.TL "311466-6713" "49059-6" \" charging case filing case
+Guidelines for writing \f5ksh-93\fP built-in commands
+.AU "David G. Korn" DGK FP 11267 8062 D-237 "(research!dgk)"
+.AF
+.TM 11267-930???-93 \" technical memo + TM numbers
+.MT 4
+.AS 2 \" abstract start for TM
+One of the features of \f5ksh93\fP, the latest version of \f5ksh\fP,
+is the ability to add built-in commands at run time.
+This feature only works on operating systems that have the ability
+to load and link code into the current process at run time.
+Some examples of the systems that have this feature
+are Linux, System V Release 4, Solaris, Sun OS, HP-UX Release 8 and above,
+AIX 3.2 and above, and Microsoft Windows systems.
+.P
+This memo describes how to write and compile programs
+that can be loaded into \f5ksh\fP at run time as built-in
+commands.
+.AE \" abstract end
+.H 1 INTRODUCTION
+A built-in command is executed without creating a separate process.
+Instead, the command is invoked as a C function by \f5ksh\fP.
+If this function has no side effects in the shell process,
+then the behavior of this built-in is identical to that of
+the equivalent stand-alone command. The primary difference
+in this case is performance. The overhead of process creation
+is eliminated. For commands of short duration, the effect
+can be dramatic. For example, on SUN OS 4.1, the time to
+run \f5wc\fP on a small file of about 1000 bytes, runs
+about 50 times faster as a built-in command.
+.P
+In addition, built-in commands may have side effects on the
+shell environment.
+This is usually done to extend the application domain for
+shell programming. For example, there is a group of X-windows extension
+built-ins that make heavy use of the shell variable namespace.
+These built-ins are added at run time and
+result in a windowing shell that can be used to write
+X-windows applications.
+.P
+While there are definite advantages to adding built-in
+commands, there are some disadvantages as well.
+Since the built-in command and \f5ksh\fP share the same
+address space, a coding error in the built-in program
+may affect the behavior of \f5ksh\fP; perhaps causing
+it to core dump or hang.
+Debugging is also more complex since your code is now
+a part of a larger entity.
+The isolation provided by a separate process
+guarantees that all resources used by the command
+will be freed when the command completes.
+Resources used by a built-in must be meticulously maintained and freed.
+Also, since the address space of \f5ksh\fP will be larger when built-in are loaded,
+it may increase the time it takes \f5ksh\fP to fork() and
+exec() non-built-in commands.
+It makes no sense to add a built-in command that takes
+a long time to run or that is run only once, since the performance
+benefits will be negligible.
+Built-ins that have side effects in the current shell
+environment have the disadvantage of increasing the
+coupling between the built-in and \f5ksh\fP, making
+the overall system less modular and more monolithic.
+.P
+Despite these drawbacks, in many cases extending
+\f5ksh\fP by adding built-in
+commands makes sense and allows reuse of the shell
+scripting ability in an application specific domain.
+This memo describes how to write \f5ksh\fP extensions.
+.H 1 "WRITING BUILT-IN COMMANDS"
+There is a development kit available for writing \f5ksh\fP
+built-ins as part of the AST (AT&T Software Technology) Toolkit.
+The development kit has three directories,
+\f5include\fP, \f5lib\fP, and \f5bin\fP.
+It is best to set the value of the environment variable
+\f5PACKAGE_ast\fP to the pathname of the directory
+containing the development kit.
+The \f5include\fP directory contains a sub-directory
+named \f5ast\fP that contains interface prototypes
+for functions that you can call from built-ins. The \f5lib\fP
+directory contains the \f5ast\fP library
+and a library named \f5cmd\fP that contains a version
+of several of the standard POSIX\*(Rf
+.RS
+.I "POSIX \- Part 2: Shell and Utilities,"
+IEEE Std 1003.2-1992, ISO/IEC 9945-2:1993.
+.RF
+utilities that can be made run time built-ins.
+The \f5lib/ksh\fP directory contains shared libraries
+that implement other \f5ksh\fP built-ins.
+The \f5bin\fP directory contains build tools such as \f5nmake\fP\*(Rf.
+.RS
+Glenn Fowler,
+.IR "A Case for make" ,
+Software - Practice and Experience, Vol. 20 No. S1, pp. 30-46, June 1990.
+.RF
+To add built-ins at runtime, it is necessary to build a shared library
+containing one or more built-ins that you wish to add.
+The built-ins are then added by running \f5builtin \-f\fP \fIshared_lib\fP.
+Since the procedure for building share libraries is system dependent,
+it is best to use
+\f5nmake\fP
+using the sample nmake makefile below as a prototype.
+The AST Toolkit also contains some examples of built-in libraries under
+the \f5src/cmd/kshlib\fP directory.
+.P
+There are two ways to code adding built-ins. One method is to replace
+the function \f5main\fP with a function
+\f5b_\fP\fIname\fP, where \fIname\fP is the name
+of the built-in you wish to define.
+A built-in command has a calling convention similar to
+the \f5main\fP function of a program,
+\f5int main(int argc, char *argv[])\fP.
+except that it takes a third argument of type \f5Shbltin_t*\fP which can
+be passed as \f5\s-1NULL\s+1\fP if it is not used. The definition for
+\f5Shbltin_t*\fP is in \f5<ast/shcmd.h>\fP.
+Instead of \f5exit\fP, you need to use \f5return\fP
+to terminate your command.
+The return value will become the exit status of the command.
+The \f5open\fP built-in, installed in \f5lib/ksh\fP in the AST Toolkit, uses this method.
+The \f5Shbltin_t\fP structure contains a field named \f5shp\fP which is
+a pointer the the shell data that is needed for \f5shell\fP library callbacks.
+It also contains the fields, \f5shrun\fP, \f5shtrap\fP, \f5shexit\fP,
+and \f5shbltin\fP
+that are function pointers to the \f5shell\fP library functions \f5sh_run\fP, \f5sh_trap\fP
+\f5sh_exit\fP, and \f5sh_addbuiltin\fP, respectively. These functions
+can be invoked without the need for runtime symbol lookup when the
+shell is statically linked with \f5libshell\fP.
+.P
+The alternative method is to create a function \f5lib_init\fP and
+use the \f5Shbltin_t.shbltin()\fP function to add one or more built-ins.
+The \f5lib_init\fP function will be called with two arguments. The
+first argument will be 0 when the library is loaded and the second
+argument will be of type \f5Shbltin_t*\fP.
+The \f5dbm_t\fP and \f5dss\fP shell built-ins use this method.
+.P
+No matter which way you add built-ins you should add the line
+\f5SHLIB(\fP\fIidentifier\fP\f5)\fP as the last line of one
+of the built-in source file, where \fIidentifier\fP is any C identifier.
+This line provides version information to the shell \f5builtin\fP command
+that it uses to verify compatibility between the built-in and \f5ksh\fP
+implementation versions. \f5builtin\fP fails with a diagnostic on version
+mismatch. The diagnostic helps determine whether \f5ksh\fP is out of
+date and requires an upgrade or the built-in is out of date and requires
+recompilation.
+.P
+The steps necessary to create and add a run time built-in are
+illustrated in the following simple example.
+Suppose you wish to add a built-in command named \f5hello\fP
+which requires one argument and prints the word hello followed
+by its argument. First, write the following program in the file
+\f5hello.c\fP:
+.EX
+#include <stdio.h>
+int b_hello(int argc, char *argv[], void *context)
+{
+ if(argc != 2)
+ {
+ fprintf(stderr,"Usage: hello arg\en");
+ return(2);
+ }
+ printf("hello %s\en",argv[1]);
+ return(0);
+}
+SHLIB(hello)
+.EE
+.P
+Next, the program needs to be compiled.
+If you are building with AT&T \f5nmake\fP use the following \f5Makefile\fP:
+.EX
+:PACKAGE: --shared ast
+hello plugin=ksh :LIBRARY: hello.c
+.EE
+and run \f5nmake install\fP to compile, link, and install the built-in shared library
+in \f5lib/ksh/\fP under \f5PACKAGE_ast\fP.
+If the built-in extension uses several \f5.c\fP files, list all of these on
+the \f5:LIBRARY:\fP line.
+.P
+Otherwise you will have to compile \f5hello.c\fP with an option
+to pick up the AST include directory
+(since the AST \f5<stdio.h>\fP is required for \f5ksh\fP compatibility)
+and options required for generating shared libraries.
+For example, on Linux use this to compile:
+.EX
+cc -fpic -I$PACKAGE_ast/include/ast -c hello.c
+.EE
+and use the appropriate link line.
+It really is best to use \f5nmake\fP because the 2 line Makefile above
+will work on all systems that have \f5ksh\fP installed.
+.P
+If you have several built-ins, it is desirable
+to build a shared library that contains them all.
+.P
+The final step is using the built-in.
+This can be done with the \f5ksh\fP command \f5builtin\fP.
+To load the shared library \f5libhello.so\fP from the current directory
+and add the built-in \f5hello\fP, invoke the command,
+.EX
+builtin -f ./libhello.so hello
+.EE
+The shared library prefix (\f5lib\fP here) and suffix (\f5.so\fP here) be omitted;
+the shell will add an appropriate suffix
+for the system that it is loading from.
+If you install the shared library in \f5lib/ksh/\fP, where \f5../lib/ksh/\fP is
+a directory on \fB$PATH\fP, the command
+.EX
+builtin -f hello hello
+.EE
+will automatically find, load and install the built-in on any system.
+Once this command has been invoked, you can invoke \f5hello\fP
+as you do any other command.
+If you are using \f5lib_init\fP method to add built-ins then no arguments
+follow the \f5\-f\fP option.
+.P
+It is often desirable to make a command \fIbuilt-in\fP
+the first time that it is referenced. The first
+time \f5hello\fP is invoked, \f5ksh\fP should load and execute it,
+whereas for subsequent invocations \f5ksh\fP should just execute the built-in.
+This can be done by creating a file named \f5hello\fP
+with the following contents:
+.EX
+function hello
+{
+ unset -f hello
+ builtin -f hello hello
+ hello "$@"
+}
+.EE
+This file \f5hello\fP needs to be placed in a directory that is
+in your \fB\s-1FPATH\s+1\fP variable, and the built-in shared library
+should be installed in \f5lib/ksh/\fP, as described above.
+.H 1 "CODING REQUIREMENTS AND CONVENTIONS"
+As mentioned above, the entry point for built-ins must either be of
+the form \f5b_\fP\fIname\fP or else be loaded from a function named
+\f5lib_init\fP.
+Your built-ins can call functions from the standard C library,
+the \f5ast\fP library, interface functions provided by \f5ksh\fP,
+and your own functions.
+You should avoid using any global symbols beginning with
+.BR sh_ ,
+.BR nv_ ,
+and
+.B ed_
+since these are used by \f5ksh\fP itself.
+\f5#define\fP constants in \f5ksh\fP interface
+files use symbols beginning with \f5SH_\fP and \f5NV_\fP,
+so avoid using names beginning with these too.
+.H 2 "Header Files"
+The development kit provides a portable interface
+to the C library and to libast.
+The header files in the development kit are compatible with
+K&R C\*(Rf,
+.RS
+Brian W. Kernighan and Dennis M. Ritchie,
+.IR "The C Programming Language" ,
+Prentice Hall, 1978.
+.RF
+ANSI-C\*(Rf,
+.RS
+American National Standard for Information Systems \- Programming
+Language \- C, ANSI X3.159-1989.
+.RF
+and C++\*(Rf.
+.RS
+Bjarne Stroustroup,
+.IR "C++" ,
+Addison Wesley, xxxx
+.RF
+.P
+The best thing to do is to include the header file \f5<shell.h>\fP.
+This header file causes the \f5<ast.h>\fP header, the
+\f5<error.h>\fP header and the \f5<stak.h>\fP
+header to be included as well as defining prototypes
+for functions that you can call to get shell
+services for your builtins.
+The header file \f5<ast.h>\fP
+provides prototypes for many \fBlibast\fP functions
+and all the symbol and function definitions from the
+ANSI-C headers, \f5<stddef.h>\fP,
+\f5<stdlib.h>\fP, \f5<stdarg.h>\fP, \f5<limits.h>\fP,
+and \f5<string.h>\fP.
+It also provides all the symbols and definitions for the
+POSIX\*(Rf
+.RS
+.I "POSIX \- Part 1: System Application Program Interface,"
+IEEE Std 1003.1-1990, ISO/IEC 9945-1:1990.
+.RF
+headers \f5<sys/types.h>\fP, \f5<fcntl.h>\fP, and
+\f5<unistd.h>\fP.
+You should include \f5<ast.h>\fP instead of one or more of
+these headers.
+The \f5<error.h>\fP header provides the interface to the error
+and option parsing routines defined below.
+The \f5<stak.h>\fP header provides the interface to the memory
+allocation routines described below.
+.P
+Programs that want to use the information in \f5<sys/stat.h>\fP
+should include the file \f5<ls.h>\fP instead.
+This provides the complete POSIX interface to \f5stat()\fP
+related functions even on non-POSIX systems.
+.P
+.H 2 "Input/Output"
+\f5ksh\fP uses \fBsfio\fP,
+the Safe/Fast I/O library\*(Rf,
+.RS
+David Korn and Kiem-Phong Vo,
+.IR "SFIO - A Safe/Fast Input/Output library,"
+Proceedings of the Summer Usenix,
+pp. , 1991.
+.RF
+to perform all I/O operations.
+The \fBsfio\fP library, which is part of \fBlibast\fP,
+provides a superset of the functionality provided by the standard
+I/O library defined in ANSI-C.
+If none of the additional functionality is required,
+and if you are not familiar with \fBsfio\fP and
+you do not want to spend the time learning it,
+then you can use \f5sfio\fP via the \f5stdio\fP library
+interface. The development kit contains the header \f5<stdio.h>\fP
+which maps \f5stdio\fP calls to \f5sfio\fP calls.
+In most instances the mapping is done
+by macros or inline functions so that there is no overhead.
+The man page for the \f5sfio\fP library is in an Appendix.
+.P
+However, there are some very nice extensions and
+performance improvements in \f5sfio\fP
+and if you plan any major extensions I recommend
+that you use it natively.
+.H 2 "Error Handling"
+For error messages it is best to use the \f5ast\fP library
+function \f5errormsg()\fP rather that sending output to
+\f5stderr\fP or the equivalent \f5sfstderr\fP directly.
+Using \f5errormsg()\fP will make error message appear
+more uniform to the user.
+Furthermore, using \f5errormsg()\fP should make it easier
+to do error message translation for other locales
+in future versions of \f5ksh\fP.
+.P
+The first argument to
+\f5errormsg()\fP specifies the dictionary in which the string
+will be searched for translation.
+The second argument to \f5errormsg()\fP contains that error type
+and value. The third argument is a \fIprintf\fP style format
+and the remaining arguments are arguments to be printed
+as part of the message. A new-line is inserted at the
+end of each message and therefore, should not appear as
+part of the format string.
+The second argument should be one of the following:
+.VL .5i
+.LI \f5ERROR_exit(\fP\fIn\fP\f5)\fP:
+If \fIn\fP is not-zero, the builtin will exit value \fIn\fP after
+printing the message.
+.LI \f5ERROR_system(\fP\fIn\fP\f5)\fP:
+Exit builtin with exit value \fIn\fP after printing the message.
+The message will display the message corresponding to \f5errno\fP
+enclosed within \f5[\ ]\fP at the end of the message.
+.LI \f5ERROR_usage(\fP\fIn\fP\f5)\fP:
+Will generate a usage message and exit. If \fIn\fP is non-zero,
+the exit value will be 2. Otherwise the exit value will be 0.
+.LI \f5ERROR_debug(\fP\fIn\fP\f5)\fP:
+Will print a level \fIn\fP debugging message and will then continue.
+.LI \f5ERROR_warn(\fP\fIn\fP\f5)\fP:
+Prints a warning message. \fIn\fP is ignored.
+.H 2 "Option Parsing"
+The first thing that a built-in should do is to check
+the arguments for correctness and to print any usage
+messages on standard error.
+For consistency with the rest of \f5ksh\fP, it is best
+to use the \f5libast\fP functions \f5optget()\fP and
+\f5optusage()\fPfor this
+purpose.
+The header \f5<error.h>\fP includes prototypes for
+these functions.
+The \f5optget()\fP function is similar to the
+System V C library function \f5getopt()\fP,
+but provides some additional capabilities.
+Built-ins that use \f5optget()\fP provide a more
+consistent user interface.
+.P
+The \f5optget()\fP function is invoked as
+.EX
+int optget(char *\fIargv\fP[], const char *\fIoptstring\fP)
+.EE
+where \f5argv\fP is the argument list and \f5optstring\fP
+is a string that specifies the allowable arguments and
+additional information that is used to format \fIusage\fP
+messages.
+In fact a complete man page in \f5troff\fP or \f5html\fP
+can be generated by passing a usage string as described
+by the \f5getopts\fP command.
+Like \f5getopt()\fP,
+single letter options are represented by the letter itself,
+and options that take a string argument are followed by the \f5:\fP
+character.
+Option strings have the following special characters:
+.VL .5i
+.LI \f5:\fP
+Used after a letter option to indicate that the option
+takes an option argument.
+The variable \f5opt_info.arg\fP will point to this
+value after the given argument is encountered.
+.LI \f5#\fP
+Used after a letter option to indicate that the option
+can only take a numerical value.
+The variable \f5opt_info.num\fP will contain this
+value after the given argument is encountered.
+.LI \f5?\fP
+Used after a \f5:\fP or \f5#\fP (and after the optional \f5?\fP)
+to indicate the the
+preceding option argument is not required.
+.LI \f5[\fP...\f5]\fP
+After a \f5:\fP or \f5#\fP, the characters contained
+inside the brackets are used to identify the option
+argument when generating a \fIusage\fP message.
+.LI \fIspace\fP
+The remainder of the string will only be used when generating
+usage messages.
+.LE
+.P
+The \f5optget()\fP function returns the matching option letter if
+one of the legal option is matched.
+Otherwise, \f5optget()\fP returns
+.VL .5i
+.LI \f5':'\fP
+If there is an error. In this case the variable \f5opt_info.arg\fP
+contains the error string.
+.LI \f50\fP
+Indicates the end of options.
+The variable \f5opt_info.index\fP contains the number of arguments
+processed.
+.LI \f5'?'\fP
+A usage message has been required.
+You normally call \f5optusage()\fP to generate and display
+the usage message.
+.LE
+.P
+The following is an example of the option parsing portion
+of the \f5wc\fP utility.
+.EX
+#include <shell.h>
+while(1) switch(n=optget(argv,"xf:[file]"))
+{
+ case 'f':
+ file = opt_info.arg;
+ break;
+ case ':':
+ error(ERROR_exit(0), opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), opt_info.arg);
+ break;
+}
+.EE
+.H 2 "Storage Management"
+It is important that any memory used by your built-in
+be returned. Otherwise, if your built-in is called frequently,
+\f5ksh\fP will eventually run out of memory.
+You should avoid using \f5malloc()\fP for memory that must
+be freed before returning from you built-in, because by default,
+\f5ksh\fP will terminate you built-in in the event of an
+interrupt and the memory will not be freed.
+.P
+The best way to to allocate variable sized storage is
+through calls to the \fBstak\fP library
+which is included in \fBlibast\fP
+and which is used extensively by \f5ksh\fP itself.
+Objects allocated with the \f5stakalloc()\fP
+function are freed when you function completes
+or aborts.
+The \fBstak\fP library provides a convenient way to
+build variable length strings and other objects dynamically.
+The man page for the \fBstak\fP library is contained
+in the Appendix.
+.P
+Before \f5ksh\fP calls each built-in command, it saves
+the current stack location and restores it after
+it returns.
+It is not necessary to save and restore the stack
+location in the \f5b_\fP entry function,
+but you may want to write functions that use this stack
+are restore it when leaving the function.
+The following coding convention will do this in
+an efficient manner:
+.EX
+\fIyourfunction\fP()
+{
+ char *savebase;
+ int saveoffset;
+ if(saveoffset=staktell())
+ savebase = stakfreeze(0);
+ \fR...\fP
+ if(saveoffset)
+ stakset(savebase,saveoffset);
+ else
+ stakseek(0);
+}
+.EE
+.H 1 "CALLING \f5ksh\fP SERVICES"
+Some of the more interesting applications are those that extend
+the functionality of \f5ksh\fP in application specific directions.
+A prime example of this is the X-windows extension which adds
+builtins to create and delete widgets.
+The \fBnval\fP library is used to interface with the shell
+name space.
+The \fBshell\fP library is used to access other shell services.
+.H 2 "The nval library"
+A great deal of power is derived from the ability to use
+portions of the hierarchal variable namespace provided by \f5ksh-93\fP
+and turn these names into active objects.
+.P
+The \fBnval\fP library is used to interface with shell
+variables.
+A man page for this file is provided in an Appendix.
+You need to include the header \f5<nval.h>\fP
+to access the functions defined in the \fBnval\fP library.
+All the functions provided by the \fBnval\fP library begin
+with the prefix \f5nv_\fP.
+Each shell variable is an object in an associative table
+that is referenced by name.
+The type \f5Namval_t*\fP is pointer to a shell variable.
+To operate on a shell variable, you first get a handle
+to the variable with the \f5nv_open()\fP function
+and then supply the handle returned as the first
+argument of the function that provides an operation
+on the variable.
+You must call \f5nv_close()\fP when you are finished
+using this handle so that the space can be freed once
+the value is unset.
+The two most frequent operations are to get the value of
+the variable, and to assign value to the variable.
+The \f5nv_getval()\fP returns a pointer the the
+value of the variable.
+In some cases the pointer returned is to a region that
+will be overwritten by the next \f5nv_getval()\fP call
+so that if the value isn't used immediately, it should
+be copied.
+Many variables can also generate a numeric value.
+The \f5nv_getnum()\fP function returns a numeric
+value for the given variable pointer, calling the
+arithmetic evaluator if necessary.
+.P
+The \f5nv_putval()\fP function is used to assign a new
+value to a given variable.
+The second argument to \f5putval()\fP is the value
+to be assigned
+and the third argument is a \fIflag\fP which
+is used in interpreting the second argument.
+.P
+Each shell variable can have one or more attributes.
+The \f5nv_isattr()\fP is used to test for the existence
+of one or more attributes.
+See the appendix for a complete list of attributes.
+.P
+By default, each shell variable passively stores the string you
+give with with \f5nv_putval()\fP, and returns the value
+with \f5getval()\fP. However, it is possible to turn
+any node into an active entity by assigning functions
+to it that will be called whenever \f5nv_putval()\fP
+and/or \f5nv_getval()\fP is called.
+In fact there are up to five functions that can
+associated with each variable to override the
+default actions.
+The type \f5Namfun_t\fP is used to define these functions.
+Only those that are non-\f5NULL\fP override the
+default actions.
+To override the default actions, you must allocate an
+instance of \f5Namfun_t\fP, and then assign
+the functions that you wish to override.
+The \f5putval()\fP
+function is called by the \f5nv_putval()\fP function.
+A \f5NULL\fP for the \fIvalue\fP argument
+indicates a request to unset the variable.
+The \fItype\fP argument might contain the \f5NV_INTEGER\fP
+bit so you should be prepared to do a conversion if
+necessary.
+The \f5getval()\fP
+function is called by \f5nv_getval()\fP
+value and must return a string.
+The \f5getnum()\fP
+function is called by by the arithmetic evaluator
+and must return double.
+If omitted, then it will call \f5nv_getval()\fP and
+convert the result to a number.
+.P
+The functionality of a variable can further be increased
+by adding discipline functions that
+can be associated with the variable.
+A discipline function allows a script that uses your
+variable to define functions whose name is
+\fIvarname\fP\f5.\fP\fIdiscname\fP
+where \fIvarname\fP is the name of the variable, and \fIdiscname\fP
+is the name of the discipline.
+When the user defines such a function, the \f5settrap()\fP
+function will be called with the name of the discipline and
+a pointer to the parse tree corresponding to the discipline
+function.
+The application determines when these functions are actually
+executed.
+By default, \f5ksh\fP defines \f5get\fP,
+\f5set\fP, and \f5unset\fP as discipline functions.
+.P
+In addition, it is possible to provide a data area that
+will be passed as an argument to
+each of these functions whenever any of these functions are called.
+To have private data, you need to define and allocate a structure
+that looks like
+.EX
+struct \fIyours\fP
+{
+ Namfun_t fun;
+ \fIyour_data_fields\fP;
+};
+.EE
+.H 2 "The shell library"
+There are several functions that are used by \f5ksh\fP itself
+that can also be called from built-in commands.
+The man page for these routines are in the Appendix.
+.P
+The \f5sh_addbuiltin()\fP function can be used to add or delete
+builtin commands. It takes the name of the built-in, the
+address of the function that implements the built-in, and
+a \f5void*\fP pointer that will be passed to this function
+as the third agument whenever it is invoked.
+If the function address is \f5NULL\fP, the specified built-in
+will be deleted. However, special built-in functions cannot
+be deleted or modified.
+.P
+The \f5sh_fmtq()\fP function takes a string and returns
+a string that is quoted as necessary so that it can
+be used as shell input.
+This function is used to implement the \f5%q\fP option
+of the shell built-in \f5printf\fP command.
+.P
+The \f5sh_parse()\fP function returns a parse tree corresponding
+to a give file stream. The tree can be executed by supplying
+it as the first argument to
+the \f5sh_trap()\fP function and giving a value of \f51\fP as the
+second argument.
+Alternatively, the \f5sh_trap()\fP function can parse and execute
+a string by passing the string as the first argument and giving \f50\fP
+as the second argument.
+.P
+The \f5sh_isoption()\fP function can be used to set to see whether one
+or more of the option settings is enabled.
diff --git a/src/cmd/ksh93/data/aliases.c b/src/cmd/ksh93/data/aliases.c
new file mode 100644
index 0000000..d9eca14
--- /dev/null
+++ b/src/cmd/ksh93/data/aliases.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include "defs.h"
+#include <signal.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+
+/*
+ * This is the table of built-in aliases. These should be exported.
+ */
+
+const struct shtable2 shtab_aliases[] =
+{
+#if SHOPT_FS_3D
+ "2d", NV_NOFREE, "set -f;_2d",
+#endif /* SHOPT_FS_3D */
+ "autoload", NV_NOFREE, "typeset -fu",
+ "command", NV_NOFREE, "command ",
+ "compound", NV_NOFREE, "typeset -C",
+ "fc", NV_NOFREE, "hist",
+ "float", NV_NOFREE, "typeset -lE",
+ "functions", NV_NOFREE, "typeset -f",
+ "hash", NV_NOFREE, "alias -t --",
+ "history", NV_NOFREE, "hist -l",
+ "integer", NV_NOFREE, "typeset -li",
+ "nameref", NV_NOFREE, "typeset -n",
+ "nohup", NV_NOFREE, "nohup ",
+ "r", NV_NOFREE, "hist -s",
+ "redirect", NV_NOFREE, "command exec",
+ "source", NV_NOFREE, "command .",
+#ifdef SIGTSTP
+ "stop", NV_NOFREE, "kill -s STOP",
+ "suspend", NV_NOFREE, "kill -s STOP $$",
+#endif /*SIGTSTP */
+ "times", NV_NOFREE, "{ { time;} 2>&1;}",
+ "type", NV_NOFREE, "whence -v",
+ "", 0, (char*)0
+};
+
diff --git a/src/cmd/ksh93/data/bash_pre_rc.sh b/src/cmd/ksh93/data/bash_pre_rc.sh
new file mode 100644
index 0000000..4f8a451
--- /dev/null
+++ b/src/cmd/ksh93/data/bash_pre_rc.sh
@@ -0,0 +1,255 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# bash compatibility startup script
+#
+# Author:
+# Karsten Fleischer
+# Omnium Software Engineering
+# An der Luisenburg 7
+# D-51379 Leverkusen
+# Germany
+#
+# <K.Fleischer@omnium.de>
+#
+
+alias declare=typeset
+
+nameref FUNCNAME=.sh.fun
+integer SHLVL
+export SHLVL
+SHLVL+=1
+
+if [[ ! $EUID ]]
+then EUID=$(id -u)
+ readonly EUID
+fi
+
+if [[ ! $UID ]]
+then UID=$(id -u)
+ readonly UID
+fi
+
+readonly SHELLOPTS
+if ! shopt -qo restricted; then
+ IFS=:
+ for i in $SHELLOPTS
+ do
+ [[ -n "$i" ]] && set -o $i
+ done
+ unset IFS
+fi
+function SHELLOPTS.get
+{
+ .sh.value=$(shopt -so)
+ .sh.value=${.sh.value//+([[:space:]])on*([[:space:]])/:}
+ .sh.value=${.sh.value%:}
+}
+
+set -A GROUPS $(id -G)
+function GROUPS.set
+{
+ return 1
+}
+function GROUPS.unset
+{
+ unset -f GROUPS.set
+ unset -f GROUPS.unset
+}
+
+typeset -A DIRSTACK
+function DIRSTACK.get
+{
+ set -A .sh.value $(dirs)
+}
+function DIRSTACK.set
+{
+ integer index
+ index=_push_max-.sh.subscript
+ (( index == _push_max || index < _push_top )) && return
+ _push_stack[index]=${.sh.value}
+}
+function DIRSTACK.unset
+{
+ unset -f DIRSTACK.get
+ unset -f DIRSTACK.set
+ unset -f DIRSTACK.unset
+}
+
+function PS1.set
+{
+ typeset prefix remaining=${.sh.value} var= n= k=
+ while [[ $remaining ]]
+ do prefix=${remaining%%'\'*}
+ remaining=${remaining#$prefix}
+ var+="$prefix"
+ case ${remaining:1:1} in
+ t) var+="\$(printf '%(%H:%M:%S)T')";;
+ d) var+="\$(printf '%(%a %b:%e)T')";;
+ n) var+=$'\n';;
+ s) var+=ksh;;
+ w) var+="\$(pwd)";;
+ W) var+="\$(basename \"\$(pwd)\")";;
+ u) var+=$USER;;
+ h) var+=$(hostname -s);;
+ '#') var+=!;;
+ !) var+=!;;
+ @) var+="\$(printf '%(%I:%M%p)T')";;
+ '$') if (( $(id -u) == 0 ))
+ then var+='#'
+ else var+='$'
+ fi;;
+ '\') var+='\\';;
+ '['|']') ;;
+ [0-7]) case ${remaining:1:3} in
+ [0-7][0-7][0-7])
+ k=4;;
+ [0-7][0-7])
+ k=3;;
+ *) k=2;;
+ esac
+ eval n="\$'"${remaining:0:k}"'"
+ var+=$n
+ remaining=${remaining:k}
+ continue
+ ;;
+ "") ;;
+ *) var+='\'${remaining:0:2};;
+ esac
+ remaining=${remaining:2}
+ done
+ .sh.value=$var
+}
+function logout
+{
+ if shopt -q login_shell; then
+ exit
+ else
+ print ${BASH##*/}: $0: not login shell: use 'exit' >&2
+ return 1
+ fi
+}
+PS1="bash$ "
+
+function source
+{
+ if ! shopt -qpo posix; then
+ unset OPATH
+ typeset OPATH=$PATH
+ typeset PATH=$PATH
+ if shopt -q sourcepath; then
+ PATH=$OPATH:.
+ else
+ PATH=.
+ fi
+ fi
+ . "$@"
+}
+unalias .
+alias .=source
+
+alias enable=builtin
+
+function help
+{
+ typeset b cmd usage try_cmd man
+ function has_help_option
+ {
+ [[ $1 == @(''|/*|:|echo|false|true|login|test|'[') ]] && return 1
+ return 0
+ }
+ typeset -A short_use=(
+ [echo]='Usage: echo [ options ] [arg]...'
+ [:]='Usage: : ...'
+ [true]='Usage: true ...'
+ [false]='Usage: false ...'
+ [login]='Usage: login [-p] [name]'
+ ['[']='Usage: [ EXPRESSION ] | [ OPTION'
+ [test]='Usage: test EXPRESSION | test'
+ )
+ b=$(builtin)
+ if (( $# == 0))
+ then print 'The following is the current list of built-in commands:'
+ print -r $'Type help *name* for more information about name\n'
+ for cmd in $b
+ do if has_help_option $cmd
+ then usage=$($cmd --short 2>&1)
+ print -r -- "${usage:7}"
+ else print -r -- ${short_use[$cmd]:7}
+ fi
+ done
+ return
+ fi
+ b=${b/'['/}
+ man=--man
+ [[ $1 == -s ]] && man=--short && shift
+ for try_cmd
+ do if has_help_option $try_cmd
+ then if [[ $try_cmd == @(${b//$'\n'/'|'}) ]]
+ then $try_cmd $man
+ else man $try_cmd
+ fi
+ elif [[ $man == '--short' ]]
+ then print -r -- ${short_use[$try_cmd]}
+ else man $try_cmd
+ fi
+ done
+}
+
+function cd
+{
+
+ local msg
+ local args
+ local i
+ local a
+ local ret
+
+ if ! shopt -q cdable_vars; then
+ command cd "$@"
+ else
+ msg=$(command cd "$@" 2>&1)
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ for i
+ do
+ case $i in
+ -*) args="$args $i" ;;
+ */*) args="$args $i" ;;
+ *) eval a="$"$i
+ if [[ -n $a ]]; then args="$args $a"
+ else args="$args $i"
+ fi
+ ;;
+ esac
+ done
+
+ command cd $args
+ else
+ print -- $msg
+ return $ret
+ fi
+ fi
+}
+
+typeset BASH=$0
+! shopt -qo posix && HISTFILE=~/.bash_history
+HOSTNAME=$(hostname)
+nameref BASH_SUBSHELL=.sh.subshell
diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c
new file mode 100644
index 0000000..98300fa
--- /dev/null
+++ b/src/cmd/ksh93/data/builtins.c
@@ -0,0 +1,1902 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+
+#include "defs.h"
+#include "shtable.h"
+#include <signal.h>
+#include "ulimit.h"
+#include "name.h"
+#include "version.h"
+#if KSHELL
+# include "builtins.h"
+# include "jobs.h"
+# include "FEATURE/cmds"
+# define bltin(x) (b_##x)
+ /* The following is for builtins that do not accept -- options */
+# define Bltin(x) (B_##x)
+#else
+# define bltin(x) 0
+#endif
+
+#if defined(SHOPT_CMDLIB_DIR) && !defined(SHOPT_CMDLIB_HDR)
+# define SHOPT_CMDLIB_HDR <cmdlist.h>
+#endif
+#define Q(f) #f /* libpp cpp workaround -- fixed 2005-04-11 */
+#define CMDLIST(f) SH_CMDLIB_DIR "/" Q(f), NV_BLTIN|NV_BLTINOPT|NV_NOFREE, bltin(f),
+
+#undef basename
+#undef dirname
+
+/*
+ * The order up through "[" is significant
+ */
+const struct shtable3 shtab_builtins[] =
+{
+ "login", NV_BLTIN|BLT_ENV|BLT_SPC, Bltin(login),
+ "exec", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(exec),
+ "set", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(set),
+ ":", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(true),
+ "true", NV_BLTIN|BLT_ENV, bltin(true),
+ "command", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(command),
+ "cd", NV_BLTIN|BLT_ENV, bltin(cd),
+ "break", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(break),
+ "continue", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(break),
+ "typeset", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(typeset),
+ "test", NV_BLTIN|BLT_ENV, bltin(test),
+ "[", NV_BLTIN|BLT_ENV, bltin(test),
+ "let", NV_BLTIN|BLT_ENV, bltin(let),
+ "export", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(readonly),
+ ".", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(dot_cmd),
+ "return", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return),
+#if SHOPT_BASH
+ "local", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(typeset),
+#endif
+#if _bin_newgrp || _usr_bin_newgrp
+ "newgrp", NV_BLTIN|BLT_ENV|BLT_SPC, Bltin(login),
+#endif /* _bin_newgrp || _usr_bin_newgrp */
+ "alias", NV_BLTIN|BLT_SPC|BLT_DCL, bltin(alias),
+ "hash", NV_BLTIN|BLT_SPC|BLT_DCL, bltin(alias),
+ "enum", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(enum),
+ "eval", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_EXIT,bltin(eval),
+ "exit", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return),
+ "fc", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(hist),
+ "hist", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(hist),
+ "readonly", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(readonly),
+ "shift", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(shift),
+ "trap", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(trap),
+ "unalias", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(unalias),
+ "unset", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(unset),
+ "builtin", NV_BLTIN, bltin(builtin),
+#if SHOPT_ECHOPRINT
+ "echo", NV_BLTIN|BLT_ENV, bltin(print),
+#else
+ "echo", NV_BLTIN|BLT_ENV, Bltin(echo),
+#endif /* SHOPT_ECHOPRINT */
+#ifdef JOBS
+# ifdef SIGTSTP
+ "bg", NV_BLTIN|BLT_ENV, bltin(bg),
+ "fg", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(bg),
+ "disown", NV_BLTIN|BLT_ENV, bltin(bg),
+ "kill", NV_BLTIN|BLT_ENV, bltin(kill),
+# else
+ "/bin/kill", NV_BLTIN|BLT_ENV, bltin(kill),
+# endif /* SIGTSTP */
+ "jobs", NV_BLTIN|BLT_ENV, bltin(jobs),
+#endif /* JOBS */
+ "false", NV_BLTIN|BLT_ENV, bltin(false),
+ "getopts", NV_BLTIN|BLT_ENV, bltin(getopts),
+ "print", NV_BLTIN|BLT_ENV, bltin(print),
+ "printf", NV_BLTIN|BLT_ENV, bltin(printf),
+ "pwd", NV_BLTIN, bltin(pwd),
+ "read", NV_BLTIN|BLT_ENV, bltin(read),
+ "sleep", NV_BLTIN, bltin(sleep),
+ "alarm", NV_BLTIN, bltin(alarm),
+ "ulimit", NV_BLTIN|BLT_ENV, bltin(ulimit),
+ "umask", NV_BLTIN|BLT_ENV, bltin(umask),
+#ifdef _cmd_universe
+ "universe", NV_BLTIN|BLT_ENV, bltin(universe),
+#endif /* _cmd_universe */
+#if SHOPT_FS_3D
+ "vpath", NV_BLTIN|BLT_ENV, bltin(vpath),
+ "vmap", NV_BLTIN|BLT_ENV, bltin(vpath),
+#endif /* SHOPT_FS_3D */
+ "wait", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(wait),
+ "type", NV_BLTIN|BLT_ENV, bltin(whence),
+ "whence", NV_BLTIN|BLT_ENV, bltin(whence),
+#ifdef SHOPT_CMDLIB_HDR
+#include SHOPT_CMDLIB_HDR
+#else
+ CMDLIST(basename)
+ CMDLIST(chmod)
+ CMDLIST(dirname)
+ CMDLIST(getconf)
+ CMDLIST(head)
+ CMDLIST(mkdir)
+ CMDLIST(logname)
+ CMDLIST(cat)
+ CMDLIST(cmp)
+ CMDLIST(cut)
+ CMDLIST(uname)
+ CMDLIST(wc)
+ CMDLIST(sync)
+#endif
+#if SHOPT_REGRESS
+ "__regress__", NV_BLTIN|BLT_ENV, bltin(__regress__),
+#endif
+ "", 0, 0
+};
+
+#if SHOPT_COSHELL
+# define _JOB_ "[+?Each \ajob\a can be specified as one of the following:]{" \
+ "[+\anumber\a?\anumber\a refers to a process id.]" \
+ "[+-\anumber\a?\anumber\a refers to a process group id.]" \
+ "[+\apool\a.\anum\a?refers to job \anum\a in background pool named \apool\a.]" \
+ "[+\apool\a?refers to all jobs in background pool named \apool\a.]" \
+ "[+%\anumber\a?\anumber\a refer to a job number.]" \
+ "[+%\astring\a?Refers to a job whose name begins with \astring\a.]" \
+ "[+%??\astring\a?Refers to a job whose name contains \astring\a.]" \
+ "[+%+ \bor\b %%?Refers to the current job.]" \
+ "[+%-?Refers to the previous job.]" \
+ "}"
+#else
+# define _JOB_ "[+?Each \ajob\a can be specified as one of the following:]{" \
+ "[+\anumber\a?\anumber\a refers to a process id.]" \
+ "[+-\anumber\a?\anumber\a refers to a process group id.]" \
+ "[+%\anumber\a?\anumber\a refer to a job number.]" \
+ "[+%\astring\a?Refers to a job whose name begins with \astring\a.]" \
+ "[+%??\astring\a?Refers to a job whose name contains \astring\a.]" \
+ "[+%+ \bor\b %%?Refers to the current job.]" \
+ "[+%-?Refers to the previous job.]" \
+ "}"
+#endif
+
+
+const char sh_set[] =
+"[a?Set the export attribute for each variable whose name does not "
+ "contain a \b.\b that you assign a value in the current shell "
+ "environment.]"
+"[b?The shell writes a message to standard error as soon it detects that "
+ "a background job completes rather than waiting until the next prompt.]"
+"[e?A simple command that has an non-zero exit status will cause the shell "
+ "to exit unless the simple command is:]{"
+ "[++?contained in an \b&&\b or \b||\b list.]"
+ "[++?the command immediately following \bif\b, \bwhile\b, or \buntil\b.]"
+ "[++?contained in the pipeline following \b!\b.]"
+"}"
+"[f?Pathname expansion is disabled.]"
+"[h?Obsolete. Causes each command whose name has the syntax of an "
+ "alias to become a tracked alias when it is first encountered.]"
+"[k?This is obsolete. All arguments of the form \aname\a\b=\b\avalue\a "
+ "are removed and placed in the variable assignment list for "
+ "the command. Ordinarily, variable assignments must precede "
+ "command arguments.]"
+"[m?When enabled, the shell runs background jobs in a separate process "
+ "group and displays a line upon completion. This mode is enabled "
+ "by default for interactive shells on systems that support job "
+ "control.]"
+"[n?The shell reads commands and checks for syntax errors, but does "
+ "not execute the command. Usually specified on command invocation.]"
+"[o]:?[option?If \aoption\a is not specified, the list of options and "
+ "their current settings will be written to standard output. When "
+ "invoked with a \b+\b the options will be written in a format "
+ "that can be reinput to the shell to restore the settings. "
+ "This option can be repeated to enable/disable multiple options. "
+ "The value of \aoption\a must be one of the following:]{"
+ "[+allexport?Equivalent to \b-a\b.]"
+ "[+bgnice?Runs background jobs at lower priorities.]"
+ "[+braceexpand?Equivalent to \b-B\b.] "
+ "[+emacs?Enables/disables \bemacs\b editing mode.]"
+ "[+errexit?Equivalent to \b-e\b.]"
+ "[+globstar?Equivalent to \b-G\b.]"
+ "[+gmacs?Enables/disables \bgmacs\b editing mode. \bgmacs\b "
+ "editing mode is the same as \bemacs\b editing mode "
+ "except for the handling of \b^T\b.]"
+#if SHOPT_BASH
+ "[+hashall?Equivalent to \b-h\b and \b-o trackall\b. Available "
+ "in bash compatibility mode only.]"
+ "[+history?Enable command history. Available in bash "
+ "compatibility mode only. On by default in interactive "
+ "shells.]"
+#endif
+#if SHOPT_HISTEXPAND
+ "[+histexpand?Equivalent to \b-H\b.]"
+#endif
+ "[+ignoreeof?Prevents an interactive shell from exiting on "
+ "reading an end-of-file.]"
+ "[+keyword?Equivalent to \b-k\b.]"
+ "[+letoctal?The \blet\b builtin recognizes octal constants "
+ "with leading 0.]"
+ "[+markdirs?A trailing \b/\b is appended to directories "
+ "resulting from pathname expansion.]"
+ "[+monitor?Equivalent to \b-m\b.]"
+ "[+multiline?Use multiple lines when editing lines that are "
+ "longer than the window width.]"
+ "[+noclobber?Equivalent to \b-C\b.]"
+ "[+noexec?Equivalent to \b-n\b.]"
+ "[+noglob?Equivalent to \b-f\b.]"
+ "[+nolog?This has no effect. It is provided for backward "
+ "compatibility.]"
+ "[+notify?Equivalent to \b-b\b.]"
+ "[+nounset?Equivalent to \b-u\b.]"
+#if SHOPT_BASH
+ "[+onecmd?Equivalent to \b-t\b. Available in bash compatibility "
+ "mode only.]"
+ "[+physical?Equivalent to \b-P\b. Available in bash "
+ "compatibility mode only.]"
+ "[+posix?Turn on POSIX compatibility. Available in bash "
+ "compatibility mode only. Bash in POSIX mode is not the "
+ "same as ksh.]"
+#endif
+ "[+pipefail?A pipeline will not complete until all components "
+ "of the pipeline have completed, and the exit status "
+ "of the pipeline will be the value of the last "
+ "command to exit with non-zero exit status, or will "
+ "be zero if all commands return zero exit status.]"
+ "[+privileged?Equivalent to \b-p\b.]"
+ "[+showme?Simple commands preceded by a \b;\b will be traced "
+ "as if \b-x\b were enabled but not executed.]"
+ "[+trackall?Equivalent to \b-h\b.]"
+ "[+verbose?Equivalent to \b-v\b.]"
+ "[+vi?Enables/disables \bvi\b editing mode.]"
+ "[+viraw?Does not use canonical input mode when using \bvi\b "
+ "edit mode.]"
+ "[+xtrace?Equivalent to \b-x\b.]"
+"}"
+"[p?Privileged mode. Disabling \b-p\b sets the effective user id to the "
+ "real user id, and the effective group id to the real group id. "
+ "Enabling \b-p\b restores the effective user and group ids to their "
+ "values when the shell was invoked. The \b-p\b option is on "
+ "whenever the real and effective user id is not equal or the "
+ "real and effective group id is not equal. User profiles are "
+ "not processed when \b-p\b is enabled.]"
+"[r?restricted. Enables restricted shell. This option cannot be unset once "
+ "enabled.]"
+"[t?Obsolete. The shell reads one command and then exits.]"
+"[u?If enabled, the shell displays an error message when it tries to expand "
+ "a variable that is unset.]"
+"[v?Verbose. The shell displays its input onto standard error as it "
+ "reads it.]"
+"[x?Execution trace. The shell will display each command after all "
+ "expansion and before execution preceded by the expanded value "
+ "of the \bPS4\b parameter.]"
+#if SHOPT_BASH
+ "\fbash1\f"
+#endif
+#if SHOPT_BRACEPAT
+"[B?Enable {...} group expansion. On by default.]"
+#endif
+"[C?Prevents existing regular files from being overwritten using the \b>\b "
+ "redirection operator. The \b>|\b redirection overrides this "
+ "\bnoclobber\b option.]"
+"[G?Causes \b**\b by itself to also match all sub-directories during pathname "
+ "expansion.]"
+#if SHOPT_HISTEXPAND
+ "[H?Enable \b!\b-style history expansion similar to \bcsh\b.]"
+#endif
+;
+
+const char sh_optbreak[] =
+"[-1c?\n@(#)$Id: break (AT&T Research) 1999-04-07 $\n]"
+USAGE_LICENSE
+"[+NAME?break - break out of loop ]"
+"[+DESCRIPTION?\bbreak\b is a shell special built-in that exits the "
+ "smallest enclosing \bfor\b, \bselect\b, \bwhile\b, or \buntil\b loop, "
+ "or the \an\a-th enclosing loop if \an\a is specified. "
+ "Execution continues at the command following the loop(s).]"
+"[+?If \an\a is given, it must be a positive integer >= 1. If \an\a "
+ "is larger than the number of enclosing loops, the last enclosing "
+ "loop will be exited.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?0]"
+"[+SEE ALSO?\bcontinue\b(1), \breturn\b(1)]"
+;
+
+const char sh_optcont[] =
+"[-1c?\n@(#)$Id: continue (AT&T Research) 1999-04-07 $\n]"
+USAGE_LICENSE
+"[+NAME?continue - continue execution at top of the loop]"
+"[+DESCRIPTION?\bcontinue\b is a shell special built-in that continues "
+ "execution at the top of smallest enclosing enclosing \bfor\b, "
+ "\bselect\b, \bwhile\b, or \buntil\b loop, if any; or the top of "
+ "the \an\a-th enclosing loop if \an\a is specified.]"
+"[+?If \an\a is given, it must be a positive integer >= 1. If \an\a "
+ "is larger than the number of enclosing loops, the last enclosing "
+ " loop will be used.]"
+
+"\n"
+"\n[n]\n"
+"\n"
+"[+SEE ALSO?\bbreak\b(1)]"
+;
+
+const char sh_optalarm[] = "r [varname seconds]";
+const char sh_optalias[] =
+"[-1c?\n@(#)$Id: alias (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?alias - define or display aliases]"
+"[+DESCRIPTION?\balias\b creates or redefines alias definitions "
+ "or writes the existing alias definitions to standard output. "
+ "An alias definitions provides a string value that will replace "
+ "a command name when the command is read. Alias names can "
+ "contain any printable character which is not special to the shell. "
+ "If an alias value ends in a space or tab, then the word "
+ "following the command name the alias replaces is also checked "
+ "to see whether it is an alias.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "aliases are written to standard output. Otherwise, for "
+ "each \aname\a that is specified, and \b=\b\avalue\a is not "
+ "specified, the current value of the alias corresponding to "
+ "\aname\a is written to standard output. If \b=\b\avalue\a is "
+ "specified, the alias \aname\a will be created or redefined.]"
+"[+?\balias\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a. An alias "
+ "definition only affects scripts read by the current shell "
+ "environment. It does not effect scripts run by this shell.]"
+"[p?Causes the output to be in the form of alias commands that can be used "
+ "as input to the shell to recreate the current aliases.]"
+"[t?Used for tracked aliases. These are aliases that connect a "
+ "command name to the pathname of the command and are reset "
+ "when the \bPATH\b variable is unset. The tracked aliases feature is "
+ "now obsolete.]"
+"[x?Ignored, this option is obsolete.]"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?One or more \aname\a operands did not have an alias "
+ "definition, or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\bsh\b(1), \bunalias\b(1)]"
+;
+
+const char sh_optbuiltin[] =
+"[-1c?\n@(#)$Id: builtin (AT&T Research) 2010-08-04 $\n]"
+USAGE_LICENSE
+"[+NAME?builtin - add, delete, or display shell built-ins]"
+"[+DESCRIPTION?\bbuiltin\b can be used to add, delete, or display "
+ "built-in commands in the current shell environment. A built-in command "
+ "executes in the current shell process and can have side effects in the "
+ "current shell. On most systems, the invocation time for built-in "
+ "commands is one or two orders of magnitude less than commands that "
+ "create a separate process.]"
+"[+?For each \apathname\a specified, the basename of the pathname "
+ "determines the name of the built-in. For each basename, the shell looks "
+ "for a C level function in the current shell whose name is determined by "
+ "prepending \bb_\b to the built-in name. If \apathname\a contains a "
+ "\b/\b, then the built-in is bound to this pathname. A built-in bound to "
+ "a pathname will only be executed if \apathname\a is the first "
+ "executable found during a path search. Otherwise, built-ins are found "
+ "prior to performing the path search.]"
+"[+?If no \apathname\a operands are specified, then \bbuiltin\b displays "
+ "the current list of built-ins, or just the special built-ins if \b-s\b "
+ "is specified, on standard output. The full pathname for built-ins that "
+ "are bound to pathnames are displayed.]"
+"[+?Libraries containing built-ins can be specified with the \b-f\b "
+ "option. If the library contains a function named \blib_init\b(), this "
+ "function will be invoked with argument \b0\b when the library is "
+ "loaded. The \blib_init\b() function can load built-ins by invoking an "
+ "appropriate C level function. In this case there is no restriction on "
+ "the C level function name.]"
+"[+?The C level function will be invoked with three arguments. The first "
+ "two are the same as \bmain\b() and the third one is a pointer.]"
+"[+?\bbuiltin\b cannot be invoked from a restricted shell.]"
+"[d?Deletes each of the specified built-ins. Special built-ins cannot be "
+ "deleted.]"
+"[f]:[lib?On systems with dynamic linking, \alib\a names a shared "
+ "library to load and search for built-ins. Libraries are searched for "
+ "in \b../lib/ksh\b and \b../lib\b on \b$PATH\b and in system dependent "
+ "library directories. The system "
+ "dependent shared library prefix and/or suffix may be omitted. Once a "
+ "library is loaded, its symbols become available for the current and "
+ "subsequent invocations of \bbuiltin\b. Multiple libraries can be "
+ "specified with separate invocations of \bbuiltin\b. Libraries are "
+ "searched in the reverse order in which they are specified.]"
+"[l?List the library base name, plugin YYYYMMDD version stamp, and full "
+ "path for \b-f\b\alib\a on one line on the standard output.]"
+"[s?Display only the special built-ins.]"
+"\n"
+"\n[pathname ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All \apathname\a operands and \b-f\b options processed "
+ "successfully.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bwhence\b(1)]"
+;
+
+const char sh_optcd[] =
+"[-1c?\n@(#)$Id: cd (AT&T Research) 1999-06-05 $\n]"
+USAGE_LICENSE
+"[+NAME?cd - change working directory ]"
+"[+DESCRIPTION?\bcd\b changes the current working directory of the "
+ "current shell environment.]"
+"[+?In the first form with one operand, if \adirectory\a begins with "
+ "\b/\b, or if the first component is \b.\b or \b..\b, the "
+ "directory will be changed to this directory. If directory is \b-\b, "
+ "the directory will be changed to the last directory visited. "
+ "Otherwise, if the \bCDPATH\b environment variable is set, \bcd\b "
+ "searches for \adirectory\a relative to each directory named in "
+ "the colon separated list of directories defined by \bCDPATH\b. "
+ "If \bCDPATH\b not set, \bcd\b changes to the directory specified "
+ "by \adirectory\a.]"
+"[+?In the second form, the first occurrence of the string \aold\a "
+ "contained in the pathname of the present working directory "
+ "is replaced by the string \anew\a and the resulting string "
+ "is used as the directory to which to change.]"
+"[+?When invoked without operands and when the \bHOME\b environment "
+ "variable is set to a nonempty value, the directory named by "
+ "the \bHOME\b environment variable will be used. If \bHOME\b "
+ "is empty or unset, \bcd\b will fail.]"
+"[+?When \bcd\b is successful, the \bPWD\b environment variable will be set "
+ "to the name of an absolute pathname that does not contain any "
+ "\b..\b components corresponding to the new directory. The "
+ "environment variable \bOLDPWD\b will be set to the previous "
+ "value of \bPWD\b. If the new directory is found by searching "
+ "the directories named by \bCDPATH\b, or if \adirectory\a is \b-\b, "
+ "or if the two operand form is used, the new value of \bPWD\b will be "
+ "written to standard output.]"
+"[+?If both \b-L\b and \b-P\b are specified, the last one specified will "
+ "be used. If neither \b-P\b or \b-L\b is specified then the "
+ "behavior will be determined by the \bgetconf\b parameter "
+ "\bPATH_RESOLVE\b. If \bPATH_RESOLVE\b is \bphysical\b, "
+ "then the behavior will be as if \b-P\b were specified. Otherwise, "
+ "the behavior will be as if \b-L\b were specified.]"
+"[L?Handle each pathname component \b..\b in a logical fashion by moving "
+ "up one level by name in the present working directory.]"
+"[P?The present working directory is first converted to an absolute pathname "
+ "that does not contain symbolic link components and symbolic name "
+ "components are expanded in the resulting directory name.]"
+"\n"
+"\n[directory]\n"
+"old new\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Directory successfully changed.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bpwd\b(1), \bgetconf\b(1)]"
+;
+
+const char sh_optcommand[] =
+"[-1c?\n@(#)$Id: command (AT&T Research) 2003-08-01 $\n]"
+USAGE_LICENSE
+"[+NAME?command - execute a simple command]"
+"[+DESCRIPTION?Without \b-v\b or \b-V\b, \bcommand\b executes \acommand\a "
+ "with arguments given by \aarg\a, suppressing the shell function lookup "
+ "that normally occurs. In addition, if \acommand\a is a special "
+ "built-in command, then the special properties are removed so that "
+ "failures will not cause the script that executes it to terminate.]"
+"[+?With the \b-v\b or \b-V\b options, \bcommand\b is equivalent to the "
+ "\bwhence\b(1) command.]"
+"[p?Causes a default path to be searched rather than the one defined by the "
+ "value of \bPATH\b.]"
+"[v?Equivalent to \bwhence\b \acommand\a [\aarg\a ...]].]"
+"[x?If \acommand\a fails because there are too many \aarg\as, it will be "
+ "invoked multiple times with a subset of the arguments on each "
+ "invocation. Arguments that occur prior to the first word that expand "
+ "to multiple arguments and arguments that occur after the last word "
+ "that expands to multiple arguments will be passed on each invocation. "
+ "The exit status will be the maximum invocation exit status.]"
+"[V?Equivalent to \bwhence \b-v\b \acommand\a [\aarg\a ...]].]"
+"\n"
+"\n[command [arg ...]]\n"
+"\n"
+"[+EXIT STATUS?If \acommand\a is invoked, the exit status of \bcommand\b "
+ "will be that of \acommand\a. Otherwise, it will be one of "
+ "the following:]{"
+ "[+0?\bcommand\b completed successfully.]"
+ "[+>0?\b-v\b or \b-V\b has been specified and an error occurred.]"
+ "[+126?\acommand\a was found but could not be invoked.]"
+ "[+127?\acommand\a could not be found.]"
+"}"
+
+"[+SEE ALSO?\bwhence\b(1), \bgetconf\b(1)]"
+;
+
+const char sh_optdot[] =
+"[-1c?@(#)$Id: \b.\b (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?\b.\b - execute commands in the current environment]"
+"[+DESCRIPTION?\b.\b is a special built-in command that executes commands "
+ "from a function or a file in the current environment.]"
+"[+?If \aname\a refers to a function defined with the \bfunction\b \aname\a "
+ "syntax, the function executes in the current environment as "
+ "if it had been defined with the \aname\a\b()\b syntax so that "
+ "there is no scoping. Otherwise, commands from the file defined "
+ "by \aname\a are executed in the current environment. Note that "
+ "the complete script is read before it begins to execute so that "
+ "any aliases defined in this script will not take effect until "
+ "the script completes execution.]"
+"[+?When \aname\a refers to a file, the \bPATH\b variable is searched "
+ "for the file containing commands. In this case execute permission "
+ "is not required for \aname\a.]"
+"[+?If any \aarg\as are specified, these become the positional parameters "
+ "for the duration of the function or script and are restored "
+ "upon completion.]"
+"\n"
+"\n name [arg ...]\n"
+"\n"
+"[+EXIT STATUS?If \aname\a is found, then the exit status is that "
+ "of the last command executed. Otherwise, since this is a special "
+ "built-in, an error will cause a non-interactive shell to exit with "
+ "a non-zero exit status. An interactive shell returns a non-zero exit "
+ "status to indicate an error.]"
+
+"[+SEE ALSO?\bcommand\b(1), \bksh\b(1)]"
+;
+
+#ifndef ECHOPRINT
+ const char sh_optecho[] = " [-n] [arg...]";
+#endif /* !ECHOPRINT */
+
+const char sh_opteval[] =
+"[-1c?\n@(#)$Id: eval (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?eval - create a shell command and process it]"
+"[+DESCRIPTION?\beval\b is a shell special built-in command that constructs "
+ "a command by concatenating the \aarg\as together, separating each "
+ "with a space. The resulting string is then taken as input to "
+ "the shell and evaluated in the current environment. Note that "
+ "command words are expanded twice; once to construct \aarg\a, and "
+ "again when the shell executes the constructed command.]"
+"[+?It is not an error if \aarg\a is not given.]"
+"\n"
+"\n[arg...]\n"
+"\n"
+"[+EXIT STATUS?If \aarg\a is not specified, the exit status is \b0\b. "
+ "Otherwise, it is the exit status of the command defined by the "
+ "\aarg\a operands.]"
+"[+SEE ALSO?\bexec\b(1), \btrap\b(1), \b.\b(1)]"
+;
+
+const char sh_optexec[] =
+"[-1c?\n@(#)$Id: exec (AT&T Research) 1999-07-10 $\n]"
+USAGE_LICENSE
+"[+NAME?exec - execute command, open/close and duplicate file descriptors]"
+"[+DESCRIPTION?\bexec\b is a special built-in command that can be used to "
+ "manipulate file descriptors or to replace the current shell "
+ "with a new command.]"
+"[+?If \acommand\a is specified, then the current shell process will be "
+ "replaced by \acommand\a rather than running \acommand\a and waiting "
+ "for it to complete. Note that there is no need to use "
+ "\bexec\b to enhance performance since the shell implicitly "
+ "uses the exec mechanism internally whenever possible.]"
+"[+?If no operands are specified, \bexec\b can be used to open or "
+ "close files, or to manipulate file descriptors from \b0\b to "
+ "\b9\b in the current shell environment using the standard "
+ "redirection mechanism available with all commands. The "
+ "close-on-exec flags will be set on file descriptor numbers "
+ "greater than \b2\b that are opened this way so that they "
+ "will be closed when another program is invoked.]"
+"[+?Because \bexec\b is a special command, any failure will cause the "
+ "script that invokes it to exit. This can be prevented by "
+ "invoking \bexec\b from the \bcommand\b utility.]"
+"[+?\bexec\b cannot be invoked from a restricted shell to create "
+ "files or to open a file for writing or appending.]"
+"[c?Clear all environment variables before executions except variable "
+ "assignments that are part of the current \bexec\b command.]"
+"[a]:[name?\bargv[0]]\b will be set to \aname\a for \acommand\a]"
+"\n"
+"\n[command [arg ...]]\n"
+"\n"
+"[+EXIT STATUS?If \acommand\a is specified, \bexec\b does not return. "
+ "Otherwise, the exit status is one of the following:]{"
+ "[+0?All I/O redirections were successful.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcommand\b(1), \beval\b(1)]"
+;
+
+
+const char sh_optexit[] =
+"[-1c?\n@(#)$Id: exit (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?exit - exit the current shell]"
+"[+DESCRIPTION?\bexit\b is shell special built-in that causes the "
+ "shell that invokes it to exit. Before exiting the shell, if the "
+ "\bEXIT\b trap is set it will be invoked.]"
+"[+?If \an\a is given, it will be used to set the exit status.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?If \an\a is specified, the exit status is the least significant "
+ "eight bits of the value of \an\a. Otherwise, the exit status is the "
+ "exit status of preceding command. When invoked inside a trap, the "
+ "preceding command means the command that invoked the trap.]"
+"[+SEE ALSO?\bbreak\b(1), \breturn\b(1)]"
+;
+
+const char sh_optexport[] =
+"[-1c?\n@(#)$Id: export (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?export - set export attribute on variables]"
+"[+DESCRIPTION?\bexport\b sets the export attribute on each of "
+ "the variables specified by \aname\a which causes them "
+ "to be in the environment of subsequently executed commands. "
+ "If \b=\b\avalue\a is specified, the variable \aname\a is "
+ "set to \avalue\a.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "exported variables are written to standard output.]"
+"[+?\bexport\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[p?Causes the output to be in the form of \bexport\b commands that can be "
+ "used as input to the shell to recreate the current exports.]"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bsh\b(1), \btypeset\b(1)]"
+;
+
+const char sh_optgetopts[] =
+":[-1c?\n@(#)$Id: getopts (AT&T Research) 2005-01-01 $\n]"
+"[-author?Glenn Fowler <gsf@research.att.com>]"
+USAGE_LICENSE
+"[+NAME?\f?\f - parse utility options]"
+"[+DESCRIPTION?The \bgetopts\b utility can be used to retrieve options and "
+ "arguments from a list of arguments given by \aargs\a or the positional "
+ "parameters if \aargs\a is omitted. It can also generate usage messages "
+ "and a man page for the command based on the information in \aoptstring\a.]"
+"[+?Each time it is invoked, the \bgetopts\b utility places the value "
+ "of the next option in the shell variable specified by the \aname\a "
+ "operand and the index of the next argument to be processed in the "
+ "shell variable \bOPTIND\b. When the shell is invoked \bOPTIND\b "
+ "is initialized to \b1\b. When an option requires or permits an option "
+ "argument, \bgetopts\b places the option argument in the shell "
+ "variable \bOPTARG\b. Otherwise \bOPTARG\b is set to \b1\b when the "
+ "option is set and \b0\b when the option is unset.]"
+"[+?The \aoptstring\a string consists of alpha-numeric characters, "
+ "the special characters +, -, ?, :, and <space>, or character groups "
+ "enclosed in [...]]. Character groups may be nested in {...}. "
+ "Outside of a [...]] group, a single new-line followed by zero or "
+ "more blanks is ignored. One or more blank lines separate the "
+ "options from the command argument synopsis.]"
+"[+?Each [...]] group consists of an optional label, "
+ "optional attributes separated by :, and an "
+ "optional description string following ?. The characters from the ? "
+ "to the end of the next ]] are ignored for option parsing and short "
+ "usage messages. They are used for generating verbose help or man pages. "
+ "The : character may not appear in the label. "
+ "The ? character must be specified as ?? in the label and the ]] character "
+ "must be specified as ]]]] in the description string. "
+ "Text between two \\b (backspace) characters indicates "
+ "that the text should be emboldened when displayed. "
+ "Text between two \\a (bell) characters indicates that the text should "
+ "be emphasized or italicized when displayed. "
+ "Text between two \\v (vertical tab) characters indicates "
+ "that the text should displayed in a fixed width font. "
+ "Text between two \\f (formfeed) characters will be replaced by the "
+ "output from the shell function whose name is that of the enclosed text.]"
+"[+?All output from this interface is written to the standard error.]"
+"[+?There are several group types:]{"
+ "[+1.?A group of the form "
+ "[-[\aversion\a]][\aflag\a[\anumber\a]]]]...[?\atext\a]]]] "
+ "appearing as the first group enables the extended interface. \aversion\a "
+ "specifies the interface version, currently \b1\b. The latest version is "
+ "assumed if \aversion\a is omitted. Future enhancements "
+ "may increment \aversion\a, but all versions will be supported. \atext\a "
+ "typically specifies an SCCS or CVS identification string. Zero or more "
+ "\aflags\a with optional \anumber\a values may be specified to control "
+ "option parsing. "
+ "The flags are:]{"
+ "[++?Arguments beginning with + are considered options.]"
+ "[+c?Cache this \aoptstring\a for multiple passes. Used to optimize "
+ "builtins that may be called many times within the same process.]"
+ "[+i?Ignore this \aoptstring\a when generating help. Used when "
+ "combining \aoptstring\a values from multiple passes.]"
+ "[+l?Display only \alongname\a options in help messages.]"
+ "[+n?Associate -\anumber\a and +\anumber\a options with the first "
+ "option with numeric arguments.]"
+ "[+o?The \b-\b option character prefix is optional (supports "
+ "obsolete \bps\b(1) option syntax.)]"
+ "[+p?\anumber\a specifies the number of \b-\b characters that must "
+ "prefix long option names. The default is \b2\b; \b0\b, \b1\b or "
+ "\b2\b are accepted (e.g., \bp0\b for \bdd\b(1) and \bp1\b for "
+ "\bfind\b(1).)]"
+ "[+s?\anumber\a specifies the \b--??man\b section number, "
+ "\b1\b by default.]"
+ "}"
+ "[+2.?An option specification of the form "
+ "[\aoption\a[!]][=\anumber\a]][:\alongname\a]][?\atext\a]]]]. In this "
+ "case the first field is the option character; this is the value returned "
+ "in the \aname\a operand when the option is matched. If there is no "
+ "option character then a two or more digit number should be specified. "
+ "This number will be returned as the value of the \aname\a operand if the "
+ "long option is matched. If \aoption\a is followed by \b!\b then the option "
+ "character sense is the inverse of the longname sense. For options that do "
+ "not take values \bOPTARG\b will be set to \b0\b for \b!\b inverted option "
+ "characters and \b1\b otherwise. =\anumber\a optionally specifies a number to "
+ "be returned in the \aname\a operand instead of the option character. A "
+ "longname is specified by \b--\b\alongname\a and is matched by the shortest "
+ "non-ambiguous prefix of all long options. * in the \alongname\a field "
+ "indicates that only characters up to that point need to match, provided "
+ "any additional characters match exactly. The enclosing [ and ]] can be "
+ "omitted for an option that does not have a longname or descriptive text.]"
+ "[+3.?An option argument specification. "
+ "Options that take arguments can be followed by : (string value) or # "
+ "(numeric value) and an option argument specification. An option argument "
+ "specification consists of the option argument name as field 1. "
+ "The remaining \b:\b separated fields are a type name and zero or more of "
+ "the special attribute words \blistof\b, \boneof\b, and \bignorecase\b. "
+ "A default option value may be specified in the final field as "
+ "\b:=\b\adefault\a. The option argument specification may be followed "
+ "by a list of option value descriptions enclosed in braces. "
+ "A long option that takes an argument is specified as "
+ "\b--\b\alongname\a=\avalue\a. If the : or # is followed by ? then the "
+ "option argument is optional. If only the option character form is "
+ "specified then the optional argument value is not set if the next "
+ "argument starts with - or +. The special attributes are currently "
+ "informational with respect to \boptget\b(3), but may be useful to "
+ "applications that parse \b--api\b output. The special attributes are:]{"
+ "[+listof?zero or more of the possible option values may be specified, "
+ "separated by \b,\b or space.]"
+ "[+oneof?exactly one of the possible option values must be specified]"
+ "[+ignorecase?case ignored in matching the long option name]"
+ "}"
+ "[+4.?A option value description.]"
+ "[+5.?A argument specification. A list of valid option argument values "
+ "can be specified by enclosing them inside a {...} following "
+ "the option argument specification. Each of the permitted "
+ "values can be specified with a [...]] containing the "
+ "value followed by a description.]"
+ "[+6.?A group of the form [+\\n...]] will display the characters "
+ "representing ... in fixed with font without adding line breaks.]"
+ "[+7.?A group of the form [+\aname\a?\atext\a]] specifies a section "
+ "\aname\a with descriptive \atext\a. If \aname\a is omitted then "
+ "\atext\a is placed in a new paragraph.]"
+ "[+8.?A group of the form [-\aname\a?\atext\a]] specifies entries "
+ "for the \bIMPLEMENTATION\b section.]"
+"}"
+"[+?A leading : character in \aoptstring\a "
+ "affects the way errors are handled. If an option character or longname "
+ "argument not specified in \aoptstring\a is encountered when processing "
+ "options, the shell variable whose name is \aname\a will be set to the ? "
+ "character. The shell variable \bOPTARG\b will be set to "
+ "the character found. If an option argument is missing or has an invalid "
+ "value, then \aname\a will be set to the : character and the shell variable "
+ "\bOPTARG\b will be set to the option character found. "
+ "Without the leading :, \aname\a will be set to the ? character, \bOPTARG\b "
+ "will be unset, and an error message will be written to standard error "
+ "when errors are encountered.]"
+"[+?A leading + character or a + following a leading : in \aoptstring\a "
+ "specifies that arguments beginning with + will also be considered options.]"
+"[+?The end of options occurs when:]{"
+ "[+1.?The special argument \b--\b is encountered.]"
+ "[+2.?An argument that does not begin with a \b-\b is encountered.]"
+ "[+3.?A help argument is specified.]"
+ "[+4.?An error is encountered.]"
+"}"
+"[+?If \bOPTIND\b is set to the value \b1\b, a new set of arguments "
+ "can be used.]"
+"[+?\bgetopts\b can also be used to generate help messages containing command "
+ "usage and detailed descriptions. Specify \aargs\a as:]"
+"{ "
+ "[+-???To generate a usage synopsis.]"
+ "[+--?????To generate a verbose usage message.]"
+ "[+--????man?To generate a formatted man page.]"
+ "[+--????api?To generate an easy to parse usage message.]"
+ "[+--????html?To generate a man page in \bhtml\b format.]"
+ "[+--????nroff?To generate a man page in \bnroff\b format.]"
+ "[+--????usage?List the current \aoptstring\a.]"
+ "[+--??????\aname\a?List \bversion=\b\an\a, \an\a>0, "
+ "if the option \aname\a is recognized by \bgetopts\b.]"
+"}"
+"[+?When the end of options is encountered, \bgetopts\b exits with a "
+ "non-zero return value and the variable \bOPTIND\b is set to the "
+ "index of the first non-option argument.]"
+"[+?The obsolete long option forms \aflag\a(\along-name\a) and "
+ "\aflag\a:(\along-name\a) for options that take arguments is supported "
+ "for backwards compatibility.]"
+"a:[name?Use \aname\a instead of the command name in usage messages.]"
+"\n"
+"\nopstring name [args...]\n"
+"\n"
+"[+EXIT STATUS]{"
+ "[+0?An option specified was found.]"
+ "[+1?An end of options was encountered.]"
+ "[+2?A usage or information message was generated.]"
+"}"
+;
+
+const char sh_optbg[] =
+"[-1c?@(#)$Id: bg (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?bg - resume jobs in the background]"
+"[+DESCRIPTION?\bbg\b places the given \ajob\as into the background "
+ "and sends them a \bCONT\b signal to start them running.]"
+"[+?If \ajob\a is omitted, the most recently started or stopped "
+ "background job is resumed or continued in the background.]"
+_JOB_
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?If all background jobs are started.]"
+ "[+>0?If one more jobs does not exist or there are no background "
+ "jobs.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bfg\b(1), \bdisown\b(1), \bjobs\b(1)]"
+;
+
+const char sh_optfg[] =
+"[-1c?@(#)$Id: fg (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?fg - move jobs to the foreground]"
+"[+DESCRIPTION?\bfg\b places the given \ajob\as into the foreground "
+ "in sequence and sends them a \bCONT\b signal to start each running.]"
+"[+?If \ajob\a is omitted, the most recently started or stopped "
+ "background job is moved to the foreground.]"
+_JOB_
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?If \bfg\b brings one or more jobs into the foreground, "
+ "the exit status of \bfg\b will be that of the last \ajob\a. "
+ "If one or more jobs does not exist or has completed, \bfg\b will "
+ "return a non-zero exit status.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bbg\b(1), \bjobs\b(1)]"
+;
+
+const char sh_optdisown[] =
+"[-1c?@(#)$Id: disown (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?disown - disassociate a job with the current shell]"
+"[+DESCRIPTION?\bdisown\b prevents the current shell from sending "
+ "a \bHUP\b signal to each of the given \ajob\as when "
+ "the current shell terminates a login session.]"
+"[+?If \ajob\a is omitted, the most recently started or stopped "
+ "background job is used.]"
+_JOB_
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?If all jobs are successfully disowned.]"
+ "[+>0?If one more \ajob\as does not exist.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bbg\b(1), \bjobs\b(1)]"
+;
+
+const char sh_optjobs[] =
+"[-1c?@(#)$Id: jobs (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?jobs - display status of jobs]"
+"[+DESCRIPTION?\bjobs\b displays information about specified \ajob\as "
+ "that were started by the current shell environment on standard "
+ "output. The information contains the job number enclosed in "
+ "[...]], the status, and the command line that started the job.]"
+"[+?If \ajob\a is omitted, \bjobs\b displays the status of all stopped jobs, "
+ "background jobs, and all jobs whose status has changed since last "
+ "reported by the shell.]"
+"[+?When \bjobs\b reports the termination status of a job, the "
+ "shell removes the jobs from the list of known jobs in "
+ "the current shell environment.]"
+_JOB_
+"[l?\bjobs\b displays process id's after the job number in addition "
+ "to the usual information]"
+"[n?Only the jobs whose status has changed since the last prompt "
+ "is displayed.]"
+"[p?The process group leader id's for the specified jobs are displayed.]"
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The information for each job is written to standard output.]"
+ "[+>0?One or more jobs does not exist.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bps\b(1), \bfg\b(1), \bbg\b(1)]"
+;
+
+const char sh_opthist[] =
+"[-1cn?@(#)$Id: hist (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - process command history list]"
+"[+DESCRIPTION?\b\f?\f\b lists, edits, or re-executes, commands "
+ "previously entered into the current shell environment.]"
+"[+?The command history list references commands by number. The first number "
+ "in the list is selected arbitrarily. The relationship of a number "
+ "to its command does not change during a login session. When the "
+ "number reaches 32767 the number wraps around to 1 but "
+ "maintains the ordering.]"
+"[+?When commands are edited (when the \b-l\b option is not specified), the "
+ "resulting lines will be entered at the end of the history list and "
+ "then reexecuted by the current shell. The \b\f?\f\b command that "
+ "caused the editing will not be entered into the history list. If the "
+ "editor returns a non-zero exit status, this will suppress the "
+ "entry into the history list and the command reexecution. Command "
+ "line variable assignments and redirections affect both the \f?\f "
+ "command and the commands that are reexecuted.]"
+"[+?\afirst\a and \alast\a define the range of commands. \afirst\a and "
+ "\alast\a can be one of the following:]{"
+ "[+\anumber\a?A positive number representing a command "
+ "number. A \b+\b sign can precede \anumber\a.]"
+ "[+-\anumber\a?A negative number representing a command "
+ "that was executed \anumber\a commands previously. "
+ "For example, \b-1\b is the previous command.]"
+ "[+\astring\a?\astring\a indicates the most recently "
+ "entered command that begins with \astring\a. "
+ "\astring\a should not contain an \b=\b.]"
+ "}"
+"[+?If \afirst\a is omitted, the previous command is used, unless \b-l\b "
+ "is specified, in which case it will default to \b-16\b and \alast\a "
+ "will default to \b-1\b.]"
+"[+?If \afirst\a is specified and \alast\a is omitted, then \alast\a will "
+ "default to \afirst\a unless \b-l\b is specified in which case "
+ "it will default to \b-1\b.]"
+"[+?If no editor is specified, then the editor specfied by the \bHISTEDIT\b "
+ "variable will be used if set, or the \bFCEDIT\b variable will be "
+ "used if set, otherwise, \bed\b will be used.]"
+"[e]:[editor?\aeditor\a specifies the editor to use to edit the history "
+ "command. A value of \b-\b for \aeditor\a is equivalent to "
+ "specifiying the \b-s\b option.]"
+"[l?List the commands rather than editing and reexecuting them.]"
+"[N]#[num?Start at \anum\a commands back.]"
+"[n?Suppress the command numbers when the commands are listed.]"
+#if SHOPT_HISTEXPAND
+"[p?Writes the result of history expansion for each operand to standard "
+ "output. All other options are ignored.]"
+#endif
+"[r?Reverse the order of the commands.]"
+"[s?Reexecute the command without invoking an editor. In this case "
+ "an operand of the form \aold\a\b=\b\anew\a can be specified "
+ "to change the first occurrence of the string \aold\a in the "
+ "command to \anew\a before reexecuting the command.]"
+
+"\n"
+"\n[first [last] ]\n"
+"\n"
+"[+EXIT STATUS?If a command is reexecuted, the exit status is that of "
+ "the command that gets reexecuted. Otherwise, it is one of the "
+ "following:]{"
+ "[+0?Successfully completion of the listing.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bksh\b(1), \bsh\b(1), \bed\b(1)]"
+;
+
+const char sh_optkill[] =
+"[-1c?\n@(#)$Id: kill (AT&T Research) 1999-06-17 $\n]"
+USAGE_LICENSE
+"[+NAME?kill - terminate or signal process]"
+"[+DESCRIPTION?With the first form in which \b-l\b is not specified, "
+ "\bkill\b sends a signal to one or more processes specified by "
+ "\ajob\a. This normally terminates the processes unless the signal "
+ "is being caught or ignored.]"
+_JOB_
+"[+?If the signal is not specified with either the \b-n\b or the \b-s\b "
+ "option, the \bSIGTERM\b signal is used.]"
+"[+?If \b-l\b is specified, and no \aarg\a is specified, then \bkill\b "
+ "writes the list of signals to standard output. Otherwise, \aarg\a "
+ "can be either a signal name, or a number representing either a "
+ "signal number or exit status for a process that was terminated "
+ "due to a signal. If a name is given the corresponding signal "
+ "number will be written to standard output. If a number is given "
+ "the corresponding signal name will be written to standard output.]"
+"[l?List signal names or signal numbers rather than sending signals as "
+ "described above. "
+ "The \b-n\b and \b-s\b options cannot be specified.]"
+"[n]#[signum?Specify a signal number to send. Signal numbers are not "
+ "portable across platforms, except for the following:]{"
+ "[+0?No signal]"
+ "[+1?\bHUP\b]"
+ "[+2?\bINT\b]"
+ "[+3?\bQUIT\b]"
+ "[+6?\bABRT\b]"
+ "[+9?\bKILL\b]"
+ "[+14?\bALRM\b]"
+ "[+15?\bTERM\b]"
+ "}"
+"[s]:[signame?Specify a signal name to send. The signal names are derived "
+ "from their names in \b<signal.h>\b without the \bSIG\b prefix and "
+ "are case insensitive. \bkill -l\b will generate the list of "
+ "signals on the current platform.]"
+"\n"
+"\njob ...\n"
+" -l [arg ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?At least one matching process was found for each \ajob\a "
+ "operand, and the specified signal was successfully sent to at "
+ "least one matching process.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bps\b(1), \bjobs\b(1), \bkill\b(2), \bsignal\b(2)]"
+;
+
+const char sh_optlet[] =
+"[-1c?@(#)$Id: let (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?let - evaluate arithmetic expressions]"
+"[+DESCRIPTION?\blet\b evaluates each \aexpr\a in the current "
+ "shell environment as an arithmetic expression using ANSI C "
+ "syntax. Variables names are shell variables and they "
+ "are recursively evaluated as arithmetic expressions to "
+ "get numerical values.]"
+"[+?\blet\b has been made obsolete by the \b((\b...\b))\b syntax "
+ "of \bksh\b(1) which does not require quoting of the operators "
+ "to pass them as command arguments.]"
+"\n"
+"\n[expr ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The last \aexpr\a evaluates to a non-zero value.]"
+ "[+>0?The last \aexpr\a evaluates to \b0\b or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\bexpr\b(1), \btest\b(1), \bksh\b(1)]"
+;
+
+const char sh_optprint[] =
+"[-1c?\n@(#)$Id: print (AT&T Research) 2008-11-26 $\n]"
+USAGE_LICENSE
+"[+NAME?print - write arguments to standard output]"
+"[+DESCRIPTION?By default, \bprint\b writes each \astring\a operand to "
+ "standard output and appends a newline character.]"
+"[+?Unless, the \b-r\b or \b-f\b option is specified, each \b\\\b "
+ "character in each \astring\a operand is processed specially as "
+ "follows:]{"
+ "[+\\a?Alert character.]"
+ "[+\\b?Backspace character.]"
+ "[+\\c?Terminate output without appending newline. The "
+ "remaining \astring\a operands are ignored.]"
+ "[+\\f?Formfeed character.]"
+ "[+\\n?Newline character.]"
+ "[+\\t?Tab character.]"
+ "[+\\v?Vertical tab character.]"
+ "[+\\\\?Backslash character.]"
+ "[+\\E?Escape character (ASCII octal 033).]"
+ "[+\\0\ax\a?The 8-bit character whose ASCII code is the "
+ "1-, 2-, or 3-digit octal number \ax\a.]"
+ "}"
+"[+?If both \b-e\b and \b-r\b are specified, the last one specified is "
+ "the one that is used.]"
+"[+?When the \b-f\b option is specified and there are more \astring\a "
+ "operands than format specifiers, the format string is "
+ "reprocessed from the beginning. If there are fewer \astring\a "
+ "operands than format specifiers, then outputting will end "
+ "at the first unneeded format specifier.]"
+"[e?Unless \b-f\b is specified, process \b\\\b sequences in each \astring\a "
+ "operand as described above. This is the default behavior.]"
+"[n?Do not append a new-line character to the output.]"
+"[f]:[format?Write the \astring\a arguments using the format string "
+ "\aformat\a and do not append a new-line. See \bprintf\b for "
+ "details on how to specify \aformat\a.]"
+"[p?Write to the current co-process instead of standard output.]"
+"[r?Do not process \b\\\b sequences in each \astring\a operand as described "
+ "above.]"
+"[s?Write the output as an entry in the shell history file instead of "
+ "standard output.]"
+"[u]:[fd:=1?Write to file descriptor number \afd\a instead of standard output.]"
+"[v?Treat each \astring\a as a variable name and write the value in \b%B\b "
+ "format. Cannot be used with \b-f\b.]"
+"[C?Treat each \astring\a as a variable name and write the value in \b%#B\b "
+ "format. Cannot be used with \b-f\b.]"
+"\n"
+"\n[string ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\becho\b(1), \bprintf\b(1), \bread\b(1)]"
+;
+
+const char sh_optprintf[] =
+"[-1c?\n@(#)$Id: printf (AT&T Research) 2009-02-02 $\n]"
+USAGE_LICENSE
+"[+NAME?printf - write formatted output]"
+"[+DESCRIPTION?\bprintf\b writes each \astring\a operand to "
+ "standard output using \aformat\a to control the output format.]"
+"[+?The \aformat\a operands supports the full range of ANSI C formatting "
+ "specifiers plus the following additional specifiers:]{"
+ "[+%b?Each character in the \astring\a operand is processed "
+ "specially as follows:]{"
+ "[+\\a?Alert character.]"
+ "[+\\b?Backspace character.]"
+ "[+\\c?Terminate output without appending newline. "
+ "The remaining \astring\a operands are ignored.]"
+ "[+\\f?Formfeed character.]"
+ "[+\\n?Newline character.]"
+ "[+\\t?Tab character.]"
+ "[+\\v?Vertical tab character.]"
+ "[+\\\\?Backslash character.]"
+ "[+\\E?Escape character (ASCII octal 033).]"
+ "[+\\0\ax\a?The 8-bit character whose ASCII code is "
+ "the 1-, 2-, or 3-digit octal number \ax\a.]"
+ "}"
+ "[+%q?Output \astring\a quoted in a manner that it can be read in "
+ "by the shell to get back the same string. However, empty "
+ "strings resulting from missing \astring\a operands will "
+ "not be quoted.]"
+ "[+%B?Treat the argument as a variable name and output the value "
+ "without converting it to a string. This is most useful for "
+ "variables of type \b-b\b.]"
+ "[+%H?Output \astring\a with characters \b<\b, \b&\b, \b>\b, "
+ "\b\"\b, and non-printable characters properly escaped for "
+ "use in HTML and XML documents. The alternate flag \b#\b "
+ "formats the output for use as a URI.]"
+ "[+%P?Treat \astring\a as an extended regular expression and "
+ "convert it to a shell pattern.]"
+ "[+%R?Treat \astring\a as an shell pattern expression and "
+ "convert it to an extended regular expression.]"
+ "[+%T?Treat \astring\a as a date/time string and format it. The "
+ "\bT\b can be preceded by \b(\b\adformat\a\b)\b, where "
+ "\adformat\a is a date format as defined by the \bdate\b "
+ "command.]"
+ "[+%Z?Output a byte whose value is \b0\b.]"
+"}"
+"[+?The format modifier flag \bL\b can precede the width and/or precision "
+ "specifiers for the \bc\b and \bs\b to cause the width and/or "
+ "precision to be measured in character width rather than byte count.]"
+"[+?When performing conversions of \astring\a to satisfy a numeric "
+ "format specifier, if the first character of \astring\a "
+ "is \b\"\b or \b'\b, then the value will be the numeric value "
+ "in the underlying code set of the character following the "
+ "\b\"\b or \b'\b. Otherwise, \astring\a is treated like a shell "
+ "arithmetic expression and evaluated.]"
+"[+?If a \astring\a operand cannot be completely converted into a value "
+ "appropriate for that format specifier, an error will occur, "
+ "but remaining \astring\a operands will continue to be processed.]"
+"[+?In addition to the format specifier extensions, the following "
+ "extensions of ANSI-C are permitted in format specifiers:]{"
+ "[+-?The escape sequences \b\\E\b and \b\\e\b expand to the escape "
+ "character which is octal \b033\b in ASCII.]"
+ "[+-?The escape sequence \b\\c\b\ax\a expands to Control-\ax\a.]"
+ "[+-?The escape sequence \b\\C[.\b\aname\a\b.]]\b expands to "
+ "the collating element \aname\a.]"
+ "[+-?The escape sequence \b\\x{\b\ahex\a\b}\b expands to the "
+ "character corresponding to the hexidecimal value \ahex\a.]"
+ "[+-?The format modifier flag \b=\b can be used to center a field to "
+ "a specified width.]"
+ "[+-?The format modifier flag \bL\b can be used with the \bc\b and "
+ "\bs\b formats to treat precision as character width instead "
+ "of byte count.]"
+ "[+-?The format modifier flag \b,\b can be used with \bd\b and \bf\f "
+ "formats to cause group of digits.]"
+ "[+-?Each of the integral format specifiers can have a third "
+ "modifier after width and precision that specifies the "
+ "base of the conversion from 2 to 64. In this case the "
+ "\b#\b modifier will cause \abase\a\b#\b to be prepended to "
+ "the value.]"
+ "[+-?The \b#\b modifier can be used with the \bd\b specifier when "
+ "no base is specified cause the output to be written in units "
+ "of \b1000\b with a suffix of one of \bk M G T P E\b.]"
+ "[+-?The \b#\b modifier can be used with the \bi\b specifier to "
+ "cause the output to be written in units of \b1024\b with "
+ "a suffix of one of \bKi Mi Gi Ti Pi Ei\b.]"
+ "}"
+"[+?If there are more \astring\a operands than format specifiers, the "
+ "\aformat\a string is reprocessed from the beginning. If there are "
+ "fewer \astring\a operands than format specifiers, then string "
+ "specifiers will be treated as if empty strings were supplied, "
+ "numeric conversions will be treated as if 0 were supplied, and "
+ "time conversions will be treated as if \bnow\b were supplied.]"
+"[+?\bprintf\b is equivalent to \bprint -f\b which allows additional "
+ "options to be specified.]"
+"\n"
+"\nformat [string ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bdate\b(1), \bprint\b(1), \bread\b(1)]"
+;
+
+const char sh_optpwd[] =
+"[-1c?\n@(#)$Id: pwd (AT&T Research) 1999-06-07 $\n]"
+USAGE_LICENSE
+"[+NAME?pwd - write working directory name]"
+"[+DESCRIPTION?\bpwd\b writes an absolute pathname of the current working "
+ "directory to standard output. An absolute pathname is a "
+ "pathname that begins with \b/\b that does not contains any "
+ "\b.\b or \b..\b components.]"
+"[+?If both \b-L\b and \b-P\b are specified, the last one specified will "
+ "be used. If neither \b-P\b or \b-L\b is specified then the "
+ "behavior will be determined by the \bgetconf\b parameter "
+ "\bPATH_RESOLVE\b. If \bPATH_RESOLVE\b is \bphysical\b, "
+ "then the behavior will be as if \b-P\b were specified. Otherwise, "
+ "the behavior will be as if \b-L\b were specified.]"
+"[L?The absolute pathname may contains symbolic link components. This is "
+ "the default.]"
+"[P?The absolute pathname will not contain any symbolic link components.]"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcd\b(1), \bgetconf\b(1)]"
+;
+
+const char sh_optread[] =
+"[-1c?\n@(#)$Id: read (AT&T Research) 2006-12-19 $\n]"
+USAGE_LICENSE
+"[+NAME?read - read a line from standard input]"
+"[+DESCRIPTION?\bread\b reads a line from standard input and breaks it "
+ "into fields using the characters in value of the \bIFS\b variable "
+ "as separators. The escape character, \b\\\b, is used to remove "
+ "any special meaning for the next character and for line continuation "
+ "unless the \b-r\b option is specified.]"
+"[+?If there are more variables than fields, the remaining variables are "
+ "set to empty strings. If there are fewer variables than fields, "
+ "the leftover fields and their intervening separators are assigned "
+ "to the last variable. If no \avar\a is specified then the variable "
+ "\bREPLY\b is used.]"
+"[+?When \avar\a has the binary attribute and \b-n\b or \b-N\b is specified, "
+ "the bytes that are read are stored directly into \bvar\b.]"
+"[+?If you specify \b?\b\aprompt\a after the first \avar\a, then \bread\b "
+ "will display \aprompt\a on standard error when standard input "
+ "is a terminal or pipe.]"
+"[+?If an end of file is encountered while reading a line the data is "
+ "read and processed but \bread\b returns with a non-zero exit status.]"
+"[A?Unset \avar\a and then create an indexed array containing each field in "
+ "the line starting at index 0.]"
+"[C?Unset \avar\a and read \avar\a as a compound variable.]"
+"[d]:[delim?Read until delimiter \adelim\a instead of to the end of line.]"
+"[p?Read from the current co-process instead of standard input. An end of "
+ "file causes \bread\b to disconnect the co-process so that another "
+ "can be created.]"
+"[r?Do not treat \b\\\b specially when processing the input line.]"
+"[s?Save a copy of the input as an entry in the shell history file.]"
+"[S?Treat the input as if it was saved from a spreasheet in csv format.]"
+"[u]#[fd:=0?Read from file descriptor number \afd\a instead of standard input.]"
+"[t]:[timeout?Specify a timeout \atimeout\a in seconds when reading from "
+ "a terminal or pipe.]"
+"[n]#[count?Read at most \acount\a characters. For binary fields \acount\a "
+ "is the number of bytes.]"
+"[N]#[count?Read exactly \ancount\a characters. For binary fields \acount\a "
+ "is the number of bytes.]"
+"[v?When reading from a terminal the value of the first variable is displayed "
+ "and used as a default value.]"
+"\n"
+"\n[var?prompt] [var ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0? Successful completion.]"
+ "[+>0?End of file was detected or an error occurred.]"
+"}"
+"[+SEE ALSO?\bprint\b(1), \bprintf\b(1), \bcat\b(1)]"
+;
+
+const char sh_optreadonly[] =
+"[-1c?\n@(#)$Id: readonly (AT&T Research) 2008-06-16 $\n]"
+USAGE_LICENSE
+"[+NAME?readonly - set readonly attribute on variables]"
+"[+DESCRIPTION?\breadonly\b sets the readonly attribute on each of "
+ "the variables specified by \aname\a which prevents their "
+ "values from being changed. If \b=\b\avalue\a is specified, "
+ "the variable \aname\a is set to \avalue\a before the variable "
+ "is made readonly.]"
+"[+?Within a type definition, if the value is not specified, then a "
+ "value must be specified when creating each instance of the type "
+ "and the value is readonly for each instance.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "readonly variables are written to standard output.]"
+"[+?\breadonly\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[p?Causes the output to be in a form of \breadonly\b commands that can be "
+ "used as input to the shell to recreate the current set of "
+ "readonly variables.]"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bsh\b(1), \btypeset\b(1)]"
+;
+
+const char sh_optreturn[] =
+"[-1c?\n@(#)$Id: return (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?return - return from a function or dot script ]"
+"[+DESCRIPTION?\breturn\b is a shell special built-in that causes the "
+ "function or dot script that invokes it to exit. "
+ "If \breturn\b is invoked outside of a function or dot script "
+ "it is equivalent to \bexit\b.]"
+"[+?If \breturn\b is invoked inside a function defined with the \bfunction\b "
+ "reserved word syntax, then any \bEXIT\b trap set within the "
+ "then function will be invoked in the context of the caller "
+ "before the function returns.]"
+"[+?If \an\a is given, it will be used to set the exit status.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?If \an\a is specified, the exit status is the least significant "
+ "eight bits of the value of \an\a. Otherwise, the exit status is the "
+ "exit status of preceding command.]"
+"[+SEE ALSO?\bbreak\b(1), \bexit\b(1)]"
+;
+
+
+const char sh_optksh[] =
+"+[-1?\n@(#)$Id: sh (AT&T Research) "SH_RELEASE" $\n]"
+USAGE_LICENSE
+"[+NAME?\b\f?\f\b - Shell, the standard command language interpreter]"
+"[+DESCRIPTION?\b\f?\f\b is a command language interpreter that "
+ "executes commands read from a command line string, the "
+ "standard input, or a specified file.]"
+"[+?If the \b-i\b option is present, or there are no \aarg\as and "
+ "the standard input and standard error are attached to a "
+ "terminal, the shell is considered to be interactive.]"
+"[+?The \b-s\b and \b-c\b options are mutually exclusive. If the \b-c\b "
+ "option is specified, the first \aarg\a is the command-line string "
+ "and must be specified. Any remaining \aarg\as will be used "
+ "to initialize \b$0\b and positional parameters.]"
+"[+?If the neither \b-s\b nor \b-c\b is specified, then the first \barg\b "
+ "will be the pathname of the file containing commands and \b$0\b "
+ "will be set to this value. If there is no file with this pathname, "
+ "and this pathame does not contain a \b/\b, then the \bPATH\b "
+ "will be searched for an executable with this name. Any remaining "
+ "\aarg\as will be used to initialize the positional parmaeters.]"
+"[+?Any option can use a \b+\b instead of a \b-\b to disable the corresponding "
+ "option.]"
+"[c?Read the commands from the first \aarg\a.]"
+"[i?Specifies that the shell is interactive.]"
+"[l?Invoke the shell as a login shell; \b/etc/profile\b and \b$HOME/.profile\b, "
+ "if they exist, are read before the first command.]"
+"[r\f:restricted\f?Invoke the shell in a restricted mode. A restricted "
+ "shell does not permit any of the following:]{"
+ "[+-?Changing the working directory.]"
+ "[+-?Setting values or attributes of the variables \bSHELL\b, "
+ "\bENV\b, \bFPATH\b, or \bPATH\b.]"
+ "[+-?Executing any command whose name as a \b/\b in it.]"
+ "[+-?Redirecting output of a command with \b>\b, \b>|\b, "
+ "\b<>\b, or \b>>\b.]"
+ "[+-?Adding or deleting built-in commands or libraries with "
+ "\bbuiltin\b.]"
+ "[+-?Executing \bcommand -p\b \a...\a .]"
+ "}"
+"[s?Read the commands from standard input. The positional parameters will be "
+ "initialized from \aarg\a.]"
+"[D\f:dump-strings\f?Do not execute the script, but output the set of double "
+ "quoted strings preceded by a \b$\b. These strings are needed for "
+ "localization of the script to different locales.]"
+"[E?Reads the file "
+#if SHOPT_SYSRC
+ "\b/etc/ksh.kshrc\b, if it exists, as a profile, followed by "
+#endif
+ "\b${ENV-$HOME/.kshrc}\b, if it exists, as a profile. "
+ "On by default for interactive shells; use \b+E\b to disable.]"
+#if SHOPT_PFSH
+"[P?Invoke the shell as a profile shell. See \bpfexec\b(1).]"
+#endif
+#if SHOPT_KIA
+"[R]:[file?Do not execute the script, but create a cross reference database "
+ "in \afile\a that can be used a separate shell script browser. The "
+ "-R option requires a script to be specified as the first operand.]"
+#endif /* SHOPT_KIA */
+#if SHOPT_REGRESS
+"[I:regress]:[intercept?Enable the regression test \aintercept\a. Must be "
+ "the first command line option(s).]"
+#endif
+#if SHOPT_BASH
+ "\fbash2\f"
+#endif
+"\fabc\f"
+"?"
+"[T?Enable implementation specific test code defined by mask.]#[mask]"
+"\n"
+"\n[arg ...]\n"
+"\n"
+"[+EXIT STATUS?If \b\f?\f\b executes command, the exit status will be that "
+ "of the last command executed. Otherwise, it will be one of "
+ "the following:]{"
+ "[+0?The script or command line to be executed consists entirely "
+ "of zero or more blank lines or comments.]"
+ "[+>1-125?A noninteractive shell detected a syntax error, a variable "
+ "assignment error, or an error in a special built-in.]"
+ "[+126?\b-c\b and \b-s\b were not specified and the command script "
+ "was found on \bPATH\b but was not executable.]"
+ "[+127?\b-c\b and \b-s\b were not specified and the command script "
+ "corresponding to \aarg\a could not be found.]"
+"}"
+
+"[+SEE ALSO?\bset\b(1), \bbuiltin\b(1)]"
+;
+const char sh_optset[] =
+"+[-1c?\n@(#)$Id: set (AT&T Research) 1999-09-28 $\n]"
+USAGE_LICENSE
+"[+NAME?set - set/unset options and positional parameters]"
+"[+DESCRIPTION?\bset\b sets or unsets options and positional parameters. "
+ "Options that are specified with a \b-\b cause the options to "
+ "be set. Options that are specified with a \b+\b cause the "
+ "option to be unset.]"
+"[+?\bset\b without any options or arguments displays the names and "
+ "values of all shell variables in the order of the collation "
+ "sequence in the current locale. The values are quoted so that "
+ "they are suitable for reinput to the shell.]"
+"[+?If no \aarg\as are specified, not even the end of options argument \b--\b, "
+ "the positional parameters are unchanged. Otherwise, unless "
+ "the \b-A\b options has been specified, the positional parameters "
+ "are replaced by the list of \aarg\as. A first \aarg\a of "
+ "\b--\b is ignored when setting positional parameters.]"
+"[+?For backward compatibility, a \bset\b command without any options "
+ "specified whose first \aarg\a is \b-\b will turn off "
+ "the \b-v\b and \b-x\b options. If any additional \aarg\as "
+ "are specified, they will replace the positional parameters.]"
+"[s?Sort the positional parameters.]"
+"[A]:[name?Assign the arguments sequentially to the array named by \aname\a "
+ "starting at subscript 0 rather than to the positional parameters.]"
+"\fabc\f"
+"[06:default?Restore all non-command line options to the default settings.]"
+"[07:state?List the current option state in the form of a \bset\b command "
+ "that can be executed to restore the state.]"
+"\n"
+"\n[arg ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?No errors occurred.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\btypeset\b(1), \bshift\b(1)]"
+;
+
+
+
+const char sh_optshift[] =
+"[-1c?\n@(#)$Id: shift (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?shift - shift positional parameters]"
+"[+DESCRIPTION?\bshift\b is a shell special built-in that shifts the "
+ "positional parameters to the left by the number of places "
+ "defined by \an\a, or \b1\b if \an\a is omitted. The number of "
+ "positional parameters remaining will be reduced by the "
+ "number of places that are shifted.]"
+"[+?If \an\a is given, it will be evaluated as an arithmetic expression "
+ "to determinate the number of places to shift. It is an error "
+ "to shift more than the number of positional parameters or a "
+ "negative number of places.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The positional parameters were successfully shifted.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bset\b(1)]"
+;
+
+const char sh_optsleep[] =
+"[-1c?\n@(#)$Id: sleep (AT&T Research) 2009-03-12 $\n]"
+USAGE_LICENSE
+"[+NAME?sleep - suspend execution for an interval]"
+"[+DESCRIPTION?\bsleep\b suspends execution for at least the time specified "
+ "by \aduration\a or until a \bSIGALRM\b signal is received. "
+ "\aduration\a may be one of the following:]"
+"{"
+ "[+integer?The number of seconds to sleep.]"
+ "[+floating point?The number of seconds to sleep. The actual "
+ "granularity depends on the underlying system, normally "
+ "around 1 millisecond.]"
+ "[+P\an\a\bY\b\an\a\bM\b\an\a\bDT\b\an\a\bH\b\an\a\bM\b\an\a\bS?An ISO 8601 duration "
+ "where at least one of the duration parts must be specified.]"
+ "[+P\an\a\bW?An ISO 8601 duration specifying \an\a weeks.]"
+ "[+p\an\a\bY\b\an\a\bM\b\an\a\bDT\b\an\a\bH\b\an\a\bm\b\an\a\bS?A case insensitive "
+ "ISO 8601 duration except that \bM\b specifies months, \bm\b before \bs\b or \bS\b "
+ "specifies minutes and after specifies milliseconds, \bu\b or \bU\b specifies "
+ "microseconds, and \bn\b specifies nanoseconds.]"
+ "[+date/time?Sleep until the \bdate\b(1) compatible date/time.]"
+"}"
+"[s?Sleep until a signal or a timeout is received. If \aduration\a is omitted "
+ "or 0 then no timeout will be used.]"
+"\n"
+"\n[ duration ]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The execution was successfully suspended for at least \aduration\a "
+ "or a \bSIGALRM\b signal was received.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bdate\b(1), \btime\b(1), \bwait\b(1)]"
+;
+
+const char sh_opttrap[] =
+"[-1c?\n@(#)$Id: trap (AT&T Research) 1999-07-17 $\n]"
+USAGE_LICENSE
+"[+NAME?trap - trap signals and conditions]"
+"[+DESCRIPTION?\btrap\b is a special built-in that defines actions to be "
+ "taken when conditions such as receiving a signal occur. Also, "
+ "\btrap\b can be used to display the current trap settings on "
+ "standard output.]"
+"[+?If \aaction\a is \b-\b, \btrap\b resets each \acondition\a "
+ "to the default value. If \aaction\a is an empty string, the "
+ "shell ignores each of the \acondition\as if they arise. "
+ "Otherwise, the argument \aaction\a will be read and executed "
+ "by the shell as if it were processed by \beval\b(1) when one "
+ "of the corresponding conditions arise. The action of the trap "
+ "will override any previous action associated with each specified "
+ "\acondition\a. The value of \b$?\b is not altered by the trap "
+ "execution.]"
+"[+?\acondition\a can be the name or number of a signal, or one of the "
+ "following:]{"
+ "[+EXIT?This trap is executed when the shell exits. If defined "
+ "within a function defined with the \bfunction\b reserved "
+ "word, the trap is executed in the caller's environment "
+ "when the function returns and the trap action is restored "
+ "to the value it had when it called the function.]"
+ "[+0?Same as EXIT.]"
+ "[+DEBUG?Executed before each simple command is executed but after "
+ "the arguments are expanded.]"
+ "[+ERR?Executed whenever \bset -e\b would cause the shell to exit.]"
+ "[+KEYBD?Executed when a key is entered from a terminal device.]"
+"}"
+"[+?Signal names are case insensitive and the \bsig\b prefix is optional. "
+ "Signals that were ignored on entry to a noninteractive shell cannot "
+ "trapped or reset although doing so will not report an error. The "
+ "use of signal numbers other than \b1\b, \b2\b, \b3\b, \b6\b, "
+ "\b9\b, \b14\b, and \b15\b is not portable.]"
+"[+?Although \btrap\b is a special built-in, specifying a condition that "
+ "the shell does not know about causes \btrap\b to exit with a "
+ "non-zero exit status, but does not terminate the invoking shell.]"
+"[+?If no \aaction\a or \acondition\as are specified then all the current "
+ "trap settings are written to standard output.]"
+"[p?Causes the current traps to be output in a format that can be processed "
+ "as input to the shell to recreate the current traps.]"
+"\n"
+"\n[action condition ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bkill\b(1), \beval\b(1), \bsignal\b(3)]"
+;
+
+const char sh_opttypeset[] =
+"+[-1c?\n@(#)$Id: typeset (AT&T Research) 2010-12-08 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - declare or display variables with attributes]"
+"[+DESCRIPTION?Without the \b-f\b option, \b\f?\f\b sets, unsets, "
+ "or displays attributes of variables as specified with the "
+ "options. If the first option is specified with a \b-\b "
+ "then the attributes are set for each of the given \aname\as. "
+ "If the first option is specified with a \b+\b, then the specified "
+ "attributes are unset. If \b=\b\avalue\a is specified value is "
+ "assigned before the attributes are set.]"
+"[+?When \b\f?\f\b is called inside a function defined with the "
+ "\bfunction\b reserved word, and \aname\a does not contain a "
+ "\b.\b, then a local variable statically scoped to that function "
+ "will be created.]"
+"[+?Not all option combinations are possible. For example, the numeric "
+ "options \b-i\b, \b-E\b, and \b-F\b cannot be specified with "
+ "the justification options \b-L\b, \b-R\b, and \b-Z\b.]"
+"[+?Note that the following preset aliases are set by the shell:]{"
+ "[+compound?\b\f?\f -C\b.]"
+ "[+float?\b\f?\f -lE\b.]"
+ "[+functions?\b\f?\f -f\b.]"
+ "[+integer?\b\f?\f -li\b.]"
+ "[+nameref?\b\f?\f -n\b.]"
+"}"
+"[+?If no \aname\as are specified then variables that have the specified "
+ "options are displayed. If the first option is specified with "
+ "a leading \b-\b then the name and value of each variable is "
+ "written to standard output. Otherwise, only the names are "
+ "written. If no options are specified or just \b-p\b is "
+ "specified, then the names and attributes of all variables that have "
+ "attributes are written to standard output. When \b-f\b is specified, "
+ "the names displayed will be function names.]"
+"[+?If \b-f\b is specified, then each \aname\a refers to a function "
+ "and the only valid options are \b-u\b and \b-t\b. In this "
+ "case no \b=\b\avalue\a can be specified.]"
+"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+#if 1
+"[a]:?[type?Indexed array. This is the default. If \b[\b\atype\a\b]]\b is "
+ "specified, each subscript is interpreted as a value of type \atype\a.]"
+#else
+"[a?Indexed array. this is the default.]"
+#endif
+"[b?Each \aname\a may contain binary data. Its value is the mime "
+ "base64 encoding of the data. It can be used with \b-Z\b, "
+ "to specify fixed sized fields.]"
+"[f?Each of the options and \aname\as refers to a function.]"
+"[i]#?[base:=10?An integer. \abase\a represents the arithmetic base "
+ "from 2 to 64.]"
+"[l?Without \b-i\b, sets character mapping to \btolower\b. When used "
+ "with \b-i\b, \b-E\b, or \b-F\b indicates long variant.]"
+"[m?Move. The value is the name of a variable whose value will be "
+ "moved to \aname\a. The orignal variable will be unset. Cannot be "
+ "used with any other options.]"
+"[n?Name reference. The value is the name of a variable that \aname\a "
+ "references. \aname\a cannot contain a \b.\b. Cannot be use with "
+ "any other options.]"
+"[p?Causes the output to be in a format that can be used as input to the "
+ "shell to recreate the attributes for variables.]"
+"[r?Enables readonly. Once enabled it cannot be disabled. See "
+ "\breadonly\b(1).]"
+"[s?Used with \b-i\b to restrict integer size to short.]"
+"[t?When used with \b-f\b, enables tracing for each of the specified "
+ "functions. Otherwise, \b-t\b is a user defined attribute and "
+ "has no meaning to the shell.]"
+"[u?Without \b-f\b or \b-i\b, sets character mapping to \btoupper\b. When "
+ "used with \b-f\b specifies that \aname\a is a function "
+ "that hasn't been loaded yet. With \b-i\b specifies that the "
+ "value will be displayed as an unsigned integer.]"
+"[x?Puts each \aname\a on the export list. See \bexport\b(1). \aname\a "
+ "cannot contain a \b.\b.]"
+"[A?Associative array. Each \aname\a will converted to an associate "
+ "array. If a variable already exists, the current value will "
+ "become index \b0\b.]"
+"[C?Compound variable. Each \aname\a will be a compound variable. If "
+ "\avalue\a names a compound variable it will be copied to \aname\a. "
+ "Otherwise if the variable already exists, it will first be unset.]"
+"[E]#?[n:=10?Floating point number represented in scientific notation. "
+ "\an\a specifies the number of significant figures when the "
+ "value is expanded.]"
+"[F]#?[n:=10?Floating point. \an\a is the number of places after the "
+ "decimal point when the value is expanded.]"
+"[H?Hostname mapping. Each \aname\a holds a native pathname. Assigning a "
+ "UNIX format pathname will cause it to be converted to a pathname "
+ "suitable for the current host. This has no effect when the "
+ "native system is UNIX.]"
+"[L]#?[n?Left justify. If \an\a is given it represents the field width. If "
+ "the \b-Z\b attribute is also specified, then leading zeros are "
+ "stripped.]"
+"[M]:?[mapping?\amapping\a is the name of a character mapping known by "
+ "\bwctrans\b(3) such as \btolower\b or \btoupper\b. When the option "
+ "value \bmapping\b is omitted and there are no operands, all mapped "
+ "variables are displayed.]"
+"[R]#?[n?Right justify. If \an\a is given it represents the field width. If "
+ "the \b-Z\b attribute is also specified, then zeros will "
+ "be used as the fill character. Otherwise, spaces are used.]"
+"[X]#?[n:=2*sizeof(long long)?Floating point number represented in hexadecimal "
+ "notation. \an\a specifies the number of significant figures when the "
+ "value is expanded.]"
+
+#ifdef SHOPT_TYPEDEF
+"[h]:[string?Used within a type definition to provide a help string "
+ "for variable \aname\a. Otherwise, it is ignored.]"
+"[S?Used with a type definition to indicate that the variable is shared by "
+ "each instance of the type. When used inside a function defined "
+ "with the \bfunction\b reserved word, the specified variables "
+ "will have function static scope. Otherwise, the variable is "
+ "unset prior to processing the assignment list.]"
+#endif
+"[T]:?[tname?\atname\a is the name of a type name given to each \aname\a.]"
+"[Z]#?[n?Zero fill. If \an\a is given it represents the field width.]"
+"\n"
+"\n[name[=value]...]\n"
+" -f [name...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?No errors occurred.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\breadonly\b(1), \bexport\b(1)]"
+;
+
+const char sh_optulimit[] =
+"[-1c?@(#)$Id: ulimit (AT&T Research) 2003-06-21 $\n]"
+USAGE_LICENSE
+"[+NAME?ulimit - set or display resource limits]"
+"[+DESCRIPTION?\bulimit\b sets or displays resource limits. These "
+ "limits apply to the current process and to each child process "
+ "created after the resource limit has been set. If \alimit\a "
+ "is specified, the resource limit is set, otherwise, its current value "
+ "is displayed on standard output.]"
+"[+?Increasing the limit for a resource usually requires special privileges. "
+ "Some systems allow you to lower resource limits and later increase "
+ "them. These are called soft limits. Once a hard limit is "
+ "set the resource can not be increased.]"
+"[+?Different systems allow you to specify different resources and some "
+ "restrict how much you can raise the limit of the resource.]"
+"[+?The value of \alimit\a depends on the unit of the resource listed "
+ "for each resource. In addition, \alimit\a can be \bunlimited\b "
+ "to indicate no limit for that resource.]"
+"[+?If you do not specify \b-H\b or \b-S\b, then \b-S\b is used for "
+ "listing and both \b-S\b and \b-H\b are used for setting resources.]"
+"[+?If you do not specify any resource, the default is \b-f\b.]"
+"[H?A hard limit is set or displayed.]"
+"[S?A soft limit is set or displayed.]"
+"[a?Displays all current resource limits]"
+"\flimits\f"
+"\n"
+"\n[limit]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?A request for a higher limit was rejected or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\bulimit\b(2), \bgetrlimit\b(2)]"
+;
+
+const char sh_optumask[] =
+"[-1c?\n@(#)$Id: umask (AT&T Research) 1999-04-07 $\n]"
+USAGE_LICENSE
+"[+NAME?umask - get or set the file creation mask]"
+"[+DESCRIPTION?\bumask\b sets the file creation mask of the current "
+ "shell execution environment to the value specified by the "
+ "\amask\a operand. This mask affects the file permission bits "
+ "of subsequently created files. \amask\a can either be an "
+ "octal number or a symbolic value as described in \bchmod\b(1). "
+ "If a symbolic value is given, the new file creation mask is the "
+ "complement of the result of applying \amask\a to the complement "
+ "of the current file creation mask.]"
+"[+?If \amask\a is not specified, \bumask\b writes the value of the "
+ "file creation mask for the current process to standard output.]"
+"[S?Causes the file creation mask to be written or treated as a symbolic value "
+ "rather than an octal number.]"
+"\n"
+"\n[mask]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The file creation mask was successfully changed, or no "
+ "\amask\a operand was supplied.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bchmod\b(1)]"
+;
+const char sh_optuniverse[] = " [name]";
+const char sh_optunset[] =
+"[-1c?\n@(#)$Id: unset (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?unset - unset values and attributes of variables and functions]"
+"[+DESCRIPTION?For each \aname\a specified, \bunset\b unsets the variable, "
+ "or function if \b-f\b is specified, from the current shell "
+ "execution environment. Readonly variables cannot be unset.]"
+"[n?If \aname\a refers to variable that is a reference, the variable \aname\a "
+ "will be unset rather than the variable it references. Otherwise, "
+ "is is equivalent to \b-v\b.]"
+"[f?\aname\a refers to a function name and the shell will unset the "
+ "function definition.]"
+"[v?\aname\a refers to a variable name and the shell will unset it and "
+ "remove it from the environment. This is the default behavior.]"
+"\n"
+"\nname...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All \aname\as were successfully unset.]"
+ "[+>0?One or more \aname\a operands could not be unset "
+ "or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\btypeset\b(1)]"
+;
+
+const char sh_optunalias[] =
+"[-1c?\n@(#)$Id: unalias (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?unalias - remove alias definitions]"
+"[+DESCRIPTION?\bunalias\b removes the definition of each named alias "
+ "from the current shell execution environment, or all aliases if "
+ "\b-a\b is specified. It will not affect any commands that "
+ "have already been read and subsequently executed.]"
+"[a?Causes all alias definitions to be removed. \aname\a operands "
+ "are optional and ignored in this case.]"
+"\n"
+"\nname...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?\b-a\b was not specified and one or more \aname\a operands "
+ "did not have an alias definition, or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\balias\b(1)]"
+;
+
+const char sh_optwait[] =
+"[-1c?\n@(#)$Id: wait (AT&T Research) 1999-06-17 $\n]"
+USAGE_LICENSE
+"[+NAME?wait - wait for process or job completion]"
+"[+DESCRIPTION?\bwait\b with no operands, waits until all jobs "
+ "known to the invoking shell have terminated. If one or more "
+ "\ajob\a operands are specified, \bwait\b waits until all of them "
+ "have completed.]"
+_JOB_
+"[+?If one ore more \ajob\a operands is a process id or process group id "
+ "not known by the current shell environment, \bwait\b treats each "
+ "of them as if it were a process that exited with status 127.]"
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?If \await\a is invoked with one or more \ajob\as, and all of "
+ "them have terminated or were not known by the invoking shell, "
+ "the exit status of \bwait\b will be that of the last \ajob\a. "
+ "Otherwise, it will be one of the following:]{"
+ "[+0?\bwait\b utility was invoked with no operands and all "
+ "processes known by the invoking process have terminated.]"
+ "[+127?\ajob\a is a process id or process group id that is unknown "
+ "to the current shell environment.]"
+"}"
+
+"[+SEE ALSO?\bjobs\b(1), \bps\b(1)]"
+;
+
+#if SHOPT_FS_3D
+ const char sh_optvpath[] = " [top] [base]";
+ const char sh_optvmap[] = " [dir] [list]";
+#endif /* SHOPT_FS_3D */
+
+const char sh_optwhence[] =
+"[-1c?\n@(#)$Id: whence (AT&T Research) 2007-04-24 $\n]"
+USAGE_LICENSE
+"[+NAME?whence - locate a command and describe its type]"
+"[+DESCRIPTION?Without \b-v\b, \bwhence\b writes on standard output an "
+ "absolute pathname, if any, corresponding to \aname\a based "
+ "on the complete search order that the shell uses. If \aname\a "
+ "is not found, then no output is produced.]"
+"[+?If \b-v\b is specified, the output will also contain information "
+ "that indicates how the given \aname\a would be interpreted by "
+ "the shell in the current execution environment.]"
+"[a?Displays all uses for each \aname\a rather than the first.]"
+"[f?Do not check for functions.]"
+"[p?Do not check to see if \aname\a is a reserved word, a built-in, "
+ "an alias, or a function. This turns off the \b-v\b option.]"
+"[q?Quiet mode. Returns 0 if all arguments are built-ins, functions, or are "
+ "programs found on the path.]"
+"[v?For each name you specify, the shell displays a line that indicates "
+ "if that name is one of the following:]{"
+ "[+?Reserved word]"
+ "[+?Alias]"
+ "[+?Built-in]"
+ "[+?Undefined function]"
+ "[+?Function]"
+ "[+?Tracked alias]"
+ "[+?Program]"
+"}"
+"\n"
+"\nname ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Each \aname\a was found by the shell.]"
+ "[+1?One or more \aname\as were not found by the shell.]"
+ "[+>1?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bcommand\b(1)]"
+;
+
+
+const char e_alrm1[] = "alarm -r %s +%.3g\n";
+const char e_alrm2[] = "alarm %s %.3f\n";
+const char e_baddisc[] = "%s: invalid discipline function";
+const char e_nospace[] = "out of memory";
+const char e_nofork[] = "cannot fork";
+const char e_nosignal[] = "%s: unknown signal name";
+const char e_condition[] = "condition(s) required";
+const char e_cneedsarg[] = "-c requires argument";
diff --git a/src/cmd/ksh93/data/keywords.c b/src/cmd/ksh93/data/keywords.c
new file mode 100644
index 0000000..fed2cf0
--- /dev/null
+++ b/src/cmd/ksh93/data/keywords.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include "shell.h"
+#include "shlex.h"
+#include "FEATURE/options"
+
+/*
+ * table of reserved words in shell language
+ * This list must be in in ascii sorted order
+ */
+
+const Shtable_t shtab_reserved[] =
+{
+ "!", NOTSYM,
+ "[[", BTESTSYM,
+ "case", CASESYM,
+ "do", DOSYM,
+ "done", DONESYM,
+ "elif", ELIFSYM,
+ "else", ELSESYM,
+ "esac", ESACSYM,
+ "fi", FISYM,
+ "for", FORSYM,
+ "function", FUNCTSYM,
+ "if", IFSYM,
+ "in", INSYM,
+#if SHOPT_NAMESPACE
+ "namespace", NSPACESYM,
+#endif /* SHOPT_NAMESPACE */
+ "select", SELECTSYM,
+ "then", THENSYM,
+ "time", TIMESYM,
+ "until", UNTILSYM,
+ "while", WHILESYM,
+ "{", LBRACE,
+ "}", RBRACE,
+ "", 0,
+};
+
+const char e_unexpected[] = "unexpected";
+const char e_unmatched[] = "unmatched";
+const char e_endoffile[] = "end of file";
+const char e_newline[] = "newline";
+
diff --git a/src/cmd/ksh93/data/lexstates.c b/src/cmd/ksh93/data/lexstates.c
new file mode 100644
index 0000000..90938c1
--- /dev/null
+++ b/src/cmd/ksh93/data/lexstates.c
@@ -0,0 +1,417 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#include "FEATURE/options"
+#include "lexstates.h"
+
+
+/*
+ * This is the initial state for tokens
+ */
+static const char sh_lexstate0[256] =
+{
+ S_EOF, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+#if SHOPT_CRNL
+ S_REG, 0, S_NLTOK,S_REG, S_REG, 0, S_REG, S_REG,
+#else
+ S_REG, 0, S_NLTOK,S_REG, S_REG, S_REG, S_REG, S_REG,
+#endif /* SHOPT_CRNL */
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+
+ 0, S_REG, S_REG, S_COM, S_REG, S_REG, S_OP, S_REG,
+ S_OP, S_OP, S_REG, S_REG, S_REG, S_REG, S_NAME, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_OP, S_OP, S_REG, S_OP, S_REG,
+
+ S_REG, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+ S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+ S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+ S_NAME, S_NAME, S_NAME, S_REG, S_REG, S_REG, S_REG, S_NAME,
+
+ S_REG, S_NAME, S_NAME, S_RES, S_RES, S_RES, S_RES, S_NAME,
+#if SHOPT_NAMESPACE
+ S_NAME, S_RES, S_NAME, S_NAME, S_NAME, S_NAME, S_RES, S_NAME,
+#else
+ S_NAME, S_RES, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+#endif /* SHOPT_NAMESPACE */
+ S_NAME, S_NAME, S_NAME, S_RES, S_RES, S_RES, S_NAME, S_RES,
+ S_NAME, S_NAME, S_NAME, S_BRACE,S_OP, S_BRACE,S_TILDE,S_REG,
+
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+};
+
+/*
+ * This state is for identifiers
+ */
+static const char sh_lexstate1[256] =
+{
+ S_EOF, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+#if SHOPT_CRNL
+ S_REG, S_BREAK,S_BREAK,S_REG, S_REG, S_BREAK,S_REG, S_REG,
+#else
+ S_REG, S_BREAK,S_BREAK,S_REG, S_REG, S_REG, S_REG, S_REG,
+#endif /* SHOPT_CRNL */
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+
+ S_BREAK,S_EPAT, S_QUOTE,S_REG, S_DOL, S_EPAT, S_BREAK,S_LIT,
+ S_BREAK,S_BREAK,S_PAT, S_EPAT, S_REG, S_EPAT, S_DOT, S_REG,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_LABEL,S_BREAK,S_BREAK,S_EQ, S_BREAK,S_PAT,
+
+ S_EPAT, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_REG, S_REG, 0,
+
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACE,S_BREAK,S_BRACE,S_EPAT, S_REG,
+
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+};
+
+static const char sh_lexstate2[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+#if SHOPT_CRNL
+ 0, S_BREAK,S_BREAK,0, 0, S_BREAK,0, 0,
+#else
+ 0, S_BREAK,S_BREAK,0, 0, 0, 0, 0,
+#endif /* SHOPT_CRNL */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ S_BREAK,S_EPAT, S_QUOTE,0, S_DOL, S_EPAT, S_BREAK,S_LIT,
+ S_BREAK,S_BREAK,S_PAT, S_EPAT, 0, S_EPAT, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_COLON,S_BREAK,S_BREAK,0, S_BREAK,S_PAT,
+
+ S_EPAT, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_PAT, S_ESC, 0, 0, 0,
+
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACE,S_BREAK,S_BRACE,S_EPAT, 0,
+};
+
+/*
+ * for skipping over '...'
+ */
+static const char sh_lexstate3[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_NL, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, S_LIT,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, S_ESC2, 0, 0, 0
+};
+
+/*
+ * for skipping over "..." and `...`
+ */
+static const char sh_lexstate4[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_NL, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_QUOTE,0, S_DOL, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, S_ESC, 0, 0, 0,
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, S_RBRA, 0, 0
+};
+
+/*
+ * for skipping over ?(...), [...]
+ */
+static const char sh_lexstate5[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, S_BLNK, S_NL, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ S_BLNK, 0, S_QUOTE,0, S_DOL, 0, S_META, S_LIT,
+ S_PUSH, S_POP, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_POP, S_META, 0, S_META, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_POP, 0, 0,
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACE,S_META, S_POP, S_TILDE,0
+};
+
+/*
+ * Defines valid expansion characters
+ */
+static const char sh_lexstate6[256] =
+{
+ S_EOF, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+
+ S_ERR, S_SPC1, S_ERR, S_SPC1, S_SPC2, S_ERR, S_ERR, S_LIT,
+ S_PAR, S_ERR, S_SPC2, S_ERR, S_ERR, S_SPC2, S_ALP, S_ERR,
+ S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG,
+ S_DIG, S_DIG, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_SPC2,
+
+#if SHOPT_TYPEDEF
+ S_SPC1, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+#else
+ S_SPC2, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+#endif
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ERR, S_ERR, S_ERR, S_ERR, S_ALP,
+
+ S_ERR, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_LBRA, S_ERR, S_RBRA, S_ERR, S_ERR,
+
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+};
+
+/*
+ * for skipping over ${...} until modifier
+ */
+static const char sh_lexstate7[256] =
+{
+ S_EOF, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+
+ S_ERR, S_ERR, S_ERR, S_MOD2, S_ERR, S_MOD2, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_MOD1, S_MOD1, S_ERR, S_MOD1, S_DOT, S_MOD2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_MOD1, S_ERR, S_ERR, S_MOD1, S_ERR, S_MOD1,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_ERR, S_ERR, 0,
+
+ S_ERR, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_ERR, S_ERR, S_POP, S_ERR, S_ERR,
+
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+};
+
+/*
+ * This state is for $name
+ */
+static const char sh_lexstate8[256] =
+{
+ S_EOF, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+
+ S_EDOL, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_EDOL, S_EDOL, S_EDOL, S_EDOL, 0,
+
+ S_EDOL,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+};
+
+/*
+ * This is used for macro expansion
+ */
+static const char sh_lexstate9[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_QUOTE,0, S_DOL, 0, S_PAT, S_LIT,
+ S_PAT, S_PAT, S_PAT, 0, S_COM, 0, S_DOT, S_SLASH,
+ S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG,
+ S_DIG, S_DIG, S_COLON,0, 0, S_EQ, 0, S_PAT,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_ENDCH,0, 0,
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+#if SHOPT_BRACEPAT
+ 0, 0, 0, S_BRACE,S_PAT, S_ENDCH,0, 0
+#else
+ 0, 0, 0, 0, S_PAT, S_ENDCH,0, 0
+#endif /* SHOPT_BRACEPAT */
+};
+
+const char *sh_lexrstates[ST_NONE] =
+{
+ sh_lexstate0, sh_lexstate1, sh_lexstate2, sh_lexstate3,
+ sh_lexstate4, sh_lexstate5, sh_lexstate6, sh_lexstate7,
+ sh_lexstate8, sh_lexstate9, sh_lexstate5
+};
+
+
+const char e_lexversion[] = "%d: invalid binary script version";
+const char e_lexspace[] = "line %d: use space or tab to separate operators %c and %c";
+const char e_lexslash[] = "line %d: $ not preceded by \\";
+const char e_lexsyntax1[] = "syntax error at line %d: `%s' %s";
+const char e_lexsyntax2[] = "syntax error: `%s' %s";
+const char e_lexsyntax3[] = "syntax error at line %d: duplicate label %s";
+const char e_lexsyntax4[] = "syntax error at line %d: invalid reference list";
+const char e_lexsyntax5[] = "syntax error at line %d: `<<%s' here-document not contained within command substitution";
+const char e_lexwarnvar[] = "line %d: variable expansion makes arithmetic evaluation less efficient";
+const char e_lexlabignore[] = "line %d: label %s ignored";
+const char e_lexlabunknown[] = "line %d: %s unknown label";
+const char e_lexobsolete1[] = "line %d: `...` obsolete, use $(...)";
+const char e_lexobsolete2[] = "line %d: -a obsolete, use -e";
+const char e_lexobsolete3[] = "line %d: '=' obsolete, use '=='";
+const char e_lexobsolete4[] = "line %d: %s within [[...]] obsolete, use ((...))";
+const char e_lexobsolete5[] = "line %d: set %s obsolete";
+const char e_lexobsolete6[] = "line %d: `{' instead of `in' is obsolete";
+const char e_lexnonstandard[] = "line %d: `&>file' is nonstandard -- interpreted as `>file 2>&1' for profile input only";
+const char e_lexusebrace[] = "line %d: use braces to avoid ambiguities with $id[...]";
+const char e_lexusequote[] = "line %d: %c within ${} should be quoted";
+const char e_lexescape[] = "line %d: escape %c to avoid ambiguities";
+const char e_lexquote[] = "line %d: quote %c to avoid ambiguities";
+const char e_lexnested[] = "line %d: spaces required for nested subshell";
+const char e_lexbadchar[] = "%c: invalid character in expression - %s";
+const char e_lexfuture[] = "line %d: \\ in front of %c reserved for future use";
+const char e_lexlongquote[] = "line %d: %c quote may be missing";
+const char e_lexzerobyte[] = "zero byte";
+const char e_lexemptyfor[] = "line %d: empty for list";
+const char e_lextypeset[] = "line %d: %s invalid typeset option order";
+const char e_lexcharclass[] = "line %d: '^' as first character in character class not portable";
diff --git a/src/cmd/ksh93/data/limits.c b/src/cmd/ksh93/data/limits.c
new file mode 100644
index 0000000..9ce9968
--- /dev/null
+++ b/src/cmd/ksh93/data/limits.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include "ulimit.h"
+
+/*
+ * This is the list of resouce limits controlled by ulimit
+ * This command requires getrlimit(), vlimit(), or ulimit()
+ */
+
+#ifndef _no_ulimit
+
+const char e_unlimited[] = "unlimited";
+const char* e_units[] = { 0, "block", "byte", "kbyte", "second" };
+
+const int shtab_units[] = { 1, 512, 1, 1024, 1 };
+
+const Limit_t shtab_limits[] =
+{
+"as", "address space limit", RLIMIT_AS, 0, 'M', LIM_KBYTE,
+"core", "core file size", RLIMIT_CORE, 0, 'c', LIM_BLOCK,
+"cpu", "cpu time", RLIMIT_CPU, 0, 't', LIM_SECOND,
+"data", "data size", RLIMIT_DATA, 0, 'd', LIM_KBYTE,
+"fsize", "file size", RLIMIT_FSIZE, 0, 'f', LIM_BLOCK,
+"locks", "number of file locks", RLIMIT_LOCKS, 0, 'x', LIM_COUNT,
+"memlock", "locked address space", RLIMIT_MEMLOCK, 0, 'l', LIM_KBYTE,
+"msgqueue", "message queue size", RLIMIT_MSGQUEUE,0, 'q', LIM_KBYTE,
+"nice", "scheduling priority", RLIMIT_NICE, 0, 'e', LIM_COUNT,
+"nofile", "number of open files", RLIMIT_NOFILE, "OPEN_MAX", 'n', LIM_COUNT,
+"nproc", "number of processes", RLIMIT_NPROC, "CHILD_MAX", 'u', LIM_COUNT,
+"pipe", "pipe buffer size", RLIMIT_PIPE, "PIPE_BUF", 'p', LIM_BYTE,
+"rss", "max memory size", RLIMIT_RSS, 0, 'm', LIM_KBYTE,
+"rtprio", "max real time priority",RLIMIT_RTPRIO, 0, 'r', LIM_COUNT,
+"sbsize", "socket buffer size", RLIMIT_SBSIZE, "PIPE_BUF", 'b', LIM_BYTE,
+"sigpend", "signal queue size", RLIMIT_SIGPENDING,"SIGQUEUE_MAX",'i', LIM_COUNT,
+"stack", "stack size", RLIMIT_STACK, 0, 's', LIM_KBYTE,
+"swap", "swap size", RLIMIT_SWAP, 0, 'w', LIM_KBYTE,
+"threads", "number of threads", RLIMIT_PTHREAD, "THREADS_MAX", 'T', LIM_COUNT,
+"vmem", "process size", RLIMIT_VMEM, 0, 'v', LIM_KBYTE,
+{ 0 }
+};
+
+#endif
diff --git a/src/cmd/ksh93/data/math.tab b/src/cmd/ksh93/data/math.tab
new file mode 100644
index 0000000..3750c15
--- /dev/null
+++ b/src/cmd/ksh93/data/math.tab
@@ -0,0 +1,75 @@
+# <return type: i:integer f:floating-point> <#floating-point-args> <function-name> [<alias> ...]
+# <function-name>l variants are handled by features/math.sh
+# @(#)math.tab (AT&T Research) 2010-10-26
+f 1 acos
+f 1 acosh
+f 1 asin
+f 1 asinh
+f 1 atan
+f 2 atan2
+f 1 atanh
+f 1 cbrt
+f 1 ceil
+f 2 copysign
+f 1 cos
+f 1 cosh
+f 1 erf
+f 1 erfc
+f 1 exp
+f 1 exp2
+f 1 expm1
+f 1 fabs abs
+f 2 fdim
+f 1 finite
+f 1 floor int
+f 3 fma
+f 2 fmax
+f 2 fmin
+f 2 fmod
+i 1 fpclassify
+i 1 fpclass
+f 2 hypot
+i 1 ilogb
+i 1 isfinite
+i 2 isgreater
+i 2 isgreaterequal
+i 1 isinf
+i 1 isinfinite
+i 2 isless
+i 2 islessequal
+i 2 islessgreater
+i 1 isnan
+i 1 isnormal
+i 1 issubnormal fpclassify=FP_SUBNORMAL
+i 2 isunordered
+i 1 iszero fpclassify=FP_ZERO fpclass=FP_NZERO|FP_PZERO {return a1==0.0||a1==-0.0;}
+f 1 j0
+f 1 j1
+f 2 jn
+x 2 ldexp
+f 1 lgamma
+f 1 log
+f 1 log10
+f 1 log1p
+f 1 log2
+f 1 logb
+f 1 nearbyint
+f 2 nextafter
+f 2 nexttoward
+f 2 pow
+f 2 remainder
+f 1 rint
+f 1 round {Sfdouble_t r;Sflong_t y;y=floor(2*a1);r=rint(a1);if(2*a1==y)r+=(r<a1)-(a1<0);return r;}
+f 2 scalb
+f 2 scalbn
+i 1 signbit
+f 1 sin
+f 1 sinh
+f 1 sqrt
+f 1 tan
+f 1 tanh
+f 1 tgamma {Sfdouble_t r=exp(lgamma(a1));return (signgam<0)?-r:r;}
+f 1 trunc
+f 1 y0
+f 1 y1
+f 2 yn
diff --git a/src/cmd/ksh93/data/msg.c b/src/cmd/ksh93/data/msg.c
new file mode 100644
index 0000000..a4eead9
--- /dev/null
+++ b/src/cmd/ksh93/data/msg.c
@@ -0,0 +1,215 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ * S. R. Bourne
+ * Rewritten by David Korn
+ *
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <errno.h>
+#include "defs.h"
+#include "path.h"
+#include "io.h"
+#include "shlex.h"
+#include "timeout.h"
+#include "history.h"
+#include "builtins.h"
+#include "jobs.h"
+#include "edit.h"
+
+#include "FEATURE/cmds"
+
+/* error messages */
+const char e_timewarn[] = "\r\n\ashell will timeout in 60 seconds due to inactivity";
+const char e_runvi[] = "\\hist -e \"${VISUAL:-${EDITOR:-vi}}\" ";
+const char e_timeout[] = "timed out waiting for input";
+const char e_mailmsg[] = "you have mail in $_";
+const char e_query[] = "no query process";
+const char e_history[] = "no history file";
+const char e_histopen[] = "history file cannot open";
+const char e_option[] = "%s: bad option(s)";
+const char e_toomany[] = "open file limit exceeded";
+const char e_argtype[] = "invalid argument of type %c";
+const char e_oneoperand[] = "one operand expected";
+const char e_formspec[] = "%c: unknown format specifier";
+const char e_badregexp[] = "%s: invalid regular expression";
+const char e_number[] = "%s: bad number";
+const char e_badlocale[] = "%s: unknown locale";
+const char e_nullset[] = "%s: parameter null";
+const char e_notset[] = "%s: parameter not set";
+const char e_noparent[] = "%s: no parent";
+const char e_subst[] = "%s: bad substitution";
+const char e_create[] = "%s: cannot create";
+const char e_tmpcreate[] = "cannot create temporary file";
+const char e_restricted[] = "%s: restricted";
+const char e_pfsh[] = "%s: disabled in profile shell";
+const char e_pexists[] = "process already exists";
+const char e_exists[] = "%s: file already exists";
+const char e_pipe[] = "cannot create pipe";
+const char e_alarm[] = "cannot set alarm";
+const char e_open[] = "%s: cannot open";
+const char e_notseek[] = "%s: not seekable";
+const char e_badseek[] = "%s: invalid seek offset";
+const char e_badpattern[] = "%s: invalid shell pattern";
+const char e_noread[] = "%s: pattern seek requires read access";
+const char e_logout[] = "Use 'exit' to terminate this shell";
+const char e_exec[] = "%s: cannot execute";
+const char e_pwd[] = "cannot access parent directories";
+const char e_found[] = "%s: not found";
+const char e_defined[] = "%s: function not defined";
+const char e_nointerp[] = "%s: interpreter not found";
+const char e_subscript[] = "%s: subscript out of range";
+const char e_toodeep[] = "%s: recursion too deep";
+const char e_access[] = "permission denied";
+#ifdef _cmd_universe
+ const char e_nouniverse[] = "universe not accessible";
+#endif /* _cmd_universe */
+const char e_direct[] = "bad directory";
+const char e_file[] = "%s: bad file unit number";
+const char e_redirect[] = "redirection failed";
+const char e_trap[] = "%s: bad trap";
+const char e_readonly[] = "%s: is read only";
+const char e_badfield[] = "%d: negative field size";
+const char e_ident[] = "%s: is not an identifier";
+const char e_badname[] = "%s: invalid name";
+const char e_varname[] = "%s: invalid variable name";
+const char e_badfun[] = "%s: invalid function name";
+const char e_aliname[] = "%s: invalid alias name";
+const char e_badexport[] = "%s: only simple variables can be exported";
+const char e_badref[] = "%s: reference variable cannot be an array";
+const char e_badsubscript[] = "%c: invalid subscript in assignment";
+const char e_noarray[] = "%s: cannot be an array";
+const char e_badappend[] = "%s: invalid append to associative array";
+const char e_noref[] = "%s: no reference name";
+const char e_nounattr[] = "cannot unset attribute C or A or a";
+const char e_selfref[] = "%s: invalid self reference";
+const char e_globalref[] = "%s: global reference cannot refer to local variable";
+const char e_noalias[] = "%s: alias not found\n";
+const char e_format[] = "%s: bad format";
+const char e_redef[] = "%s: type cannot be redefined";
+const char e_required[] = "%s: is a required element of %s";
+const char e_badtformat[] = "%c: bad format character in time format";
+const char e_nolabels[] = "%s: label not implemented";
+const char e_notimp[] = "%s: not implemented";
+const char e_notelem[] = "%.*s: is not an element of %s";
+const char e_notenum[] = "%s: not an enumeration type";
+const char e_unknowntype[] = "%.*s: unknown type";
+const char e_unknownmap[] = "%s: unknown mapping name";
+const char e_mapchararg[] = "-M requires argument when operands are specified";
+const char e_subcomvar[] = "%s: compound assignment requires sub-variable name";
+const char e_badtypedef[] = "%s: type definition requires compound assignment";
+const char e_typecompat[] = "%s: array instance incompatible with type assignment";
+const char e_nosupport[] = "not supported";
+const char e_badrange[] = "%d-%d: invalid range";
+const char e_eneedsarg[] = "-e - requires single argument";
+const char e_badbase[] = "%s unknown base";
+const char e_loop[] = "%s: would cause loop";
+const char e_overlimit[] = "%s: limit exceeded";
+const char e_badsyntax[] = "incorrect syntax";
+const char e_badwrite[] = "write to %d failed";
+const char e_staticfun[] = "%s: defined as a static function in type %s and cannot be redefined";
+const char e_on [] = "on";
+const char e_off[] = "off";
+const char is_reserved[] = " is a keyword";
+const char is_builtin[] = " is a shell builtin";
+const char is_spcbuiltin[] = " is a special shell builtin";
+const char is_builtver[] = "is a shell builtin version of";
+const char is_alias[] = "%s is an alias for ";
+const char is_xalias[] = "%s is an exported alias for ";
+const char is_talias[] = "is a tracked alias for";
+const char is_function[] = " is a function";
+const char is_ufunction[] = " is an undefined function";
+#ifdef JOBS
+# ifdef SIGTSTP
+ const char e_newtty[] = "Switching to new tty driver...";
+ const char e_oldtty[] = "Reverting to old tty driver...";
+ const char e_no_start[] = "Cannot start job control";
+# endif /*SIGTSTP */
+ const char e_no_jctl[] = "No job control";
+ const char e_terminate[] = "You have stopped jobs";
+ const char e_done[] = " Done";
+ const char e_nlspace[] = "\n ";
+ const char e_running[] = " Running";
+ const char e_ambiguous[] = "%s: Ambiguous";
+ const char e_jobsrunning[] = "You have running jobs";
+ const char e_no_job[] = "no such job";
+ const char e_no_proc[] = "no such process";
+ const char e_badpid[] = "%s: invalid process id";
+# if SHOPT_COSHELL
+ const char e_jobusage[] = "%s: Arguments must be %%job, process ids, or job pool names";
+# else
+ const char e_jobusage[] = "%s: Arguments must be %%job or process ids";
+# endif /* SHOPT_COSHELL */
+#endif /* JOBS */
+const char e_coredump[] = "(coredump)";
+const char e_alphanum[] = "[_[:alpha:]]*([_[:alnum:]])";
+const char e_devfdNN[] = "/dev/fd/+([0-9])";
+const char e_devfdstd[] = "/dev/@(fd/+([0-9])|std@(in|out|err))";
+const char e_signo[] = "Signal %d";
+#if SHOPT_FS_3D
+ const char e_cantget[] = "cannot get %s";
+ const char e_cantset[] = "cannot set %s";
+ const char e_mapping[] = "mapping";
+ const char e_versions[] = "versions";
+#endif /* SHOPT_FS_3D */
+
+/* string constants */
+const char e_heading[] = "Current option settings";
+const char e_sptbnl[] = " \t\n";
+const char e_tolower[] = "tolower";
+const char e_toupper[] = "toupper";
+const char e_defpath[] = "/bin:/usr/bin:";
+const char e_defedit[] = _pth_ed;
+const char e_unknown [] = "<command unknown>";
+const char e_devnull[] = "/dev/null";
+const char e_traceprompt[] = "+ ";
+const char e_supprompt[] = "# ";
+const char e_stdprompt[] = "$ ";
+const char e_profile[] = "$HOME/.profile";
+const char e_sysprofile[] = "/etc/profile";
+const char e_suidprofile[] = "/etc/suid_profile";
+#if SHOPT_SYSRC
+const char e_sysrc[] = "/etc/ksh.kshrc";
+#endif
+#if SHOPT_BASH
+#if SHOPT_SYSRC
+const char e_bash_sysrc[] = "/etc/bash.bashrc";
+#endif
+const char e_bash_rc[] = "$HOME/.bashrc";
+const char e_bash_login[] = "$HOME/.bash_login";
+const char e_bash_logout[] = "$HOME/.bash_logout";
+const char e_bash_profile[] = "$HOME/.bash_profile";
+#endif
+const char e_crondir[] = "/usr/spool/cron/atjobs";
+const char e_prohibited[] = "login setuid/setgid shells prohibited";
+#if SHOPT_SUID_EXEC
+ const char e_suidexec[] = "/etc/suid_exec";
+#endif /* SHOPT_SUID_EXEC */
+const char hist_fname[] = "/.sh_history";
+const char e_dot[] = ".";
+const char e_envmarker[] = "A__z";
+const char e_timeformat[] = "\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS";
+const char e_dict[] = "libshell";
+const char e_funload[] = "function, built-in or type definition for %s not found in %s";
diff --git a/src/cmd/ksh93/data/options.c b/src/cmd/ksh93/data/options.c
new file mode 100644
index 0000000..73617f1
--- /dev/null
+++ b/src/cmd/ksh93/data/options.c
@@ -0,0 +1,149 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "defs.h"
+#include "name.h"
+#include "shtable.h"
+
+#if SHOPT_BASH
+# define bashopt(a,b) a, b|SH_BASHOPT,
+# define bashextra(a,b) a, b|SH_BASHEXTRA,
+#else
+# define bashopt(a,b)
+# define bashextra(a,b)
+#endif
+
+/*
+ * This is the list of invocation and set options
+ * This list must be in in ascii sorted order
+ */
+
+const Shtable_t shtab_options[] =
+{
+ "allexport", SH_ALLEXPORT,
+#if SHOPT_BASH
+ "bash", (SH_BASH|SH_COMMANDLINE),
+#endif
+ "bgnice", SH_BGNICE,
+ "braceexpand", SH_BRACEEXPAND,
+ bashopt("cdable_vars", SH_CDABLE_VARS)
+ bashopt("cdspell", SH_CDSPELL)
+ bashopt("checkhash", SH_CHECKHASH)
+ bashopt("checkwinsize", SH_CHECKWINSIZE)
+ "noclobber", SH_NOCLOBBER,
+ bashopt("dotglob", SH_DOTGLOB)
+ "emacs", SH_EMACS,
+ "errexit", SH_ERREXIT,
+ "noexec", SH_NOEXEC,
+ bashopt("execfail", SH_EXECFAIL)
+ bashopt("expand_aliases", SH_EXPAND_ALIASES)
+ bashopt("extglob", SH_EXTGLOB)
+ "noglob", SH_NOGLOB,
+ "globstar", SH_GLOBSTARS,
+ "gmacs", SH_GMACS,
+ bashextra("hashall", SH_TRACKALL)
+ bashopt("histappend", SH_HISTAPPEND)
+#if SHOPT_HISTEXPAND
+ "histexpand", SH_HISTEXPAND,
+#else
+ bashextra("histexpand", SH_HISTEXPAND)
+#endif
+ bashextra("history", SH_HISTORY2)
+ bashopt("histreedit", SH_HISTREEDIT)
+ bashopt("histverify", SH_HISTVERIFY)
+ bashopt("hostcomplete", SH_HOSTCOMPLETE)
+ bashopt("huponexit", SH_HUPONEXIT)
+ "ignoreeof", SH_IGNOREEOF,
+ "interactive", SH_INTERACTIVE|SH_COMMANDLINE,
+ bashextra("interactive_comments", SH_INTERACTIVE_COMM)
+ "keyword", SH_KEYWORD,
+ "letoctal", SH_LETOCTAL,
+ bashopt("lithist", SH_LITHIST)
+ "nolog", SH_NOLOG,
+ "login_shell", SH_LOGIN_SHELL|SH_COMMANDLINE,
+ bashopt("mailwarn", SH_MAILWARN)
+ "markdirs", SH_MARKDIRS,
+ "monitor", SH_MONITOR,
+ "multiline", SH_MULTILINE,
+ bashopt("no_empty_cmd_completion", SH_NOEMPTYCMDCOMPL)
+ bashopt("nocaseglob", SH_NOCASEGLOB)
+ "notify", SH_NOTIFY,
+ bashopt("nullglob", SH_NULLGLOB)
+ bashextra("onecmd", SH_TFLAG)
+ "pipefail", SH_PIPEFAIL,
+ bashextra("physical", SH_PHYSICAL)
+ bashextra("posix", SH_POSIX)
+ "privileged", SH_PRIVILEGED,
+#if SHOPT_BASH
+ "profile", SH_LOGIN_SHELL|SH_COMMANDLINE,
+# if SHOPT_PFSH
+ "pfsh", SH_PFSH|SH_COMMANDLINE,
+# endif
+#else
+# if SHOPT_PFSH
+ "profile", SH_PFSH|SH_COMMANDLINE,
+# endif
+#endif
+ bashopt("progcomp", SH_PROGCOMP)
+ bashopt("promptvars", SH_PROMPTVARS)
+ "rc", SH_RC|SH_COMMANDLINE,
+ "restricted", SH_RESTRICTED,
+ bashopt("restricted_shell", SH_RESTRICTED2|SH_COMMANDLINE)
+ bashopt("shift_verbose", SH_SHIFT_VERBOSE)
+ "showme", SH_SHOWME,
+ bashopt("sourcepath", SH_SOURCEPATH)
+ "trackall", SH_TRACKALL,
+ "nounset", SH_NOUNSET,
+ "verbose", SH_VERBOSE,
+ "vi", SH_VI,
+ "viraw", SH_VIRAW,
+ bashopt("xpg_echo", SH_XPG_ECHO)
+ "xtrace", SH_XTRACE,
+ "", 0
+};
+
+const Shtable_t shtab_attributes[] =
+{
+ {"-Sshared", NV_REF|NV_TAGGED},
+ {"-nnameref", NV_REF},
+ {"-xexport", NV_EXPORT},
+ {"-rreadonly", NV_RDONLY},
+ {"-ttagged", NV_TAGGED},
+ {"-Aassociative array", NV_ARRAY},
+ {"-aindexed array", NV_ARRAY},
+ {"-llong", (NV_DOUBLE|NV_LONG)},
+ {"-Eexponential",(NV_DOUBLE|NV_EXPNOTE)},
+ {"-Xhexfloat", (NV_DOUBLE|NV_HEXFLOAT)},
+ {"-Ffloat", NV_DOUBLE},
+ {"-llong", (NV_INTEGER|NV_LONG)},
+ {"-sshort", (NV_INTEGER|NV_SHORT)},
+ {"-uunsigned", (NV_INTEGER|NV_UNSIGN)},
+ {"-iinteger", NV_INTEGER},
+ {"-Hfilename", NV_HOST},
+ {"-bbinary", NV_BINARY},
+ {"-ltolower", NV_UTOL},
+ {"-utoupper", NV_LTOU},
+ {"-Zzerofill", NV_ZFILL},
+ {"-Lleftjust", NV_LJUST},
+ {"-Rrightjust", NV_RJUST},
+ {"++namespace", NV_TABLE},
+ {"", 0}
+};
diff --git a/src/cmd/ksh93/data/signals.c b/src/cmd/ksh93/data/signals.c
new file mode 100644
index 0000000..802fe97
--- /dev/null
+++ b/src/cmd/ksh93/data/signals.c
@@ -0,0 +1,244 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#include "defs.h"
+
+#if defined(SIGCLD) && !defined(SIGCHLD)
+# define SIGCHLD SIGCLD
+#endif
+
+#define VAL(sig,mode) ((sig+1)|((mode)<<SH_SIGBITS))
+#define TRAP(n) (((n)|SH_TRAP)-1)
+
+#ifndef ERROR_dictionary
+# define ERROR_dictionary(s) (s)
+#endif
+#define S(s) ERROR_dictionary(s)
+
+/*
+ * This is a table that gives numbers and default settings to each signal.
+ * The signal numbers go in the low bits and the attributes go in the high bits.
+ * The names must be ASCII sorted lo-hi.
+ */
+
+const struct shtable2 shtab_signals[] =
+{
+#ifdef SIGABRT
+ "ABRT", VAL(SIGABRT,SH_SIGDONE), S("Abort"),
+#endif /*SIGABRT */
+#ifdef SIGAIO
+ "AIO", VAL(SIGAIO,SH_SIGIGNORE), S("Asynchronous I/O"),
+#endif /*SIGAIO */
+#ifdef SIGALRM
+ "ALRM", VAL(SIGALRM,SH_SIGDONE), S("Alarm call"),
+#endif /* SIGALRM */
+#ifdef SIGALRM1
+ "ALRM1", VAL(SIGALRM1,SH_SIGDONE), S("Scheduling - reserved"),
+#endif /* SIGALRM */
+#ifdef SIGAPOLLO
+ "APOLLO", VAL(SIGAPOLLO,0), S("SIGAPOLLO"),
+#endif /* SIGAPOLLO */
+#ifdef SIGBUS
+ "BUS", VAL(SIGBUS,SH_SIGDONE), S("Bus error"),
+#endif /* SIGBUS */
+#ifdef SIGCANCEL
+ "CANCEL", VAL(SIGCANCEL,SH_SIGIGNORE), S("Thread cancellation"),
+#endif /*SIGCANCEL */
+#ifdef SIGCHLD
+ "CHLD", VAL(SIGCHLD,SH_SIGFAULT), S("Death of Child"),
+# ifdef SIGCLD
+# if SIGCLD!=SIGCHLD
+ "CLD", VAL(SIGCLD,SH_SIGFAULT), S("Death of Child"),
+# endif
+# endif /* SIGCLD */
+#else
+# ifdef SIGCLD
+ "CLD", VAL(SIGCLD,SH_SIGFAULT), S("Death of Child"),
+# endif /* SIGCLD */
+#endif /* SIGCHLD */
+#ifdef SIGCONT
+ "CONT", VAL(SIGCONT,SH_SIGIGNORE), S("Stopped process continued"),
+#endif /* SIGCONT */
+#ifdef SIGCPUFAIL
+ "CPUFAIL", VAL(SIGCPUFAIL,0), S("Predictive processor deconfiguration"),
+#endif /* SIGRETRACT */
+ "DEBUG", VAL(TRAP(SH_DEBUGTRAP),0), "",
+#ifdef SIGDANGER
+ "DANGER", VAL(SIGDANGER,0), S("System crash soon"),
+#endif /* SIGDANGER */
+#ifdef SIGDIL
+ "DIL", VAL(SIGDIL,0), S("DIL signal"),
+#endif /* SIGDIL */
+#ifdef SIGEMT
+ "EMT", VAL(SIGEMT,SH_SIGDONE), S("EMT trap"),
+#endif /* SIGEMT */
+ "ERR", VAL(TRAP(SH_ERRTRAP),0), "",
+#ifdef SIGERR
+ "ERR", VAL(SIGERR,0), "",
+#endif /* SIGERR */
+ "EXIT", VAL(0,0), "",
+ "FPE", VAL(SIGFPE,SH_SIGDONE), S("Floating exception"),
+#ifdef SIGFREEZE
+ "FREEZE", VAL(SIGFREEZE,SH_SIGIGNORE), S("Special signal used by CPR"),
+#endif /* SIGFREEZE */
+#ifdef SIGGRANT
+ "GRANT", VAL(SIGGRANT,0), S("Grant monitor mode"),
+#endif /* SIGGRANT */
+ "HUP", VAL(SIGHUP,SH_SIGDONE), S("Hangup"),
+ "ILL", VAL(SIGILL,SH_SIGDONE), S("Illegal instruction"),
+#ifdef JOBS
+ "INT", VAL(SIGINT,SH_SIGINTERACTIVE), S("Interrupt"),
+#else
+ "INT", VAL(SIGINT,SH_SIGINTERACTIVE), "",
+#endif /* JOBS */
+#ifdef SIGIO
+ "IO", VAL(SIGIO,SH_SIGDONE), S("IO signal"),
+#endif /* SIGIO */
+#ifdef SIGIOT
+ "IOT", VAL(SIGIOT,SH_SIGDONE), S("Abort"),
+#endif /* SIGIOT */
+#ifdef SIGJVM1
+ "JVM1", VAL(SIGJVM1,SH_SIGIGNORE), S("Special signal used by Java Virtual Machine"),
+#endif /*SIGJVM1 */
+#ifdef SIGJVM2
+ "JVM2", VAL(SIGJVM2,SH_SIGIGNORE), S("Special signal used by Java Virtual Machine"),
+#endif /*SIGJVM2 */
+ "KEYBD", VAL(TRAP(SH_KEYTRAP),0), "",
+#ifdef SIGKILL
+ "KILL", VAL(SIGKILL,0), S("Killed"),
+#endif /* SIGKILL */
+#ifdef SIGLAB
+ "LAB", VAL(SIGLAB,0), S("Security label changed"),
+#endif /* SIGLAB */
+#ifdef SIGLOST
+ "LOST", VAL(SIGLOST,SH_SIGDONE), S("Resources lost"),
+#endif /* SIGLOST */
+#ifdef SIGLWP
+ "LWP", VAL(SIGLWP,SH_SIGIGNORE), S("Special signal used by thread library"),
+#endif /* SIGLWP */
+#ifdef SIGMIGRATE
+ "MIGRATE", VAL(SIGMIGRATE,0), S("Migrate process"),
+#endif /* SIGMIGRATE */
+#ifdef SIGMSG
+ "MSG", VAL(SIGMSG,0), S("Ring buffer input data"),
+#endif /* SIGMSG */
+#ifdef SIGPHONE
+ "PHONE", VAL(SIGPHONE,0), S("Phone interrupt"),
+#endif /* SIGPHONE */
+#ifdef SIGPIPE
+#ifdef JOBS
+ "PIPE", VAL(SIGPIPE,SH_SIGDONE), S("Broken Pipe"),
+#else
+ "PIPE", VAL(SIGPIPE,SH_SIGDONE), "",
+#endif /* JOBS */
+#endif /* SIGPIPE */
+#ifdef SIGPOLL
+ "POLL", VAL(SIGPOLL,SH_SIGDONE), S("Polling alarm"),
+#endif /* SIGPOLL */
+#ifdef SIGPROF
+ "PROF", VAL(SIGPROF,SH_SIGDONE), S("Profiling time alarm"),
+#endif /* SIGPROF */
+#ifdef SIGPRE
+ "PRE", VAL(SIGPRE,SH_SIGDONE), S("Programming exception"),
+#endif /* SIGPRE */
+#ifdef SIGPWR
+# if SIGPWR>0
+ "PWR", VAL(SIGPWR,SH_SIGIGNORE), S("Power fail"),
+# endif
+#endif /* SIGPWR */
+#ifdef SIGQUIT
+ "QUIT", VAL(SIGQUIT,SH_SIGDONE|SH_SIGINTERACTIVE), S("Quit"),
+#endif /* SIGQUIT */
+#ifdef SIGRETRACT
+ "RETRACT", VAL(SIGRETRACT,0), S("Relinquish monitor mode"),
+#endif /* SIGRETRACT */
+#ifdef SIGRTMIN
+ "RTMIN", VAL(SH_SIGRTMIN,SH_SIGRUNTIME), S("Lowest priority realtime signal"),
+#endif /* SIGRTMIN */
+#ifdef SIGRTMAX
+ "RTMAX", VAL(SH_SIGRTMAX,SH_SIGRUNTIME), S("Highest priority realtime signal"),
+#endif /* SIGRTMAX */
+#ifdef SIGSAK
+ "SAK", VAL(SIGSAK,0), S("Secure attention key"),
+#endif /* SIGSAK */
+ "SEGV", VAL(SIGSEGV,0), S("Memory fault"),
+#ifdef SIGSOUND
+ "SOUND", VAL(SIGSOUND,0), S("Sound completed"),
+#endif /* SIGSOUND */
+#ifdef SIGSTOP
+ "STOP", VAL(SIGSTOP,0), S("Stopped (SIGSTOP)"),
+#endif /* SIGSTOP */
+#ifdef SIGSYS
+ "SYS", VAL(SIGSYS,SH_SIGDONE), S("Bad system call"),
+#endif /* SIGSYS */
+ "TERM", VAL(SIGTERM,SH_SIGDONE|SH_SIGINTERACTIVE), S("Terminated"),
+#ifdef SIGTHAW
+ "THAW", VAL(SIGTHAW,SH_SIGIGNORE), S("Special signal used by CPR"),
+#endif /* SIGTHAW */
+#ifdef SIGTINT
+# ifdef JOBS
+ "TINT", VAL(SIGTINT,0), S("Interrupt"),
+# else
+ "TINT", VAL(SIGTINT,0), "",
+# endif /* JOBS */
+#endif /* SIGTINT */
+#ifdef SIGTRAP
+ "TRAP", VAL(SIGTRAP,SH_SIGDONE), S("Trace/BPT trap"),
+#endif /* SIGTRAP */
+#ifdef SIGTSTP
+ "TSTP", VAL(SIGTSTP,0), S("Stopped"),
+#endif /* SIGTSTP */
+#ifdef SIGTTIN
+ "TTIN", VAL(SIGTTIN,0), S("Stopped (SIGTTIN)"),
+#endif /* SIGTTIN */
+#ifdef SIGTTOU
+ "TTOU", VAL(SIGTTOU,0), S("Stopped (SIGTTOU)"),
+#endif /* SIGTTOU */
+#ifdef SIGURG
+ "URG", VAL(SIGURG,SH_SIGIGNORE), S("Socket interrupt"),
+#endif /* SIGURG */
+#ifdef SIGUSR1
+ "USR1", VAL(SIGUSR1,SH_SIGDONE), S("User signal 1"),
+#endif /* SIGUSR1 */
+#ifdef SIGUSR2
+ "USR2", VAL(SIGUSR2,SH_SIGDONE), S("User signal 2"),
+#endif /* SIGUSR2 */
+#ifdef SIGVIRT
+ "VIRT", VAL(SIGVIRT,0), S("Virtual timer alarm"),
+#endif /* SIGVIRT */
+#ifdef SIGVTALRM
+ "VTALRM", VAL(SIGVTALRM,SH_SIGDONE), S("Virtual time alarm"),
+#endif /* SIGVTALRM */
+#ifdef SIGWAITING
+ "WAITING", VAL(SIGWAITING,SH_SIGIGNORE), S("All threads blocked"),
+#endif /* SIGWAITING */
+#ifdef SIGWINCH
+ "WINCH", VAL(SIGWINCH,SH_SIGIGNORE), S("Window size change"),
+#endif /* SIGWINCH */
+#ifdef SIGXCPU
+ "XCPU", VAL(SIGXCPU,SH_SIGDONE|SH_SIGINTERACTIVE), S("Exceeded CPU time limit"),
+#endif /* SIGXCPU */
+#ifdef SIGXFSZ
+ "XFSZ", VAL(SIGXFSZ,SH_SIGDONE|SH_SIGINTERACTIVE), S("Exceeded file size limit"),
+#endif /* SIGXFSZ */
+#ifdef SIGXRES
+ "XRES", VAL(SIGXRES,SH_SIGDONE|SH_SIGINTERACTIVE), S("Exceeded resource control"),
+#endif /* SIGRES */
+ "", 0, 0
+};
diff --git a/src/cmd/ksh93/data/strdata.c b/src/cmd/ksh93/data/strdata.c
new file mode 100644
index 0000000..976c850
--- /dev/null
+++ b/src/cmd/ksh93/data/strdata.c
@@ -0,0 +1,104 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * data for string evaluator library
+ */
+
+#include <ast_standards.h>
+#include "FEATURE/options"
+#include "streval.h"
+
+const unsigned char strval_precedence[35] =
+ /* opcode precedence,assignment */
+{
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DONE */ 0|NOASSIGN|RASSOC,
+ /* NEQ */ 10|NOASSIGN,
+ /* NOT */ MAXPREC|NOASSIGN,
+ /* MOD */ 14,
+ /* ANDAND */ 6|NOASSIGN|SEQPOINT,
+ /* AND */ 9|NOFLOAT,
+ /* LPAREN */ MAXPREC|NOASSIGN|SEQPOINT,
+ /* RPAREN */ 1|NOASSIGN|RASSOC|SEQPOINT,
+ /* POW */ 14|NOASSIGN|RASSOC,
+ /* TIMES */ 14,
+ /* PLUSPLUS */ 15|NOASSIGN|NOFLOAT|SEQPOINT,
+ /* PLUS */ 13,
+ /* COMMA */ 1|NOASSIGN|SEQPOINT,
+ /* MINUSMINUS */ 15|NOASSIGN|NOFLOAT|SEQPOINT,
+ /* MINUS */ 13,
+ /* DIV */ 14,
+ /* LSHIFT */ 12|NOFLOAT,
+ /* LE */ 11|NOASSIGN,
+ /* LT */ 11|NOASSIGN,
+ /* EQ */ 10|NOASSIGN,
+ /* ASSIGNMENT */ 2|RASSOC,
+ /* COLON */ 0|NOASSIGN,
+ /* RSHIFT */ 12|NOFLOAT,
+ /* GE */ 11|NOASSIGN,
+ /* GT */ 11|NOASSIGN,
+ /* QCOLON */ 3|NOASSIGN|SEQPOINT,
+ /* QUEST */ 3|NOASSIGN|SEQPOINT|RASSOC,
+ /* XOR */ 8|NOFLOAT,
+ /* OROR */ 5|NOASSIGN|SEQPOINT,
+ /* OR */ 7|NOFLOAT,
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DEFAULT */ MAXPREC|NOASSIGN
+};
+
+/*
+ * This is for arithmetic expressions
+ */
+const char strval_states[64] =
+{
+ A_EOF, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG,
+ A_REG, 0, 0, A_REG, A_REG, A_REG, A_REG, A_REG,
+ A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG,
+ A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG,
+
+ 0, A_NOT, 0, A_REG, A_REG, A_MOD, A_AND, A_LIT,
+ A_LPAR, A_RPAR, A_TIMES,A_PLUS, A_COMMA,A_MINUS,A_DOT, A_DIV,
+ A_DIG, A_DIG, A_DIG, A_DIG, A_DIG, A_DIG, A_DIG, A_DIG,
+ A_DIG, A_DIG, A_COLON,A_REG, A_LT, A_ASSIGN,A_GT, A_QUEST
+
+};
+
+
+const char e_argcount[] = "%s: function has wrong number of arguments";
+const char e_badnum[] = "%s: bad number";
+const char e_moretokens[] = "%s: more tokens expected";
+const char e_paren[] = "%s: unbalanced parenthesis";
+const char e_badcolon[] = "%s: invalid use of :";
+const char e_divzero[] = "%s: divide by zero";
+const char e_synbad[] = "%s: arithmetic syntax error";
+const char e_notlvalue[] = "%s: assignment requires lvalue";
+const char e_recursive[] = "%s: recursion too deep";
+const char e_questcolon[] = "%s: ':' expected for '?' operator";
+const char e_function[] = "%s: unknown function";
+const char e_incompatible[] = "%s: invalid floating point operation";
+const char e_overflow[] = "%s: overflow exception";
+const char e_domain[] = "%s: domain exception";
+const char e_singularity[] = "%s: singularity exception";
+const char e_charconst[] = "%s: invalid character constant";
+
+#include "FEATURE/math"
diff --git a/src/cmd/ksh93/data/testops.c b/src/cmd/ksh93/data/testops.c
new file mode 100644
index 0000000..fa07d59
--- /dev/null
+++ b/src/cmd/ksh93/data/testops.c
@@ -0,0 +1,174 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * tables for the test builin [[...]] and [...]
+ */
+
+#include <ast.h>
+
+#include "defs.h"
+#include "test.h"
+
+/*
+ * This is the list of binary test and [[...]] operators
+ */
+
+const Shtable_t shtab_testops[] =
+{
+ "!=", TEST_SNE,
+ "-a", TEST_AND,
+ "-ef", TEST_EF,
+ "-eq", TEST_EQ,
+ "-ge", TEST_GE,
+ "-gt", TEST_GT,
+ "-le", TEST_LE,
+ "-lt", TEST_LT,
+ "-ne", TEST_NE,
+ "-nt", TEST_NT,
+ "-o", TEST_OR,
+ "-ot", TEST_OT,
+ "=", TEST_SEQ,
+ "==", TEST_SEQ,
+ "=~", TEST_REP,
+ "<", TEST_SLT,
+ ">", TEST_SGT,
+ "]]", TEST_END,
+ "", 0
+};
+
+const char sh_opttest[] =
+"[-1c?\n@(#)$Id: test (AT&T Research) 2003-03-18 $\n]"
+USAGE_LICENSE
+"[+NAME?test - evaluate expression]"
+"[+DESCRIPTION?\btest\b evaluates expressions and indicates its "
+ "results based on the exit status. Option parsing is not "
+ "performed so that all arguments, including \b--\b are processed "
+ " as operands. The evaluation of the "
+ "expression depends on the number of operands as follows:]{"
+ "[+0?Evaluates to false.]"
+ "[+1?True if argument is not an empty string.]"
+ "[+2?If first operand is \b!\b, the result is True if the second "
+ "operand an empty string. Otherwise, it is evaluated "
+ "as one of the unary expressions defined below. If the "
+ "unary operator is invalid and the second argument is \b--\b,"
+ "then the first argument is processed as an option argument.]"
+ "[+3?If first operand is \b!\b, the result is True if the second "
+ "and third operand evaluated as a unary expression is False. "
+ "Otherwise, the three operands are evaluaged as one of the "
+ "binary expressions listed below.]"
+ "[+4?If first operand is \b!\b, the result is True if the next "
+ "three operands are a valid binary expression that is False.]"
+"}"
+"[If any \afile\a is of the form \b/dev/fd/\b\an\a, then file descriptor "
+ "\an\a is checked.]"
+"[+?Unary expressions can be one of the following:]{"
+ "[+-a \afile\a?True if \afile\a exists, obsolete.]"
+ "[+-b \afile\a?True if \afile\a exists and is a block special file.]"
+ "[+-c \afile\a?True if \afile\a exists and is a character special "
+ "file.]"
+ "[+-d \afile\a?True if \afile\a exists and is a directory.]"
+ "[+-e \afile\a?True if \afile\a exists.]"
+ "[+-f \afile\a?True if \afile\a exists and is a regular file.]"
+ "[+-g \afile\a?True if \afile\a exists and has its set-group-id bit "
+ "set.]"
+ "[+-h \afile\a?True if \afile\a exists and is a symbolic link.]"
+ "[+-k \afile\a?True if \afile\a exists and has its sticky bit on.]"
+#if SHOPT_TEST_L
+ "[+-l \afile\a?True if \afile\a exists and is a symbolic link.]"
+#endif
+ "[+-n \astring\a?True if length of \astring\a is non-zero.]"
+ "[+-o \aoption\a?True if the shell option \aoption\a is enabled.]"
+ "[+-p \afile\a?True if \afile\a exists and is a pipe or fifo.]"
+ "[+-r \afile\a?True if \afile\a exists and is readable.]"
+ "[+-s \afile\a?True if \afile\a exists and has size > 0.]"
+ "[+-t \afildes\a?True if file descriptor number \afildes\a is "
+ "open and is associated with a terminal device.]"
+ "[+-u \afile\a?True if \afile\a exists and has its set-user-id bit "
+ "set.]"
+ "[+-v \avarname\a?True if \avarname\a is a valid variable name that is set.]"
+ "[+-w \afile\a?True if \afile\a exists and is writable.]"
+ "[+-x \afile\a?True if \afile\a exists and is executable. For a "
+ "directory it means that it can be searched.]"
+ "[+-z \astring\a?True if \astring\a is a zero length string.]"
+ "[+-G \afile\a?True if \afile\a exists and group is the effective "
+ "group id of the current process.]"
+ "[+-L \afile\a?True if \afile\a exists and is a symbolic link.]"
+ "[+-N \afile\a?True if \afile\a exists and has been modified since "
+ "it was last read.]"
+ "[+-O \afile\a?True if \afile\a exists and owner is the effective "
+ "user id of the current process.]"
+ "[+-R \avarname\a?True if \avarname\a is a name reference.]"
+ "[+-S \afile\a?True if \afile\a exists and is a socket.]"
+#if SHOPT_FS_3D
+ "[+-V \afile\a?True if \afile\a exists and is a version "
+ "directory.]"
+#endif /* SHOPT_FS_3D */
+"}"
+"[+?Binary expressions can be one of the following:]{"
+ "[+\astring1\a = \astring2\a?True if \astring1\a is equal to "
+ "\astring2\a.]"
+ "[+\astring1\a == \astring2\a?True if \astring1\a is equal to "
+ "\astring2\a.]"
+ "[+\astring1\a != \astring2\a?True if \astring1\a is not equal to "
+ "\astring2\a.]"
+ "[+\anum1\a -eq \anum2\a?True if numerical value of \anum1\a is "
+ "equal to \anum2\a.]"
+ "[+\anum1\a -ne \anum2\a?True if numerical value of \anum1\a is not "
+ "equal to \anum2\a.]"
+ "[+\anum1\a -lt \anum2\a?True if numerical value of \anum1\a is less "
+ "than \anum2\a.]"
+ "[+\anum1\a -le \anum2\a?True if numerical value of \anum1\a is less "
+ "than or equal to \anum2\a.]"
+ "[+\anum1\a -gt \anum2\a?True if numerical value of \anum1\a is "
+ "greater than \anum2\a.]"
+ "[+\anum1\a -ge \anum2\a?True if numerical value of \anum1\a is "
+ "greater than or equal to \anum2\a.]"
+ "[+\afile1\a -nt \afile2\a?True if \afile1\a is newer than \afile2\a "
+ "or \afile2\a does not exist.]"
+ "[+\afile1\a -ot \afile2\a?True if \afile1\a is older than \afile2\a "
+ "or \afile2\a does not exist.]"
+ "[+\afile1\a -ef \afile2\a?True if \afile1\a is another name for "
+ "\afile2\a. This will be true if \afile1\a is a hard link "
+ "or a symbolic link to \afile2\a.]"
+"}"
+"\n"
+"\n[expression]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Indicates that the specified expression is True.]"
+ "[+1?Indicates that the specified expression is False.]"
+ "[+>1?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\blet\b(1), \bexpr\b(1)]"
+;
+
+const char test_opchars[] = "HLNRSVOGCaeohrwxdcbfugkv"
+#if SHOPT_TEST_L
+ "l"
+#endif
+ "psnzt";
+const char e_argument[] = "argument expected";
+const char e_missing[] = "%s missing";
+const char e_badop[] = "%s: unknown operator";
+const char e_tstbegin[] = "[[ ! ";
+const char e_tstend[] = " ]]\n";
diff --git a/src/cmd/ksh93/data/variables.c b/src/cmd/ksh93/data/variables.c
new file mode 100644
index 0000000..3dce5b3
--- /dev/null
+++ b/src/cmd/ksh93/data/variables.c
@@ -0,0 +1,136 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+#include <shell.h>
+#include "shtable.h"
+#include "name.h"
+#include "defs.h"
+#include "variables.h"
+#include "builtins.h"
+
+/*
+ * This is the list of built-in shell variables and default values
+ * and default attributes.
+ */
+
+const struct shtable2 shtab_variables[] =
+{
+ "PATH", 0, (char*)0,
+ "PS1", 0, (char*)0,
+ "PS2", NV_NOFREE, "> ",
+ "IFS", NV_NOFREE, " \t\n",
+ "PWD", 0, (char*)0,
+ "HOME", 0, (char*)0,
+ "MAIL", 0, (char*)0,
+ "REPLY", 0, (char*)0,
+ "SHELL", NV_NOFREE, "/bin/" SH_STD,
+ "EDITOR", 0, (char*)0,
+ "MAILCHECK", NV_NOFREE|NV_INTEGER, (char*)0,
+ "RANDOM", NV_NOFREE|NV_INTEGER, (char*)0,
+ "ENV", NV_NOFREE, (char*)0,
+ "HISTFILE", 0, (char*)0,
+ "HISTSIZE", 0, (char*)0,
+ "HISTEDIT", NV_NOFREE, (char*)0,
+ "HISTCMD", NV_NOFREE|NV_INTEGER, (char*)0,
+ "FCEDIT", NV_NOFREE, &e_defedit[0],
+ "CDPATH", 0, (char*)0,
+ "MAILPATH", 0, (char*)0,
+ "PS3", NV_NOFREE, "#? ",
+ "OLDPWD", 0, (char*)0,
+ "VISUAL", 0, (char*)0,
+ "COLUMNS", 0, (char*)0,
+ "LINES", 0, (char*)0,
+ "PPID", NV_NOFREE|NV_INTEGER, (char*)0,
+ "_", NV_EXPORT, (char*)0,
+ "TMOUT", NV_NOFREE|NV_INTEGER, (char*)0,
+ "SECONDS", NV_NOFREE|NV_INTEGER|NV_DOUBLE, (char*)0,
+ "LINENO", NV_NOFREE|NV_INTEGER, (char*)0,
+ "OPTARG", 0, (char*)0,
+ "OPTIND", NV_NOFREE|NV_INTEGER, (char*)0,
+ "PS4", 0, (char*)0,
+ "FPATH", 0, (char*)0,
+ "LANG", 0, (char*)0,
+ "LC_ALL", 0, (char*)0,
+ "LC_COLLATE", 0, (char*)0,
+ "LC_CTYPE", 0, (char*)0,
+ "LC_MESSAGES", 0, (char*)0,
+ "LC_NUMERIC", 0, (char*)0,
+ "FIGNORE", 0, (char*)0,
+ "KSH_VERSION", 0, (char*)0,
+ "JOBMAX", NV_NOFREE|NV_INTEGER, (char*)0,
+ ".sh", NV_TABLE|NV_NOFREE|NV_NOPRINT, (char*)0,
+ ".sh.edchar", 0, (char*)0,
+ ".sh.edcol", 0, (char*)0,
+ ".sh.edtext", 0, (char*)0,
+ ".sh.edmode", 0, (char*)0,
+ ".sh.name", 0, (char*)0,
+ ".sh.subscript",0, (char*)0,
+ ".sh.value", 0, (char*)0,
+ ".sh.version", NV_NOFREE, (char*)(&e_version[10]),
+ ".sh.dollar", 0, (char*)0,
+ ".sh.match", 0, (char*)0,
+ ".sh.command", 0, (char*)0,
+ ".sh.file", 0, (char*)0,
+ ".sh.fun", 0, (char*)0,
+ ".sh.subshell", NV_INTEGER|NV_SHORT|NV_NOFREE, (char*)0,
+ ".sh.level", 0, (char*)0,
+ ".sh.lineno", NV_INTEGER, (char*)0,
+ ".sh.stats", 0, (char*)0,
+ ".sh.math", 0, (char*)0,
+ ".sh.pool", 0, (char*)0,
+ "SHLVL", NV_INTEGER|NV_NOFREE|NV_EXPORT, (char*)0,
+#if SHOPT_FS_3D
+ "VPATH", 0, (char*)0,
+#endif /* SHOPT_FS_3D */
+#if SHOPT_MULTIBYTE
+ "CSWIDTH", 0, (char*)0,
+#endif /* SHOPT_MULTIBYTE */
+#ifdef apollo
+ "SYSTYPE", 0, (char*)0,
+#endif /* apollo */
+ "", 0, (char*)0
+};
+
+const char *nv_discnames[] = { "get", "set", "append", "unset", "getn", 0 };
+
+#ifdef SHOPT_STATS
+const Shtable_t shtab_stats[] =
+{
+ "arg_cachehits", STAT_ARGHITS,
+ "arg_expands", STAT_ARGEXPAND,
+ "comsubs", STAT_COMSUB,
+ "forks", STAT_FORKS,
+ "funcalls", STAT_FUNCT,
+ "globs", STAT_GLOBS,
+ "linesread", STAT_READS,
+ "nv_cachehit", STAT_NVHITS,
+ "nv_opens", STAT_NVOPEN,
+ "pathsearch", STAT_PATHS,
+ "posixfuncall", STAT_SVFUNCT,
+ "simplecmds", STAT_SCMDS,
+ "spawns", STAT_SPAWN,
+ "subshell", STAT_SUBSHELL
+};
+#endif /* SHOPT_STATS */
+
diff --git a/src/cmd/ksh93/edit/completion.c b/src/cmd/ksh93/edit/completion.c
new file mode 100644
index 0000000..da81f94
--- /dev/null
+++ b/src/cmd/ksh93/edit/completion.c
@@ -0,0 +1,572 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * completion.c - command and file completion for shell editors
+ *
+ */
+
+#include "defs.h"
+#include <ast_wchar.h>
+#include "lexstates.h"
+#include "path.h"
+#include "io.h"
+#include "edit.h"
+#include "history.h"
+
+#if !SHOPT_MULTIBYTE
+#define mbchar(p) (*(unsigned char*)p++)
+#endif
+
+static char *fmtx(const char *string)
+{
+ register const char *cp = string;
+ register int n,c;
+ unsigned char *state = (unsigned char*)sh_lexstates[2];
+ int offset = staktell();
+ if(*cp=='#' || *cp=='~')
+ stakputc('\\');
+ while((c=mbchar(cp)),(c>UCHAR_MAX)||(n=state[c])==0 || n==S_EPAT);
+ if(n==S_EOF && *string!='#')
+ return((char*)string);
+ stakwrite(string,--cp-string);
+ for(string=cp;c=mbchar(cp);string=cp)
+ {
+ if((n=cp-string)==1)
+ {
+ if((n=state[c]) && n!=S_EPAT)
+ stakputc('\\');
+ stakputc(c);
+ }
+ else
+ stakwrite(string,n);
+ }
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+static int charcmp(int a, int b, int nocase)
+{
+ if(nocase)
+ {
+ if(isupper(a))
+ a = tolower(a);
+ if(isupper(b))
+ b = tolower(b);
+ }
+ return(a==b);
+}
+
+/*
+ * overwrites <str> to common prefix of <str> and <newstr>
+ * if <str> is equal to <newstr> returns <str>+strlen(<str>)+1
+ * otherwise returns <str>+strlen(<str>)
+ */
+static char *overlaid(register char *str,register const char *newstr,int nocase)
+{
+ register int c,d;
+ while((c= *(unsigned char *)str) && ((d= *(unsigned char*)newstr++),charcmp(c,d,nocase)))
+ str++;
+ if(*str)
+ *str = 0;
+ else if(*newstr==0)
+ str++;
+ return(str);
+}
+
+
+/*
+ * returns pointer to beginning of expansion and sets type of expansion
+ */
+static char *find_begin(char outbuff[], char *last, int endchar, int *type)
+{
+ register char *cp=outbuff, *bp, *xp;
+ register int c,inquote = 0, inassign=0;
+ int mode=*type;
+ bp = outbuff;
+ *type = 0;
+ while(cp < last)
+ {
+ xp = cp;
+ switch(c= mbchar(cp))
+ {
+ case '\'': case '"':
+ if(!inquote)
+ {
+ inquote = c;
+ bp = xp;
+ break;
+ }
+ if(inquote==c)
+ inquote = 0;
+ break;
+ case '\\':
+ if(inquote != '\'')
+ mbchar(cp);
+ break;
+ case '$':
+ if(inquote == '\'')
+ break;
+ c = *(unsigned char*)cp;
+ if(mode!='*' && (isaletter(c) || c=='{'))
+ {
+ int dot = '.';
+ if(c=='{')
+ {
+ xp = cp;
+ mbchar(cp);
+ c = *(unsigned char*)cp;
+ if(c!='.' && !isaletter(c))
+ break;
+ }
+ else
+ dot = 'a';
+ while(cp < last)
+ {
+ if((c= mbchar(cp)) , c!=dot && !isaname(c))
+ break;
+ }
+ if(cp>=last)
+ {
+ if(c==dot || isaname(c))
+ {
+ *type='$';
+ return(++xp);
+ }
+ if(c!='}')
+ bp = cp;
+ }
+ }
+ else if(c=='(')
+ {
+ *type = mode;
+ xp = find_begin(cp,last,')',type);
+ if(*(cp=xp)!=')')
+ bp = xp;
+ else
+ cp++;
+ }
+ break;
+ case '=':
+ if(!inquote)
+ {
+ bp = cp;
+ inassign = 1;
+ }
+ break;
+ case ':':
+ if(!inquote && inassign)
+ bp = cp;
+ break;
+ case '~':
+ if(*cp=='(')
+ break;
+ /* fall through */
+ default:
+ if(c && c==endchar)
+ return(xp);
+ if(!inquote && ismeta(c))
+ {
+ bp = cp;
+ inassign = 0;
+ }
+ break;
+ }
+ }
+ if(inquote && *bp==inquote)
+ *type = *bp++;
+ return(bp);
+}
+
+/*
+ * file name generation for edit modes
+ * non-zero exit for error, <0 ring bell
+ * don't search back past beginning of the buffer
+ * mode is '*' for inline expansion,
+ * mode is '\' for filename completion
+ * mode is '=' cause files to be listed in select format
+ */
+
+int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
+{
+ struct comnod *comptr;
+ struct argnod *ap;
+ register char *out;
+ char *av[2], *begin , *dir=0;
+ int addstar=0, rval=0, var=0, strip=1;
+ int nomarkdirs = !sh_isoption(SH_MARKDIRS);
+ sh_onstate(SH_FCOMPLETE);
+ if(ep->e_nlist)
+ {
+ if(mode=='=' && count>0)
+ {
+ if(count> ep->e_nlist)
+ return(-1);
+ mode = '?';
+ av[0] = ep->e_clist[count-1];
+ av[1] = 0;
+ }
+ else
+ {
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ ep->e_nlist = 0;
+ }
+ }
+ comptr = (struct comnod*)stakalloc(sizeof(struct comnod));
+ ap = (struct argnod*)stakseek(ARGVAL);
+#if SHOPT_MULTIBYTE
+ {
+ register int c = *cur;
+ register genchar *cp;
+ /* adjust cur */
+ cp = (genchar *)outbuff + *cur;
+ c = *cp;
+ *cp = 0;
+ *cur = ed_external((genchar*)outbuff,(char*)stakptr(0));
+ *cp = c;
+ *eol = ed_external((genchar*)outbuff,outbuff);
+ }
+#endif /* SHOPT_MULTIBYTE */
+ out = outbuff + *cur + (sh_isoption(SH_VI)!=0);
+ if(out[-1]=='"' || out[-1]=='\'')
+ {
+ rval = -(sh_isoption(SH_VI)!=0);
+ goto done;
+ }
+ comptr->comtyp = COMSCAN;
+ comptr->comarg = ap;
+ ap->argflag = (ARG_MAC|ARG_EXP);
+ ap->argnxt.ap = 0;
+ ap->argchn.cp = 0;
+ {
+ register int c;
+ char *last = out;
+ c = *(unsigned char*)out;
+ var = mode;
+ begin = out = find_begin(outbuff,last,0,&var);
+ /* addstar set to zero if * should not be added */
+ if(var=='$')
+ {
+ stakputs("${!");
+ stakwrite(out,last-out);
+ stakputs("@}");
+ out = last;
+ }
+ else
+ {
+ addstar = '*';
+ while(out < last)
+ {
+ c = *(unsigned char*)out;
+ if(isexp(c))
+ addstar = 0;
+ if (c == '/')
+ {
+ if(addstar == 0)
+ strip = 0;
+ dir = out+1;
+ }
+ stakputc(c);
+ out++;
+ }
+ }
+ if(mode=='?')
+ mode = '*';
+ if(var!='$' && mode=='\\' && out[-1]!='*')
+ addstar = '*';
+ if(*begin=='~' && !strchr(begin,'/'))
+ addstar = 0;
+ stakputc(addstar);
+ ap = (struct argnod*)stakfreeze(1);
+ }
+ if(mode!='*')
+ sh_onoption(SH_MARKDIRS);
+ {
+ register char **com;
+ char *cp=begin, *left=0, *saveout=".";
+ int nocase=0,narg,cmd_completion=0;
+ register int size='x';
+ while(cp>outbuff && ((size=cp[-1])==' ' || size=='\t'))
+ cp--;
+ if(!var && !strchr(ap->argval,'/') && (((cp==outbuff&&ep->sh->nextprompt==1) || (strchr(";&|(",size)) && (cp==outbuff+1||size=='('||cp[-2]!='>') && *begin!='~' )))
+ {
+ cmd_completion=1;
+ sh_onstate(SH_COMPLETE);
+ }
+ if(ep->e_nlist)
+ {
+ narg = 1;
+ com = av;
+ if(dir)
+ begin += (dir-begin);
+ }
+ else
+ {
+ com = sh_argbuild(ep->sh,&narg,comptr,0);
+ /* special handling for leading quotes */
+ if(begin>outbuff && (begin[-1]=='"' || begin[-1]=='\''))
+ begin--;
+ }
+ sh_offstate(SH_COMPLETE);
+ /* allow a search to be aborted */
+ if(ep->sh->trapnote&SH_SIGSET)
+ {
+ rval = -1;
+ goto done;
+ }
+ /* match? */
+ if (*com==0 || (narg <= 1 && (strcmp(ap->argval,*com)==0) || (addstar && com[0][strlen(*com)-1]=='*')))
+ {
+ rval = -1;
+ goto done;
+ }
+ if(mode=='=')
+ {
+ if (strip && !cmd_completion)
+ {
+ register char **ptrcom;
+ for(ptrcom=com;*ptrcom;ptrcom++)
+ /* trim directory prefix */
+ *ptrcom = path_basename(*ptrcom);
+ }
+ sfputc(sfstderr,'\n');
+ sh_menu(sfstderr,narg,com);
+ sfsync(sfstderr);
+ ep->e_nlist = narg;
+ ep->e_clist = com;
+ goto done;
+ }
+ /* see if there is enough room */
+ size = *eol - (out-begin);
+ if(mode=='\\')
+ {
+ int c;
+ if(dir)
+ {
+ c = *dir;
+ *dir = 0;
+ saveout = begin;
+ }
+ if(saveout=astconf("PATH_ATTRIBUTES",saveout,(char*)0))
+ nocase = (strchr(saveout,'c')!=0);
+ if(dir)
+ *dir = c;
+ /* just expand until name is unique */
+ size += strlen(*com);
+ }
+ else
+ {
+ size += narg;
+ {
+ char **savcom = com;
+ while (*com)
+ size += strlen(cp=fmtx(*com++));
+ com = savcom;
+ }
+ }
+ /* see if room for expansion */
+ if(outbuff+size >= &outbuff[MAXLINE])
+ {
+ com[0] = ap->argval;
+ com[1] = 0;
+ }
+ /* save remainder of the buffer */
+ if(*out)
+ left=stakcopy(out);
+ if(cmd_completion && mode=='\\')
+ out = strcopy(begin,path_basename(cp= *com++));
+ else if(mode=='*')
+ {
+ if(ep->e_nlist && dir && var)
+ {
+ if(*cp==var)
+ cp++;
+ else
+ *begin++ = var;
+ out = strcopy(begin,cp);
+ var = 0;
+ }
+ else
+ out = strcopy(begin,fmtx(*com));
+ com++;
+ }
+ else
+ out = strcopy(begin,*com++);
+ if(mode=='\\')
+ {
+ saveout= ++out;
+ while (*com && *begin)
+ {
+ if(cmd_completion)
+ out = overlaid(begin,path_basename(*com++),nocase);
+ else
+ out = overlaid(begin,*com++,nocase);
+ }
+ mode = (out==saveout);
+ if(out[-1]==0)
+ out--;
+ if(mode && out[-1]!='/')
+ {
+ if(cmd_completion)
+ {
+ Namval_t *np;
+ /* add as tracked alias */
+ Pathcomp_t *pp;
+ if(*cp=='/' && (pp=path_dirfind(ep->sh->pathlist,cp,'/')) && (np=nv_search(begin,ep->sh->track_tree,NV_ADD)))
+ path_alias(np,pp);
+ out = strcopy(begin,cp);
+ }
+ /* add quotes if necessary */
+ if((cp=fmtx(begin))!=begin)
+ out = strcopy(begin,cp);
+ if(var=='$' && begin[-1]=='{')
+ *out = '}';
+ else
+ *out = ' ';
+ *++out = 0;
+ }
+ else if((cp=fmtx(begin))!=begin)
+ {
+ out = strcopy(begin,cp);
+ if(out[-1] =='"' || out[-1]=='\'')
+ *--out = 0;
+ }
+ if(*begin==0)
+ ed_ringbell();
+ }
+ else
+ {
+ while (*com)
+ {
+ *out++ = ' ';
+ out = strcopy(out,fmtx(*com++));
+ }
+ }
+ if(ep->e_nlist)
+ {
+ cp = com[-1];
+ if(cp[strlen(cp)-1]!='/')
+ {
+ if(var=='$' && begin[-1]=='{')
+ *out = '}';
+ else
+ *out = ' ';
+ out++;
+ }
+ else if(out[-1] =='"' || out[-1]=='\'')
+ out--;
+ *out = 0;
+ }
+ *cur = (out-outbuff);
+ /* restore rest of buffer */
+ if(left)
+ out = strcopy(out,left);
+ *eol = (out-outbuff);
+ }
+ done:
+ sh_offstate(SH_FCOMPLETE);
+ if(!ep->e_nlist)
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ if(nomarkdirs)
+ sh_offoption(SH_MARKDIRS);
+#if SHOPT_MULTIBYTE
+ {
+ register int c,n=0;
+ /* first re-adjust cur */
+ c = outbuff[*cur];
+ outbuff[*cur] = 0;
+ for(out=outbuff; *out;n++)
+ mbchar(out);
+ outbuff[*cur] = c;
+ *cur = n;
+ outbuff[*eol+1] = 0;
+ *eol = ed_internal(outbuff,(genchar*)outbuff);
+ }
+#endif /* SHOPT_MULTIBYTE */
+ return(rval);
+}
+
+/*
+ * look for edit macro named _i
+ * if found, puts the macro definition into lookahead buffer and returns 1
+ */
+int ed_macro(Edit_t *ep, register int i)
+{
+ register char *out;
+ Namval_t *np;
+ genchar buff[LOOKAHEAD+1];
+ if(i != '@')
+ ep->e_macro[1] = i;
+ /* undocumented feature, macros of the form <ESC>[c evoke alias __c */
+ if(i=='_')
+ ep->e_macro[2] = ed_getchar(ep,1);
+ else
+ ep->e_macro[2] = 0;
+ if (isalnum(i)&&(np=nv_search(ep->e_macro,ep->sh->alias_tree,HASH_SCOPE))&&(out=nv_getval(np)))
+ {
+#if SHOPT_MULTIBYTE
+ /* copy to buff in internal representation */
+ int c = 0;
+ if( strlen(out) > LOOKAHEAD )
+ {
+ c = out[LOOKAHEAD];
+ out[LOOKAHEAD] = 0;
+ }
+ i = ed_internal(out,buff);
+ if(c)
+ out[LOOKAHEAD] = c;
+#else
+ strncpy((char*)buff,out,LOOKAHEAD);
+ buff[LOOKAHEAD] = 0;
+ i = strlen((char*)buff);
+#endif /* SHOPT_MULTIBYTE */
+ while(i-- > 0)
+ ed_ungetchar(ep,buff[i]);
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ * Enter the fc command on the current history line
+ */
+int ed_fulledit(Edit_t *ep)
+{
+ register char *cp;
+ if(!shgd->hist_ptr)
+ return(-1);
+ /* use EDITOR on current command */
+ if(ep->e_hline == ep->e_hismax)
+ {
+ if(ep->e_eol<0)
+ return(-1);
+#if SHOPT_MULTIBYTE
+ ep->e_inbuf[ep->e_eol+1] = 0;
+ ed_external(ep->e_inbuf, (char *)ep->e_inbuf);
+#endif /* SHOPT_MULTIBYTE */
+ sfwrite(shgd->hist_ptr->histfp,(char*)ep->e_inbuf,ep->e_eol+1);
+ sh_onstate(SH_HISTORY);
+ hist_flush(shgd->hist_ptr);
+ }
+ cp = strcopy((char*)ep->e_inbuf,e_runvi);
+ cp = strcopy(cp, fmtbase((long)ep->e_hline,10,0));
+ ep->e_eol = ((unsigned char*)cp - (unsigned char*)ep->e_inbuf)-(sh_isoption(SH_VI)!=0);
+ return(0);
+}
diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
new file mode 100644
index 0000000..b050f60
--- /dev/null
+++ b/src/cmd/ksh93/edit/edit.c
@@ -0,0 +1,1806 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * edit.c - common routines for vi and emacs one line editors in shell
+ *
+ * David Korn P.D. Sullivan
+ * AT&T Labs
+ *
+ * Coded April 1983.
+ */
+
+#include <ast.h>
+#include <errno.h>
+#include <ccode.h>
+#include "FEATURE/options"
+#include "FEATURE/time"
+#include "FEATURE/cmds"
+#ifdef _hdr_utime
+# include <utime.h>
+# include <ls.h>
+#endif
+
+#if KSHELL
+# include "defs.h"
+# include "variables.h"
+#else
+# include <ctype.h>
+ extern char ed_errbuf[];
+ char e_version[] = "\n@(#)$Id: Editlib version 1993-12-28 r $\0\n";
+#endif /* KSHELL */
+#include "io.h"
+#include "terminal.h"
+#include "history.h"
+#include "edit.h"
+
+static char CURSOR_UP[20] = { ESC, '[', 'A', 0 };
+static char KILL_LINE[20] = { ESC, '[', 'J', 0 };
+
+
+
+#if SHOPT_MULTIBYTE
+# define is_cntrl(c) ((c<=STRIP) && iscntrl(c))
+# define is_print(c) ((c&~STRIP) || isprint(c))
+#else
+# define is_cntrl(c) iscntrl(c)
+# define is_print(c) isprint(c)
+#endif
+
+#if (CC_NATIVE == CC_ASCII)
+# define printchar(c) ((c) ^ ('A'-cntl('A')))
+#else
+ static int printchar(int c)
+ {
+ switch(c)
+ {
+
+ case cntl('A'): return('A');
+ case cntl('B'): return('B');
+ case cntl('C'): return('C');
+ case cntl('D'): return('D');
+ case cntl('E'): return('E');
+ case cntl('F'): return('F');
+ case cntl('G'): return('G');
+ case cntl('H'): return('H');
+ case cntl('I'): return('I');
+ case cntl('J'): return('J');
+ case cntl('K'): return('K');
+ case cntl('L'): return('L');
+ case cntl('M'): return('M');
+ case cntl('N'): return('N');
+ case cntl('O'): return('O');
+ case cntl('P'): return('P');
+ case cntl('Q'): return('Q');
+ case cntl('R'): return('R');
+ case cntl('S'): return('S');
+ case cntl('T'): return('T');
+ case cntl('U'): return('U');
+ case cntl('V'): return('V');
+ case cntl('W'): return('W');
+ case cntl('X'): return('X');
+ case cntl('Y'): return('Y');
+ case cntl('Z'): return('Z');
+ case cntl(']'): return(']');
+ case cntl('['): return('[');
+ }
+ return('?');
+ }
+#endif
+#define MINWINDOW 15 /* minimum width window */
+#define DFLTWINDOW 80 /* default window width */
+#define RAWMODE 1
+#define ALTMODE 2
+#define ECHOMODE 3
+#define SYSERR -1
+
+#if SHOPT_OLDTERMIO
+# undef tcgetattr
+# undef tcsetattr
+#endif /* SHOPT_OLDTERMIO */
+
+#ifdef RT
+# define VENIX 1
+#endif /* RT */
+
+
+#ifdef _hdr_sgtty
+# ifdef TIOCGETP
+ static int l_mask;
+ static struct tchars l_ttychars;
+ static struct ltchars l_chars;
+ static char l_changed; /* set if mode bits changed */
+# define L_CHARS 4
+# define T_CHARS 2
+# define L_MASK 1
+# endif /* TIOCGETP */
+#endif /* _hdr_sgtty */
+
+#if KSHELL
+ static int keytrap(Edit_t *,char*, int, int, int);
+#else
+ Edit_t editb;
+#endif /* KSHELL */
+
+
+#ifndef _POSIX_DISABLE
+# define _POSIX_DISABLE 0
+#endif
+
+#ifdef future
+ static int compare(const char*, const char*, int);
+#endif /* future */
+#if SHOPT_VSH || SHOPT_ESH
+# define ttyparm (ep->e_ttyparm)
+# define nttyparm (ep->e_nttyparm)
+ static const char bellchr[] = "\a"; /* bell char */
+#endif /* SHOPT_VSH || SHOPT_ESH */
+
+
+/*
+ * This routine returns true if fd refers to a terminal
+ * This should be equivalent to isatty
+ */
+int tty_check(int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ struct termios tty;
+ ep->e_savefd = -1;
+ return(tty_get(fd,&tty)==0);
+}
+
+/*
+ * Get the current terminal attributes
+ * This routine remembers the attributes and just returns them if it
+ * is called again without an intervening tty_set()
+ */
+
+int tty_get(register int fd, register struct termios *tty)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ if(fd == ep->e_savefd)
+ *tty = ep->e_savetty;
+ else
+ {
+ while(tcgetattr(fd,tty) == SYSERR)
+ {
+ if(errno !=EINTR)
+ return(SYSERR);
+ errno = 0;
+ }
+ /* save terminal settings if in cannonical state */
+ if(ep->e_raw==0)
+ {
+ ep->e_savetty = *tty;
+ ep->e_savefd = fd;
+ }
+ }
+ return(0);
+}
+
+/*
+ * Set the terminal attributes
+ * If fd<0, then current attributes are invalidated
+ */
+
+int tty_set(int fd, int action, struct termios *tty)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ if(fd >=0)
+ {
+#ifdef future
+ if(ep->e_savefd>=0 && compare(&ep->e_savetty,tty,sizeof(struct termios)))
+ return(0);
+#endif
+ while(tcsetattr(fd, action, tty) == SYSERR)
+ {
+ if(errno !=EINTR)
+ return(SYSERR);
+ errno = 0;
+ }
+ ep->e_savetty = *tty;
+ }
+ ep->e_savefd = fd;
+ return(0);
+}
+
+#if SHOPT_ESH || SHOPT_VSH
+/*{ TTY_COOKED( fd )
+ *
+ * This routine will set the tty in cooked mode.
+ * It is also called by error.done().
+ *
+}*/
+
+void tty_cooked(register int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ ep->e_keytrap = 0;
+ if(ep->e_raw==0)
+ return;
+ if(fd < 0)
+ fd = ep->e_savefd;
+#ifdef L_MASK
+ /* restore flags */
+ if(l_changed&L_MASK)
+ ioctl(fd,TIOCLSET,&l_mask);
+ if(l_changed&T_CHARS)
+ /* restore alternate break character */
+ ioctl(fd,TIOCSETC,&l_ttychars);
+ if(l_changed&L_CHARS)
+ /* restore alternate break character */
+ ioctl(fd,TIOCSLTC,&l_chars);
+ l_changed = 0;
+#endif /* L_MASK */
+ /*** don't do tty_set unless ttyparm has valid data ***/
+ if(tty_set(fd, TCSANOW, &ttyparm) == SYSERR)
+ return;
+ ep->e_raw = 0;
+ return;
+}
+
+/*{ TTY_RAW( fd )
+ *
+ * This routine will set the tty in raw mode.
+ *
+}*/
+
+int tty_raw(register int fd, int echomode)
+{
+ int echo = echomode;
+#ifdef L_MASK
+ struct ltchars lchars;
+#endif /* L_MASK */
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ if(ep->e_raw==RAWMODE)
+ return(echo?-1:0);
+ else if(ep->e_raw==ECHOMODE)
+ return(echo?0:-1);
+#if !SHOPT_RAWONLY
+ if(ep->e_raw != ALTMODE)
+#endif /* SHOPT_RAWONLY */
+ {
+ if(tty_get(fd,&ttyparm) == SYSERR)
+ return(-1);
+ }
+#if L_MASK || VENIX
+ if(ttyparm.sg_flags&LCASE)
+ return(-1);
+ if(!(ttyparm.sg_flags&ECHO))
+ {
+ if(!echomode)
+ return(-1);
+ echo = 0;
+ }
+ nttyparm = ttyparm;
+ if(!echo)
+ nttyparm.sg_flags &= ~(ECHO | TBDELAY);
+# ifdef CBREAK
+ nttyparm.sg_flags |= CBREAK;
+# else
+ nttyparm.sg_flags |= RAW;
+# endif /* CBREAK */
+ ep->e_erase = ttyparm.sg_erase;
+ ep->e_kill = ttyparm.sg_kill;
+ ep->e_eof = cntl('D');
+ ep->e_werase = cntl('W');
+ ep->e_lnext = cntl('V');
+ if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
+ return(-1);
+ ep->e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
+# ifdef TIOCGLTC
+ /* try to remove effect of ^V and ^Y and ^O */
+ if(ioctl(fd,TIOCGLTC,&l_chars) != SYSERR)
+ {
+ lchars = l_chars;
+ lchars.t_lnextc = -1;
+ lchars.t_flushc = -1;
+ lchars.t_dsuspc = -1; /* no delayed stop process signal */
+ if(ioctl(fd,TIOCSLTC,&lchars) != SYSERR)
+ l_changed |= L_CHARS;
+ }
+# endif /* TIOCGLTC */
+#else
+ if (!(ttyparm.c_lflag & ECHO ))
+ {
+ if(!echomode)
+ return(-1);
+ echo = 0;
+ }
+# ifdef FLUSHO
+ ttyparm.c_lflag &= ~FLUSHO;
+# endif /* FLUSHO */
+ nttyparm = ttyparm;
+# ifndef u370
+ nttyparm.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL);
+ nttyparm.c_iflag |= BRKINT;
+# else
+ nttyparm.c_iflag &=
+ ~(IGNBRK|PARMRK|INLCR|IGNCR|ICRNL|INPCK);
+ nttyparm.c_iflag |= (BRKINT|IGNPAR);
+# endif /* u370 */
+ if(echo)
+ nttyparm.c_lflag &= ~(ICANON|ISIG);
+ else
+ nttyparm.c_lflag &= ~(ICANON|ISIG|ECHO|ECHOK);
+ nttyparm.c_cc[VTIME] = 0;
+ nttyparm.c_cc[VMIN] = 1;
+# ifdef VREPRINT
+ nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE;
+# endif /* VREPRINT */
+# ifdef VDISCARD
+ nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE;
+# endif /* VDISCARD */
+# ifdef VDSUSP
+ nttyparm.c_cc[VDSUSP] = _POSIX_DISABLE;
+# endif /* VDSUSP */
+# ifdef VWERASE
+ if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE)
+ ep->e_werase = cntl('W');
+ else
+ ep->e_werase = nttyparm.c_cc[VWERASE];
+ nttyparm.c_cc[VWERASE] = _POSIX_DISABLE;
+# else
+ ep->e_werase = cntl('W');
+# endif /* VWERASE */
+# ifdef VLNEXT
+ if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE )
+ ep->e_lnext = cntl('V');
+ else
+ ep->e_lnext = nttyparm.c_cc[VLNEXT];
+ nttyparm.c_cc[VLNEXT] = _POSIX_DISABLE;
+# else
+ ep->e_lnext = cntl('V');
+# endif /* VLNEXT */
+ ep->e_intr = ttyparm.c_cc[VINTR];
+ ep->e_eof = ttyparm.c_cc[VEOF];
+ ep->e_erase = ttyparm.c_cc[VERASE];
+ ep->e_kill = ttyparm.c_cc[VKILL];
+ if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
+ return(-1);
+ ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
+#endif
+ ep->e_raw = (echomode?ECHOMODE:RAWMODE);
+ return(0);
+}
+
+#if !SHOPT_RAWONLY
+
+/*
+ *
+ * Get tty parameters and make ESC and '\r' wakeup characters.
+ *
+ */
+
+# ifdef TIOCGETC
+int tty_alt(register int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ int mask;
+ struct tchars ttychars;
+ switch(ep->e_raw)
+ {
+ case ECHOMODE:
+ return(-1);
+ case ALTMODE:
+ return(0);
+ case RAWMODE:
+ tty_cooked(fd);
+ }
+ l_changed = 0;
+ if( ep->e_ttyspeed == 0)
+ {
+ if((tty_get(fd,&ttyparm) != SYSERR))
+ ep->e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
+ ep->e_raw = ALTMODE;
+ }
+ if(ioctl(fd,TIOCGETC,&l_ttychars) == SYSERR)
+ return(-1);
+ if(ioctl(fd,TIOCLGET,&l_mask)==SYSERR)
+ return(-1);
+ ttychars = l_ttychars;
+ mask = LCRTBS|LCRTERA|LCTLECH|LPENDIN|LCRTKIL;
+ if((l_mask|mask) != l_mask)
+ l_changed = L_MASK;
+ if(ioctl(fd,TIOCLBIS,&mask)==SYSERR)
+ return(-1);
+ if(ttychars.t_brkc!=ESC)
+ {
+ ttychars.t_brkc = ESC;
+ l_changed |= T_CHARS;
+ if(ioctl(fd,TIOCSETC,&ttychars) == SYSERR)
+ return(-1);
+ }
+ return(0);
+}
+# else
+# ifndef PENDIN
+# define PENDIN 0
+# endif /* PENDIN */
+# ifndef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN */
+
+int tty_alt(register int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ switch(ep->e_raw)
+ {
+ case ECHOMODE:
+ return(-1);
+ case ALTMODE:
+ return(0);
+ case RAWMODE:
+ tty_cooked(fd);
+ }
+ if((tty_get(fd, &ttyparm)==SYSERR) || (!(ttyparm.c_lflag&ECHO)))
+ return(-1);
+# ifdef FLUSHO
+ ttyparm.c_lflag &= ~FLUSHO;
+# endif /* FLUSHO */
+ nttyparm = ttyparm;
+ ep->e_eof = ttyparm.c_cc[VEOF];
+# ifdef ECHOCTL
+ /* escape character echos as ^[ */
+ nttyparm.c_lflag |= (ECHOE|ECHOK|ECHOCTL|PENDIN|IEXTEN);
+ nttyparm.c_cc[VEOL] = ESC;
+# else
+ /* switch VEOL2 and EOF, since EOF isn't echo'd by driver */
+ nttyparm.c_lflag |= (ECHOE|ECHOK);
+ nttyparm.c_cc[VEOF] = ESC; /* make ESC the eof char */
+# ifdef VEOL2
+ nttyparm.c_iflag &= ~(IGNCR|ICRNL);
+ nttyparm.c_iflag |= INLCR;
+ nttyparm.c_cc[VEOL] = '\r'; /* make CR an eol char */
+ nttyparm.c_cc[VEOL2] = ep->e_eof; /* make EOF an eol char */
+# else
+ nttyparm.c_cc[VEOL] = ep->e_eof; /* make EOF an eol char */
+# endif /* VEOL2 */
+# endif /* ECHOCTL */
+# ifdef VREPRINT
+ nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE;
+# endif /* VREPRINT */
+# ifdef VDISCARD
+ nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE;
+# endif /* VDISCARD */
+# ifdef VWERASE
+ if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE)
+ nttyparm.c_cc[VWERASE] = cntl('W');
+ ep->e_werase = nttyparm.c_cc[VWERASE];
+# else
+ ep->e_werase = cntl('W');
+# endif /* VWERASE */
+# ifdef VLNEXT
+ if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE )
+ nttyparm.c_cc[VLNEXT] = cntl('V');
+ ep->e_lnext = nttyparm.c_cc[VLNEXT];
+# else
+ ep->e_lnext = cntl('V');
+# endif /* VLNEXT */
+ ep->e_erase = ttyparm.c_cc[VERASE];
+ ep->e_kill = ttyparm.c_cc[VKILL];
+ if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
+ return(-1);
+ ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
+ ep->e_raw = ALTMODE;
+ return(0);
+}
+
+# endif /* TIOCGETC */
+#endif /* SHOPT_RAWONLY */
+
+/*
+ * ED_WINDOW()
+ *
+ * return the window size
+ */
+int ed_window(void)
+{
+ int rows,cols;
+ register char *cp = nv_getval(COLUMNS);
+ if(cp)
+ cols = (int)strtol(cp, (char**)0, 10)-1;
+ else
+ {
+ astwinsize(2,&rows,&cols);
+ if(--cols <0)
+ cols = DFLTWINDOW-1;
+ }
+ if(cols < MINWINDOW)
+ cols = MINWINDOW;
+ else if(cols > MAXWINDOW)
+ cols = MAXWINDOW;
+ return(cols);
+}
+
+/* E_FLUSH()
+ *
+ * Flush the output buffer.
+ *
+ */
+
+void ed_flush(Edit_t *ep)
+{
+ register int n = ep->e_outptr-ep->e_outbase;
+ register int fd = ERRIO;
+ if(n<=0)
+ return;
+ write(fd,ep->e_outbase,(unsigned)n);
+ ep->e_outptr = ep->e_outbase;
+}
+
+/*
+ * send the bell character ^G to the terminal
+ */
+
+void ed_ringbell(void)
+{
+ write(ERRIO,bellchr,1);
+}
+
+/*
+ * send a carriage return line feed to the terminal
+ */
+
+void ed_crlf(register Edit_t *ep)
+{
+#ifdef cray
+ ed_putchar(ep,'\r');
+#endif /* cray */
+#ifdef u370
+ ed_putchar(ep,'\r');
+#endif /* u370 */
+#ifdef VENIX
+ ed_putchar(ep,'\r');
+#endif /* VENIX */
+ ed_putchar(ep,'\n');
+ ed_flush(ep);
+}
+
+/* ED_SETUP( max_prompt_size )
+ *
+ * This routine sets up the prompt string
+ * The following is an unadvertised feature.
+ * Escape sequences in the prompt can be excluded from the calculated
+ * prompt length. This is accomplished as follows:
+ * - if the prompt string starts with "%\r, or contains \r%\r", where %
+ * represents any char, then % is taken to be the quote character.
+ * - strings enclosed by this quote character, and the quote character,
+ * are not counted as part of the prompt length.
+ */
+
+void ed_setup(register Edit_t *ep, int fd, int reedit)
+{
+ Shell_t *shp = ep->sh;
+ register char *pp;
+ register char *last, *prev;
+ char *ppmax;
+ int myquote = 0, n;
+ register int qlen = 1, qwid;
+ char inquote = 0;
+ ep->e_fd = fd;
+ ep->e_multiline = sh_isoption(SH_MULTILINE)!=0;
+#ifdef SIGWINCH
+ if(!(shp->sigflag[SIGWINCH]&SH_SIGFAULT))
+ {
+ signal(SIGWINCH,sh_fault);
+ shp->sigflag[SIGWINCH] |= SH_SIGFAULT;
+ }
+ pp = shp->st.trapcom[SIGWINCH];
+ shp->st.trapcom[SIGWINCH] = 0;
+ sh_fault(SIGWINCH);
+ shp->st.trapcom[SIGWINCH] = pp;
+ ep->sh->winch = 0;
+#endif
+#if SHOPT_EDPREDICT
+ ep->hlist = 0;
+ ep->nhlist = 0;
+ ep->hoff = 0;
+#endif /* SHOPT_EDPREDICT */
+#if KSHELL
+ ep->e_stkptr = stakptr(0);
+ ep->e_stkoff = staktell();
+ if(!(last = shp->prompt))
+ last = "";
+ shp->prompt = 0;
+#else
+ last = ep->e_prbuff;
+#endif /* KSHELL */
+ if(shp->gd->hist_ptr)
+ {
+ register History_t *hp = shp->gd->hist_ptr;
+ ep->e_hismax = hist_max(hp);
+ ep->e_hismin = hist_min(hp);
+ }
+ else
+ {
+ ep->e_hismax = ep->e_hismin = ep->e_hloff = 0;
+ }
+ ep->e_hline = ep->e_hismax;
+ if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
+ ep->e_wsize = MAXLINE;
+ else
+ ep->e_wsize = ed_window()-2;
+ ep->e_winsz = ep->e_wsize+2;
+ ep->e_crlf = 1;
+ ep->e_plen = 0;
+ pp = ep->e_prompt;
+ ppmax = pp+PRSIZE-1;
+ *pp++ = '\r';
+ {
+ register int c;
+ while(prev = last, c = mbchar(last)) switch(c)
+ {
+ case ESC:
+ {
+ int skip=0;
+ ep->e_crlf = 0;
+ *pp++ = c;
+ for(n=1; c = *last++; n++)
+ {
+ if(pp < ppmax)
+ *pp++ = c;
+ if(c=='\a' || c==ESC || c=='\r')
+ break;
+ if(skip || (c>='0' && c<='9'))
+ {
+ skip = 0;
+ continue;
+ }
+ if(n>1 && c==';')
+ skip = 1;
+ else if(n>2 || (c!= '[' && c!= ']'))
+ break;
+ }
+ if(c==0 || c==ESC || c=='\r')
+ last--;
+ qlen += (n+1);
+ break;
+ }
+ case '\b':
+ if(pp>ep->e_prompt+1)
+ pp--;
+ break;
+ case '\r':
+ if(pp == (ep->e_prompt+2)) /* quote char */
+ myquote = *(pp-1);
+ /*FALLTHROUGH*/
+
+ case '\n':
+ /* start again */
+ ep->e_crlf = 1;
+ qlen = 1;
+ inquote = 0;
+ pp = ep->e_prompt+1;
+ break;
+
+ case '\t':
+ /* expand tabs */
+ while((pp-ep->e_prompt)%TABSIZE)
+ {
+ if(pp >= ppmax)
+ break;
+ *pp++ = ' ';
+ }
+ break;
+
+ case '\a':
+ /* cut out bells */
+ break;
+
+ default:
+ if(c==myquote)
+ {
+ qlen += inquote;
+ inquote ^= 1;
+ }
+ if(pp < ppmax)
+ {
+ if(inquote)
+ qlen++;
+ else if(!is_print(c))
+ ep->e_crlf = 0;
+ if((qwid = last - prev) > 1)
+ qlen += qwid - mbwidth(c);
+ while(prev < last && pp < ppmax)
+ *pp++ = *prev++;
+ }
+ break;
+ }
+ }
+ if(pp-ep->e_prompt > qlen)
+ ep->e_plen = pp - ep->e_prompt - qlen;
+ *pp = 0;
+ if(!ep->e_multiline && (ep->e_wsize -= ep->e_plen) < 7)
+ {
+ register int shift = 7-ep->e_wsize;
+ ep->e_wsize = 7;
+ pp = ep->e_prompt+1;
+ strcpy(pp,pp+shift);
+ ep->e_plen -= shift;
+ last[-ep->e_plen-2] = '\r';
+ }
+ sfsync(sfstderr);
+ if(fd == sffileno(sfstderr))
+ {
+ /* can't use output buffer when reading from stderr */
+ static char *buff;
+ if(!buff)
+ buff = (char*)malloc(MAXLINE);
+ ep->e_outbase = ep->e_outptr = buff;
+ ep->e_outlast = ep->e_outptr + MAXLINE;
+ return;
+ }
+ qlen = sfset(sfstderr,SF_READ,0);
+ /* make sure SF_READ not on */
+ ep->e_outbase = ep->e_outptr = (char*)sfreserve(sfstderr,SF_UNBOUND,SF_LOCKR);
+ ep->e_outlast = ep->e_outptr + sfvalue(sfstderr);
+ if(qlen)
+ sfset(sfstderr,SF_READ,1);
+ sfwrite(sfstderr,ep->e_outptr,0);
+ ep->e_eol = reedit;
+ if(ep->e_multiline)
+ {
+#ifdef _cmd_tput
+ char *term;
+ if(!ep->e_term)
+ ep->e_term = nv_search("TERM",shp->var_tree,0);
+ if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname))
+ {
+ sh_trap(".sh.subscript=$(tput cuu1 2>/dev/null)",0);
+ if(pp=nv_getval(SH_SUBSCRNOD))
+ strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1);
+ nv_unset(SH_SUBSCRNOD);
+ strcpy(ep->e_termname,term);
+ }
+#endif
+ ep->e_wsize = MAXLINE - (ep->e_plen+1);
+ }
+ if(ep->e_default && (pp = nv_getval(ep->e_default)))
+ {
+ n = strlen(pp);
+ if(n > LOOKAHEAD)
+ n = LOOKAHEAD;
+ ep->e_lookahead = n;
+ while(n-- > 0)
+ ep->e_lbuf[n] = *pp++;
+ ep->e_default = 0;
+ }
+}
+
+static void ed_putstring(register Edit_t *ep, const char *str)
+{
+ register int c;
+ while(c = *str++)
+ ed_putchar(ep,c);
+}
+
+static void ed_nputchar(register Edit_t *ep, int n, int c)
+{
+ while(n-->0)
+ ed_putchar(ep,c);
+}
+
+/*
+ * Do read, restart on interrupt unless SH_SIGSET or SH_SIGTRAP is set
+ * Use sfpkrd() to poll() or select() to wait for input if possible
+ * Unfortunately, systems that get interrupted from slow reads update
+ * this access time for for the terminal (in violation of POSIX).
+ * The fixtime() macro, resets the time to the time at entry in
+ * this case. This is not necessary for systems that can handle
+ * sfpkrd() correctly (i,e., those that support poll() or select()
+ */
+int ed_read(void *context, int fd, char *buff, int size, int reedit)
+{
+ register Edit_t *ep = (Edit_t*)context;
+ register int rv= -1;
+ register int delim = (ep->e_raw==RAWMODE?'\r':'\n');
+ Shell_t *shp = ep->sh;
+ int mode = -1;
+ int (*waitevent)(int,long,int) = shp->gd->waitevent;
+ if(ep->e_raw==ALTMODE)
+ mode = 1;
+ if(size < 0)
+ {
+ mode = 1;
+ size = -size;
+ }
+ sh_onstate(SH_TTYWAIT);
+ errno = EINTR;
+ shp->gd->waitevent = 0;
+ while(rv<0 && errno==EINTR)
+ {
+ if(shp->trapnote&(SH_SIGSET|SH_SIGTRAP))
+ goto done;
+ if(ep->sh->winch && sh_isstate(SH_INTERACTIVE) && (sh_isoption(SH_VI) || sh_isoption(SH_EMACS)))
+ {
+ Edpos_t lastpos;
+ int n, rows, newsize;
+ /* move cursor to start of first line */
+ ed_putchar(ep,'\r');
+ ed_flush(ep);
+ astwinsize(2,&rows,&newsize);
+ n = (ep->e_plen+ep->e_cur)/++ep->e_winsz;
+ while(n--)
+ ed_putstring(ep,CURSOR_UP);
+ if(ep->e_multiline && newsize>ep->e_winsz && (lastpos.line=(ep->e_plen+ep->e_peol)/ep->e_winsz))
+ {
+ /* clear the current command line */
+ n = lastpos.line;
+ while(lastpos.line--)
+ {
+ ed_nputchar(ep,ep->e_winsz,' ');
+ ed_putchar(ep,'\n');
+ }
+ ed_nputchar(ep,ep->e_winsz,' ');
+ while(n--)
+ ed_putstring(ep,CURSOR_UP);
+ }
+ ep->sh->winch = 0;
+ ed_flush(ep);
+ sh_delay(.05);
+ astwinsize(2,&rows,&newsize);
+ ep->e_winsz = newsize-1;
+ if(ep->e_winsz < MINWINDOW)
+ ep->e_winsz = MINWINDOW;
+ if(!ep->e_multiline && ep->e_wsize < MAXLINE)
+ ep->e_wsize = ep->e_winsz-2;
+ ep->e_nocrnl=1;
+ if(*ep->e_vi_insert)
+ {
+ buff[0] = ESC;
+ buff[1] = cntl('L');
+ buff[2] = 'a';
+ return(3);
+ }
+ if(sh_isoption(SH_EMACS) || sh_isoption(SH_VI))
+ buff[0] = cntl('L');
+ return(1);
+ }
+ else
+ ep->sh->winch = 0;
+ /* an interrupt that should be ignored */
+ errno = 0;
+ if(!waitevent || (rv=(*waitevent)(fd,-1L,0))>=0)
+ rv = sfpkrd(fd,buff,size,delim,-1L,mode);
+ }
+ if(rv < 0)
+ {
+#ifdef _hdr_utime
+# define fixtime() if(isdevtty)utime(ep->e_tty,&utimes)
+ int isdevtty=0;
+ struct stat statb;
+ struct utimbuf utimes;
+ if(errno==0 && !ep->e_tty)
+ {
+ if((ep->e_tty=ttyname(fd)) && stat(ep->e_tty,&statb)>=0)
+ {
+ ep->e_tty_ino = statb.st_ino;
+ ep->e_tty_dev = statb.st_dev;
+ }
+ }
+ if(ep->e_tty_ino && fstat(fd,&statb)>=0 && statb.st_ino==ep->e_tty_ino && statb.st_dev==ep->e_tty_dev)
+ {
+ utimes.actime = statb.st_atime;
+ utimes.modtime = statb.st_mtime;
+ isdevtty=1;
+ }
+#else
+# define fixtime()
+#endif /* _hdr_utime */
+ while(1)
+ {
+ rv = read(fd,buff,size);
+ if(rv>=0 || errno!=EINTR)
+ break;
+ if(shp->trapnote&(SH_SIGSET|SH_SIGTRAP))
+ goto done;
+ /* an interrupt that should be ignored */
+ fixtime();
+ }
+ }
+ else if(rv>=0 && mode>0)
+ rv = read(fd,buff,rv>0?rv:1);
+done:
+ shp->gd->waitevent = waitevent;
+ sh_offstate(SH_TTYWAIT);
+ return(rv);
+}
+
+
+/*
+ * put <string> of length <nbyte> onto lookahead stack
+ * if <type> is non-zero, the negation of the character is put
+ * onto the stack so that it can be checked for KEYTRAP
+ * putstack() returns 1 except when in the middle of a multi-byte char
+ */
+static int putstack(Edit_t *ep,char string[], register int nbyte, int type)
+{
+ register int c;
+#if SHOPT_MULTIBYTE
+ char *endp, *p=string;
+ int size, offset = ep->e_lookahead + nbyte;
+ *(endp = &p[nbyte]) = 0;
+ endp = &p[nbyte];
+ do
+ {
+ c = (int)((*p) & STRIP);
+ if(c< 0x80 && c!='<')
+ {
+ if (type)
+ c = -c;
+# ifndef CBREAK
+ if(c == '\0')
+ {
+ /*** user break key ***/
+ ep->e_lookahead = 0;
+# if KSHELL
+ sh_fault(SIGINT);
+ siglongjmp(ep->e_env, UINTR);
+# endif /* KSHELL */
+ }
+# endif /* CBREAK */
+
+ }
+ else
+ {
+ again:
+ if((c=mbchar(p)) >=0)
+ {
+ p--; /* incremented below */
+ if(type)
+ c = -c;
+ }
+#ifdef EILSEQ
+ else if(errno == EILSEQ)
+ errno = 0;
+#endif
+ else if((endp-p) < mbmax())
+ {
+ if ((c=ed_read(ep,ep->e_fd,endp, 1,0)) == 1)
+ {
+ *++endp = 0;
+ goto again;
+ }
+ return(c);
+ }
+ else
+ {
+ ed_ringbell();
+ c = -(int)((*p) & STRIP);
+ offset += mbmax()-1;
+ }
+ }
+ ep->e_lbuf[--offset] = c;
+ p++;
+ }
+ while (p < endp);
+ /* shift lookahead buffer if necessary */
+ if(offset -= ep->e_lookahead)
+ {
+ for(size=offset;size < nbyte;size++)
+ ep->e_lbuf[ep->e_lookahead+size-offset] = ep->e_lbuf[ep->e_lookahead+size];
+ }
+ ep->e_lookahead += nbyte-offset;
+#else
+ while (nbyte > 0)
+ {
+ c = string[--nbyte] & STRIP;
+ ep->e_lbuf[ep->e_lookahead++] = (type?-c:c);
+# ifndef CBREAK
+ if( c == '\0' )
+ {
+ /*** user break key ***/
+ ep->e_lookahead = 0;
+# if KSHELL
+ sh_fault(SIGINT);
+ siglongjmp(ep->e_env, UINTR);
+# endif /* KSHELL */
+ }
+# endif /* CBREAK */
+ }
+#endif /* SHOPT_MULTIBYTE */
+ return(1);
+}
+
+/*
+ * routine to perform read from terminal for vi and emacs mode
+ * <mode> can be one of the following:
+ * -2 vi insert mode - key binding is in effect
+ * -1 vi control mode - key binding is in effect
+ * 0 normal command mode - key binding is in effect
+ * 1 edit keys not mapped
+ * 2 Next key is literal
+ */
+int ed_getchar(register Edit_t *ep,int mode)
+{
+ register int n, c;
+ char readin[LOOKAHEAD+1];
+ if(!ep->e_lookahead)
+ {
+ ed_flush(ep);
+ ep->e_inmacro = 0;
+ /* The while is necessary for reads of partial multbyte chars */
+ *ep->e_vi_insert = (mode==-2);
+ if((n=ed_read(ep,ep->e_fd,readin,-LOOKAHEAD,0)) > 0)
+ n = putstack(ep,readin,n,1);
+ *ep->e_vi_insert = 0;
+ }
+ if(ep->e_lookahead)
+ {
+ /* check for possible key mapping */
+ if((c = ep->e_lbuf[--ep->e_lookahead]) < 0)
+ {
+ if(mode<=0 && -c == ep->e_intr)
+ {
+ sh_fault(SIGINT);
+ siglongjmp(ep->e_env, UINTR);
+ }
+ if(mode<=0 && ep->sh->st.trap[SH_KEYTRAP])
+ {
+ ep->e_keytrap = 1;
+ n=1;
+ if((readin[0]= -c) == ESC)
+ {
+ while(1)
+ {
+ if(!ep->e_lookahead)
+ {
+ if((c=sfpkrd(ep->e_fd,readin+n,1,'\r',(mode?400L:-1L),0))>0)
+ putstack(ep,readin+n,c,1);
+ }
+ if(!ep->e_lookahead)
+ break;
+ if((c=ep->e_lbuf[--ep->e_lookahead])>=0)
+ {
+ ep->e_lookahead++;
+ break;
+ }
+ c = -c;
+ readin[n++] = c;
+ if(c>='0' && c<='9' && n>2)
+ continue;
+ if(n>2 || (c!= '[' && c!= 'O'))
+ break;
+ }
+ }
+ if(n=keytrap(ep,readin,n,LOOKAHEAD-n,mode))
+ {
+ putstack(ep,readin,n,0);
+ c = ep->e_lbuf[--ep->e_lookahead];
+ }
+ else
+ c = ed_getchar(ep,mode);
+ ep->e_keytrap = 0;
+ }
+ else
+ c = -c;
+ }
+ /*** map '\r' to '\n' ***/
+ if(c == '\r' && mode!=2)
+ c = '\n';
+ if(ep->e_tabcount && !(c=='\t'||c==ESC || c=='\\' || c=='=' || c==cntl('L') || isdigit(c)))
+ ep->e_tabcount = 0;
+ }
+ else
+ siglongjmp(ep->e_env,(n==0?UEOF:UINTR));
+ return(c);
+}
+
+void ed_ungetchar(Edit_t *ep,register int c)
+{
+ if (ep->e_lookahead < LOOKAHEAD)
+ ep->e_lbuf[ep->e_lookahead++] = c;
+ return;
+}
+
+/*
+ * put a character into the output buffer
+ */
+
+void ed_putchar(register Edit_t *ep,register int c)
+{
+ char buf[8];
+ register char *dp = ep->e_outptr;
+ register int i,size=1;
+ if(!dp)
+ return;
+ buf[0] = c;
+#if SHOPT_MULTIBYTE
+ /* check for place holder */
+ if(c == MARKER)
+ return;
+ if((size = mbconv(buf, (wchar_t)c)) > 1)
+ {
+ for (i = 0; i < (size-1); i++)
+ *dp++ = buf[i];
+ c = buf[i];
+ }
+ else
+ {
+ buf[0] = c;
+ size = 1;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if (buf[0] == '_' && size==1)
+ {
+ *dp++ = ' ';
+ *dp++ = '\b';
+ }
+ *dp++ = c;
+ *dp = '\0';
+ if(dp >= ep->e_outlast)
+ ed_flush(ep);
+ else
+ ep->e_outptr = dp;
+}
+
+/*
+ * returns the line and column corresponding to offset <off> in the physical buffer
+ * if <cur> is non-zero and <= <off>, then correspodning <curpos> will start the search
+ */
+Edpos_t ed_curpos(Edit_t *ep,genchar *phys, int off, int cur, Edpos_t curpos)
+{
+ register genchar *sp=phys;
+ register int c=1, col=ep->e_plen;
+ Edpos_t pos;
+#if SHOPT_MULTIBYTE
+ char p[16];
+#endif /* SHOPT_MULTIBYTE */
+ if(cur && off>=cur)
+ {
+ sp += cur;
+ off -= cur;
+ pos = curpos;
+ col = pos.col;
+ }
+ else
+ {
+ pos.line = 0;
+ while(col > ep->e_winsz)
+ {
+ pos.line++;
+ col -= (ep->e_winsz+1);
+ }
+ }
+ while(off-->0)
+ {
+ if(c)
+ c = *sp++;
+#if SHOPT_MULTIBYTE
+ if(c && (mbconv(p, (wchar_t)c))==1 && p[0]=='\n')
+#else
+ if(c=='\n')
+#endif /* SHOPT_MULTIBYTE */
+ col = 0;
+ else
+ col++;
+ if(col > ep->e_winsz)
+ col = 0;
+ if(col==0)
+ pos.line++;
+ }
+ pos.col = col;
+ return(pos);
+}
+
+int ed_setcursor(register Edit_t *ep,genchar *physical,register int old,register int new,int first)
+{
+ static int oldline;
+ register int delta;
+ int clear = 0;
+ Edpos_t newpos;
+
+ delta = new - old;
+ if(first < 0)
+ {
+ first = 0;
+ clear = 1;
+ }
+ if( delta == 0 && !clear)
+ return(new);
+ if(ep->e_multiline)
+ {
+ ep->e_curpos = ed_curpos(ep, physical, old,0,ep->e_curpos);
+ if(clear && old>=ep->e_peol && (clear=ep->e_winsz-ep->e_curpos.col)>0)
+ {
+ ed_nputchar(ep,clear,' ');
+ ed_nputchar(ep,clear,'\b');
+ return(new);
+ }
+ newpos = ed_curpos(ep, physical, new,old,ep->e_curpos);
+ if(ep->e_curpos.col==0 && ep->e_curpos.line>0 && oldline<ep->e_curpos.line && delta<0)
+ ed_putstring(ep,"\r\n");
+ oldline = newpos.line;
+ if(ep->e_curpos.line > newpos.line)
+ {
+ int n,pline,plen=ep->e_plen;
+ for(;ep->e_curpos.line > newpos.line; ep->e_curpos.line--)
+ ed_putstring(ep,CURSOR_UP);
+ pline = plen/(ep->e_winsz+1);
+ if(newpos.line <= pline)
+ plen -= pline*(ep->e_winsz+1);
+ else
+ plen = 0;
+ if((n=plen- ep->e_curpos.col)>0)
+ {
+ ep->e_curpos.col += n;
+ ed_putchar(ep,'\r');
+ if(!ep->e_crlf && pline==0)
+ ed_putstring(ep,ep->e_prompt);
+ else
+ {
+ int m = ep->e_winsz+1-plen;
+ ed_putchar(ep,'\n');
+ n = plen;
+ if(m < ed_genlen(physical))
+ {
+ while(physical[m] && n-->0)
+ ed_putchar(ep,physical[m++]);
+ }
+ ed_nputchar(ep,n,' ');
+ ed_putstring(ep,CURSOR_UP);
+ }
+ }
+ }
+ else if(ep->e_curpos.line < newpos.line)
+ {
+ ed_nputchar(ep, newpos.line-ep->e_curpos.line,'\n');
+ ep->e_curpos.line = newpos.line;
+ ed_putchar(ep,'\r');
+ ep->e_curpos.col = 0;
+ }
+ delta = newpos.col - ep->e_curpos.col;
+ old = new - delta;
+ }
+ else
+ newpos.line=0;
+ if(delta<0)
+ {
+ int bs= newpos.line && ep->e_plen>ep->e_winsz;
+ /*** move to left ***/
+ delta = -delta;
+ /*** attempt to optimize cursor movement ***/
+ if(!ep->e_crlf || bs || (2*delta <= ((old-first)+(newpos.line?0:ep->e_plen))) )
+ {
+ ed_nputchar(ep,delta,'\b');
+ delta = 0;
+ }
+ else
+ {
+ if(newpos.line==0)
+ ed_putstring(ep,ep->e_prompt);
+ else
+ {
+ first = 1+(newpos.line*ep->e_winsz - ep->e_plen);
+ ed_putchar(ep,'\r');
+ }
+ old = first;
+ delta = new-first;
+ }
+ }
+ while(delta-->0)
+ ed_putchar(ep,physical[old++]);
+ return(new);
+}
+
+/*
+ * copy virtual to physical and return the index for cursor in physical buffer
+ */
+int ed_virt_to_phys(Edit_t *ep,genchar *virt,genchar *phys,int cur,int voff,int poff)
+{
+ register genchar *sp = virt;
+ register genchar *dp = phys;
+ register int c;
+ genchar *curp = sp + cur;
+ genchar *dpmax = phys+MAXLINE;
+ int d, r;
+ sp += voff;
+ dp += poff;
+ for(r=poff;c= *sp;sp++)
+ {
+ if(curp == sp)
+ r = dp - phys;
+#if SHOPT_MULTIBYTE
+ d = mbwidth((wchar_t)c);
+ if(d==1 && is_cntrl(c))
+ d = -1;
+ if(d>1)
+ {
+ /* multiple width character put in place holders */
+ *dp++ = c;
+ while(--d >0)
+ *dp++ = MARKER;
+ /* in vi mode the cursor is at the last character */
+ if(dp>=dpmax)
+ break;
+ continue;
+ }
+ else
+#else
+ d = (is_cntrl(c)?-1:1);
+#endif /* SHOPT_MULTIBYTE */
+ if(d<0)
+ {
+ if(c=='\t')
+ {
+ c = dp-phys;
+ if(sh_isoption(SH_VI))
+ c += ep->e_plen;
+ c = TABSIZE - c%TABSIZE;
+ while(--c>0)
+ *dp++ = ' ';
+ c = ' ';
+ }
+ else
+ {
+ *dp++ = '^';
+ c = printchar(c);
+ }
+ /* in vi mode the cursor is at the last character */
+ if(curp == sp && sh_isoption(SH_VI))
+ r = dp - phys;
+ }
+ *dp++ = c;
+ if(dp>=dpmax)
+ break;
+ }
+ *dp = 0;
+ ep->e_peol = dp-phys;
+ return(r);
+}
+
+#if SHOPT_MULTIBYTE
+/*
+ * convert external representation <src> to an array of genchars <dest>
+ * <src> and <dest> can be the same
+ * returns number of chars in dest
+ */
+
+int ed_internal(const char *src, genchar *dest)
+{
+ register const unsigned char *cp = (unsigned char *)src;
+ register int c;
+ register wchar_t *dp = (wchar_t*)dest;
+ if(dest == (genchar*)roundof(cp-(unsigned char*)0,sizeof(genchar)))
+ {
+ genchar buffer[MAXLINE];
+ c = ed_internal(src,buffer);
+ ed_gencpy((genchar*)dp,buffer);
+ return(c);
+ }
+ while(*cp)
+ *dp++ = mbchar(cp);
+ *dp = 0;
+ return(dp-(wchar_t*)dest);
+}
+
+/*
+ * convert internal representation <src> into character array <dest>.
+ * The <src> and <dest> may be the same.
+ * returns number of chars in dest.
+ */
+
+int ed_external(const genchar *src, char *dest)
+{
+ register genchar wc;
+ register int c,size;
+ register char *dp = dest;
+ char *dpmax = dp+sizeof(genchar)*MAXLINE-2;
+ if((char*)src == dp)
+ {
+ char buffer[MAXLINE*sizeof(genchar)];
+ c = ed_external(src,buffer);
+
+#ifdef _lib_wcscpy
+ wcscpy((wchar_t *)dest,(const wchar_t *)buffer);
+#else
+ strcpy(dest,buffer);
+#endif
+ return(c);
+ }
+ while((wc = *src++) && dp<dpmax)
+ {
+ if((size = mbconv(dp, wc)) < 0)
+ {
+ /* copy the character as is */
+ size = 1;
+ *dp = wc;
+ }
+ dp += size;
+ }
+ *dp = 0;
+ return(dp-dest);
+}
+
+/*
+ * copy <sp> to <dp>
+ */
+
+void ed_gencpy(genchar *dp,const genchar *sp)
+{
+ dp = (genchar*)roundof((char*)dp-(char*)0,sizeof(genchar));
+ sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
+ while(*dp++ = *sp++);
+}
+
+/*
+ * copy at most <n> items from <sp> to <dp>
+ */
+
+void ed_genncpy(register genchar *dp,register const genchar *sp, int n)
+{
+ dp = (genchar*)roundof((char*)dp-(char*)0,sizeof(genchar));
+ sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
+ while(n-->0 && (*dp++ = *sp++));
+}
+
+#endif /* SHOPT_MULTIBYTE */
+/*
+ * find the string length of <str>
+ */
+
+int ed_genlen(register const genchar *str)
+{
+ register const genchar *sp = str;
+ sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
+ while(*sp++);
+ return(sp-str-1);
+}
+#endif /* SHOPT_ESH || SHOPT_VSH */
+
+#ifdef future
+/*
+ * returns 1 when <n> bytes starting at <a> and <b> are equal
+ */
+static int compare(register const char *a,register const char *b,register int n)
+{
+ while(n-->0)
+ {
+ if(*a++ != *b++)
+ return(0);
+ }
+ return(1);
+}
+#endif
+
+#if SHOPT_OLDTERMIO
+
+# include <sys/termio.h>
+
+#ifndef ECHOCTL
+# define ECHOCTL 0
+#endif /* !ECHOCTL */
+#define ott ep->e_ott
+
+/*
+ * For backward compatibility only
+ * This version will use termios when possible, otherwise termio
+ */
+
+int tcgetattr(int fd, struct termios *tt)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ register int r,i;
+ ep->e_tcgeta = 0;
+ ep->e_echoctl = (ECHOCTL!=0);
+ if((r=ioctl(fd,TCGETS,tt))>=0 || errno!=EINVAL)
+ return(r);
+ if((r=ioctl(fd,TCGETA,&ott)) >= 0)
+ {
+ tt->c_lflag = ott.c_lflag;
+ tt->c_oflag = ott.c_oflag;
+ tt->c_iflag = ott.c_iflag;
+ tt->c_cflag = ott.c_cflag;
+ for(i=0; i<NCC; i++)
+ tt->c_cc[i] = ott.c_cc[i];
+ ep->e_tcgeta++;
+ ep->e_echoctl = 0;
+ }
+ return(r);
+}
+
+int tcsetattr(int fd,int mode,struct termios *tt)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ register int r;
+ if(ep->e_tcgeta)
+ {
+ register int i;
+ ott.c_lflag = tt->c_lflag;
+ ott.c_oflag = tt->c_oflag;
+ ott.c_iflag = tt->c_iflag;
+ ott.c_cflag = tt->c_cflag;
+ for(i=0; i<NCC; i++)
+ ott.c_cc[i] = tt->c_cc[i];
+ if(tt->c_lflag&ECHOCTL)
+ {
+ ott.c_lflag &= ~(ECHOCTL|IEXTEN);
+ ott.c_iflag &= ~(IGNCR|ICRNL);
+ ott.c_iflag |= INLCR;
+ ott.c_cc[VEOF]= ESC; /* ESC -> eof char */
+ ott.c_cc[VEOL] = '\r'; /* CR -> eol char */
+ ott.c_cc[VEOL2] = tt->c_cc[VEOF]; /* EOF -> eol char */
+ }
+ switch(mode)
+ {
+ case TCSANOW:
+ mode = TCSETA;
+ break;
+ case TCSADRAIN:
+ mode = TCSETAW;
+ break;
+ case TCSAFLUSH:
+ mode = TCSETAF;
+ }
+ return(ioctl(fd,mode,&ott));
+ }
+ return(ioctl(fd,mode,tt));
+}
+#endif /* SHOPT_OLDTERMIO */
+
+#if KSHELL
+/*
+ * Execute keyboard trap on given buffer <inbuff> of given size <isize>
+ * <mode> < 0 for vi insert mode
+ */
+static int keytrap(Edit_t *ep,char *inbuff,register int insize, int bufsize, int mode)
+{
+ register char *cp;
+ int savexit;
+ Shell_t *shp = ep->sh;
+#if SHOPT_MULTIBYTE
+ char buff[MAXLINE];
+ ed_external(ep->e_inbuf,cp=buff);
+#else
+ cp = ep->e_inbuf;
+#endif /* SHOPT_MULTIBYTE */
+ inbuff[insize] = 0;
+ ep->e_col = ep->e_cur;
+ if(mode== -2)
+ {
+ ep->e_col++;
+ *ep->e_vi_insert = ESC;
+ }
+ else
+ *ep->e_vi_insert = 0;
+ nv_putval(ED_CHRNOD,inbuff,NV_NOFREE);
+ nv_putval(ED_COLNOD,(char*)&ep->e_col,NV_NOFREE|NV_INTEGER);
+ nv_putval(ED_TXTNOD,(char*)cp,NV_NOFREE);
+ nv_putval(ED_MODENOD,ep->e_vi_insert,NV_NOFREE);
+ savexit = shp->savexit;
+ sh_trap(shp->st.trap[SH_KEYTRAP],0);
+ shp->savexit = savexit;
+ if((cp = nv_getval(ED_CHRNOD)) == inbuff)
+ nv_unset(ED_CHRNOD);
+ else if(bufsize>0)
+ {
+ strncpy(inbuff,cp,bufsize);
+ inbuff[bufsize-1]='\0';
+ insize = strlen(inbuff);
+ }
+ else
+ insize = 0;
+ nv_unset(ED_TXTNOD);
+ return(insize);
+}
+#endif /* KSHELL */
+
+#if SHOPT_EDPREDICT
+static int ed_sortdata(const char *s1, const char *s2)
+{
+ Histmatch_t *m1 = (Histmatch_t*)s1;
+ Histmatch_t *m2 = (Histmatch_t*)s2;
+ return(strcmp(m1->data,m2->data));
+}
+
+static int ed_sortindex(const char *s1, const char *s2)
+{
+ Histmatch_t *m1 = (Histmatch_t*)s1;
+ Histmatch_t *m2 = (Histmatch_t*)s2;
+ return(m2->index-m1->index);
+}
+
+static int ed_histlencopy(const char *cp, char *dp)
+{
+ int c,n=1,col=1;
+ const char *oldcp=cp;
+ for(n=0;c = mbchar(cp);oldcp=cp,col++)
+ {
+ if(c=='\n' && *cp)
+ {
+ n += 2;
+ if(dp)
+ {
+ *dp++ = '^';
+ *dp++ = 'J';
+ col +=2;
+ }
+ }
+ else if(c=='\t')
+ {
+ n++;
+ if(dp)
+ *dp++ = ' ';
+ }
+ else
+ {
+ n += cp-oldcp;
+ if(dp)
+ {
+ while(oldcp < cp)
+ *dp++ = *oldcp++;
+ }
+ }
+
+ }
+ return(n);
+}
+
+int ed_histgen(Edit_t *ep,const char *pattern)
+{
+ Histmatch_t *mp,*mplast=0;
+ History_t *hp;
+ off_t offset;
+ int ac=0,l,m,n,index1,index2;
+ char *cp, **argv, **av, **ar;
+ if(!(hp=ep->sh->gd->hist_ptr))
+ return(0);
+ if(*pattern=='#')
+ pattern++;
+ cp = stakalloc(m=strlen(pattern)+6);
+ sfsprintf(cp,m,"@(%s)*%c",pattern,0);
+ if(ep->hlist)
+ {
+ m = strlen(ep->hpat)-4;
+ if(memcmp(pattern,ep->hpat+2,m)==0)
+ {
+ n = strcmp(cp,ep->hpat)==0;
+ for(argv=av=(char**)ep->hlist,mp=ep->hfirst; mp;mp= mp->next)
+ {
+ if(n || strmatch(mp->data,cp))
+ *av++ = (char*)mp;
+ }
+ *av = 0;
+ return(ep->hmax=av-argv);
+ }
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ }
+ pattern = ep->hpat = cp;
+ index1 = (int)hp->histind;
+ for(index2=index1-hp->histsize; index1>index2; index1--)
+ {
+ offset = hist_tell(hp,index1);
+ sfseek(hp->histfp,offset,SEEK_SET);
+ if(!(cp = sfgetr(hp->histfp,0,0)))
+ continue;
+ if(*cp=='#')
+ continue;
+ if(strmatch(cp,pattern))
+ {
+ l = ed_histlencopy(cp,(char*)0);
+ mp = (Histmatch_t*)stakalloc(sizeof(Histmatch_t)+l);
+ mp->next = mplast;
+ mplast = mp;
+ mp->len = l;
+ ed_histlencopy(cp,mp->data);
+ mp->count = 1;
+ mp->data[l] = 0;
+ mp->index = index1;
+ ac++;
+ }
+ }
+ if(ac>0)
+ {
+ l = ac;
+ argv = av = (char**)stakalloc((ac+1)*sizeof(char*));
+ for(mplast=0; l>=0 && (*av= (char*)mp); mplast=mp,mp=mp->next,av++)
+ {
+ l--;
+ }
+ *av = 0;
+ strsort(argv,ac,ed_sortdata);
+ mplast = (Histmatch_t*)argv[0];
+ for(ar= av= &argv[1]; mp=(Histmatch_t*)*av; av++)
+ {
+ if(strcmp(mp->data,mplast->data)==0)
+ {
+ mplast->count++;
+ if(mp->index> mplast->index)
+ mplast->index = mp->index;
+ continue;
+ }
+ *ar++ = (char*)(mplast=mp);
+ }
+ *ar = 0;
+ mplast->next = 0;
+ ac = ar-argv;
+ strsort(argv,ac,ed_sortindex);
+ mplast = (Histmatch_t*)argv[0];
+ for(av= &argv[1]; mp=(Histmatch_t*)*av; av++, mplast=mp)
+ mplast->next = mp;
+ mplast->next = 0;
+ }
+ ep->hlist = (Histmatch_t**)argv;
+ ep->hfirst = ep->hlist?ep->hlist[0]:0;
+ return(ep->hmax=ac);
+}
+
+void ed_histlist(Edit_t *ep,int n)
+{
+ Histmatch_t *mp,**mpp = ep->hlist+ep->hoff;
+ int i,last=0,save[2];
+ if(n)
+ {
+ /* don't bother updating the screen if there is typeahead */
+ if(!ep->e_lookahead && sfpkrd(ep->e_fd,save,1,'\r',200L,-1)>0)
+ ed_ungetchar(ep,save[0]);
+ if(ep->e_lookahead)
+ return;
+ ed_putchar(ep,'\n');
+ ed_putchar(ep,'\r');
+ }
+ else
+ {
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ ep->hlist = 0;
+ ep->nhlist = 0;
+ }
+ ed_putstring(ep,KILL_LINE);
+ if(n)
+ {
+ for(i=1; (mp= *mpp) && i <= 16 ; i++,mpp++)
+ {
+ last = 0;
+ if(mp->len >= ep->e_winsz-4)
+ {
+ last = ep->e_winsz-4;
+ save[0] = mp->data[last-1];
+ save[1] = mp->data[last];
+ mp->data[last-1] = '\n';
+ mp->data[last] = 0;
+ }
+ ed_putchar(ep,i<10?' ':'1');
+ ed_putchar(ep,i<10?'0'+i:'0'+i-10);
+ ed_putchar(ep,')');
+ ed_putchar(ep,' ');
+ ed_putstring(ep,mp->data);
+ if(last)
+ {
+ mp->data[last-1] = save[0];
+ mp->data[last] = save[1];
+ }
+ ep->nhlist = i;
+ }
+ last = i-1;
+ while(i-->0)
+ ed_putstring(ep,CURSOR_UP);
+ }
+ ed_flush(ep);
+}
+#endif /* SHOPT_EDPREDICT */
+
+void *ed_open(Shell_t *shp)
+{
+ Edit_t *ed = newof(0,Edit_t,1,0);
+ ed->sh = shp;
+ strcpy(ed->e_macro,"_??");
+ return((void*)ed);
+}
diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c
new file mode 100644
index 0000000..cb686b7
--- /dev/null
+++ b/src/cmd/ksh93/edit/emacs.c
@@ -0,0 +1,1571 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/* Original version by Michael T. Veach
+ * Adapted for ksh by David Korn */
+/* EMACS_MODES: c tabstop=4
+
+One line screen editor for any program
+
+*/
+
+
+/* The following is provided by:
+ *
+ * Matthijs N. Melchior
+ * AT&T Network Systems International
+ * APT Nederland
+ * HV BZ335 x2962
+ * hvlpb!mmelchio
+ *
+ * These are now on by default
+ *
+ * ESH_NFIRST
+ * - A ^N as first history related command after the prompt will move
+ * to the next command relative to the last known history position.
+ * It will not start at the position where the last command was entered
+ * as is done by the ^P command. Every history related command will
+ * set both the current and last position. Executing a command will
+ * only set the current position.
+ *
+ * ESH_KAPPEND
+ * - Successive kill and delete commands will accumulate their data
+ * in the kill buffer, by appending or prepending as appropriate.
+ * This mode will be reset by any command not adding something to the
+ * kill buffer.
+ *
+ * ESH_BETTER
+ * - Some enhancements:
+ * - argument for a macro is passed to its replacement
+ * - ^X^H command to find out about history position (debugging)
+ * - ^X^D command to show any debugging info
+ *
+ * I do not pretend these for changes are completely independent,
+ * but you can use them to seperate features.
+ */
+
+#include <ast.h>
+#include "FEATURE/cmds"
+#if KSHELL
+# include "defs.h"
+#else
+# include <ctype.h>
+#endif /* KSHELL */
+#include "io.h"
+
+#include "history.h"
+#include "edit.h"
+#include "terminal.h"
+
+#define ESH_NFIRST
+#define ESH_KAPPEND
+#define ESH_BETTER
+
+#undef putchar
+#define putchar(ed,c) ed_putchar(ed,c)
+#define beep() ed_ringbell()
+
+
+#if SHOPT_MULTIBYTE
+# define gencpy(a,b) ed_gencpy(a,b)
+# define genncpy(a,b,n) ed_genncpy(a,b,n)
+# define genlen(str) ed_genlen(str)
+ static int print(int);
+ static int _isword(int);
+# define isword(c) _isword(out[c])
+
+#else
+# define gencpy(a,b) strcpy((char*)(a),(char*)(b))
+# define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
+# define genlen(str) strlen(str)
+# define print(c) isprint(c)
+# define isword(c) (isalnum(out[c]) || (out[c]=='_'))
+#endif /*SHOPT_MULTIBYTE */
+
+typedef struct _emacs_
+{
+ genchar *screen; /* pointer to window buffer */
+ genchar *cursor; /* Cursor in real screen */
+ int mark;
+ int in_mult;
+ char cr_ok;
+ char CntrlO;
+ char overflow; /* Screen overflow flag set */
+ char scvalid; /* Screen is up to date */
+ char lastdraw; /* last update type */
+ int offset; /* Screen offset */
+ enum
+ {
+ CRT=0, /* Crt terminal */
+ PAPER /* Paper terminal */
+ } terminal;
+ Histloc_t _location;
+ int prevdirection;
+ Edit_t *ed; /* pointer to edit data */
+} Emacs_t;
+
+#define editb (*ep->ed)
+#define eol editb.e_eol
+#define cur editb.e_cur
+#define hline editb.e_hline
+#define hloff editb.e_hloff
+#define hismin editb.e_hismin
+#define usrkill editb.e_kill
+#define usrlnext editb.e_lnext
+#define usreof editb.e_eof
+#define usrerase editb.e_erase
+#define crallowed editb.e_crlf
+#define Prompt editb.e_prompt
+#define plen editb.e_plen
+#define kstack editb.e_killbuf
+#define lstring editb.e_search
+#define lookahead editb.e_lookahead
+#define env editb.e_env
+#define raw editb.e_raw
+#define histlines editb.e_hismax
+#define w_size editb.e_wsize
+#define drawbuff editb.e_inbuf
+#define killing editb.e_mode
+#define location ep->_location
+
+#define LBUF 100
+#define KILLCHAR UKILL
+#define ERASECHAR UERASE
+#define EOFCHAR UEOF
+#define LNEXTCHAR ULNEXT
+#define DELETE ('a'==97?0177:7)
+
+/**********************
+A large lookahead helps when the user is inserting
+characters in the middle of the line.
+************************/
+
+
+typedef enum
+{
+ FIRST, /* First time thru for logical line, prompt on screen */
+ REFRESH, /* Redraw entire screen */
+ APPEND, /* Append char before cursor to screen */
+ UPDATE, /* Update the screen as need be */
+ FINAL /* Update screen even if pending look ahead */
+} Draw_t;
+
+static void draw(Emacs_t*,Draw_t);
+static int escape(Emacs_t*,genchar*, int);
+static void putstring(Emacs_t*,char*);
+static void search(Emacs_t*,genchar*,int);
+static void setcursor(Emacs_t*,int, int);
+static void show_info(Emacs_t*,const char*);
+static void xcommands(Emacs_t*,int);
+
+int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
+{
+ Edit_t *ed = (Edit_t*)context;
+ register int c;
+ register int i;
+ register genchar *out;
+ register int count;
+ register Emacs_t *ep = ed->e_emacs;
+ int adjust,oadjust;
+ char backslash;
+ genchar *kptr;
+ char prompt[PRSIZE];
+ genchar Screen[MAXLINE];
+ memset(Screen,0,sizeof(Screen));
+ if(!ep)
+ {
+ ep = ed->e_emacs = newof(0,Emacs_t,1,0);
+ ep->ed = ed;
+ ep->prevdirection = 1;
+ location.hist_command = -5;
+ }
+ Prompt = prompt;
+ ep->screen = Screen;
+ ep->lastdraw = FINAL;
+ if(tty_raw(ERRIO,0) < 0)
+ {
+ return(reedit?reedit:ed_read(context, fd,buff,scend,0));
+ }
+ raw = 1;
+ /* This mess in case the read system call fails */
+
+ ed_setup(ep->ed,fd,reedit);
+ out = (genchar*)buff;
+#if SHOPT_MULTIBYTE
+ out = (genchar*)roundof(buff-(char*)0,sizeof(genchar));
+ if(reedit)
+ ed_internal(buff,out);
+#endif /* SHOPT_MULTIBYTE */
+ if(!kstack)
+ {
+ kstack = (genchar*)malloc(CHARSIZE*MAXLINE);
+ kstack[0] = '\0';
+ }
+ drawbuff = out;
+#ifdef ESH_NFIRST
+ if (location.hist_command == -5) /* to be initialized */
+ {
+ kstack[0] = '\0'; /* also clear kstack... */
+ location.hist_command = hline;
+ location.hist_line = hloff;
+ }
+ if (location.hist_command <= hismin) /* don't start below minimum */
+ {
+ location.hist_command = hismin + 1;
+ location.hist_line = 0;
+ }
+ ep->in_mult = hloff; /* save pos in last command */
+#endif /* ESH_NFIRST */
+ i = sigsetjmp(env,0);
+ if (i !=0)
+ {
+ if(ep->ed->e_multiline)
+ {
+ cur = eol;
+ draw(ep,FINAL);
+ ed_flush(ep->ed);
+ }
+ tty_cooked(ERRIO);
+ if (i == UEOF)
+ {
+ return(0); /* EOF */
+ }
+ return(-1); /* some other error */
+ }
+ out[reedit] = 0;
+ if(scend+plen > (MAXLINE-2))
+ scend = (MAXLINE-2)-plen;
+ ep->mark = 0;
+ cur = eol;
+ draw(ep,reedit?REFRESH:FIRST);
+ adjust = -1;
+ backslash = 0;
+ if (ep->CntrlO)
+ {
+#ifdef ESH_NFIRST
+ ed_ungetchar(ep->ed,cntl('N'));
+#else
+ location = hist_locate(shgd->hist_ptr,location.hist_command,location.hist_line,1);
+ if (location.hist_command < histlines)
+ {
+ hline = location.hist_command;
+ hloff = location.hist_line;
+ hist_copy((char*)kstack,MAXLINE, hline,hloff);
+# if SHOPT_MULTIBYTE
+ ed_internal((char*)kstack,kstack);
+# endif /* SHOPT_MULTIBYTE */
+ ed_ungetchar(ep->ed,cntl('Y'));
+ }
+#endif /* ESH_NFIRST */
+ }
+ ep->CntrlO = 0;
+ while ((c = ed_getchar(ep->ed,0)) != (-1))
+ {
+ if (backslash)
+ {
+ backslash = 0;
+ if (c==usrerase||c==usrkill||(!print(c) &&
+ (c!='\r'&&c!='\n')))
+ {
+ /* accept a backslashed character */
+ cur--;
+ out[cur++] = c;
+ out[eol] = '\0';
+ draw(ep,APPEND);
+ continue;
+ }
+ }
+ if (c == usrkill)
+ {
+ c = KILLCHAR ;
+ }
+ else if (c == usrerase)
+ {
+ c = ERASECHAR ;
+ }
+ else if (c == usrlnext)
+ {
+ c = LNEXTCHAR ;
+ }
+ else if ((c == usreof)&&(eol == 0))
+ {
+ c = EOFCHAR;
+ }
+#ifdef ESH_KAPPEND
+ if (--killing <= 0) /* reset killing flag */
+ killing = 0;
+#endif
+ oadjust = count = adjust;
+ if(count<0)
+ count = 1;
+ adjust = -1;
+ i = cur;
+ switch(c)
+ {
+ case LNEXTCHAR:
+ c = ed_getchar(ep->ed,2);
+ goto do_default_processing;
+ case cntl('V'):
+ show_info(ep,fmtident(e_version));
+ continue;
+ case '\0':
+ ep->mark = i;
+ continue;
+ case cntl('X'):
+ xcommands(ep,count);
+ continue;
+ case EOFCHAR:
+ ed_flush(ep->ed);
+ tty_cooked(ERRIO);
+ return(0);
+#ifdef u370
+ case cntl('S') :
+ case cntl('Q') :
+ continue;
+#endif /* u370 */
+ case '\t':
+ if(cur>0 && ep->ed->sh->nextprompt)
+ {
+ if(ep->ed->e_tabcount==0)
+ {
+ ep->ed->e_tabcount=1;
+ ed_ungetchar(ep->ed,ESC);
+ goto do_escape;
+ }
+ else if(ep->ed->e_tabcount==1)
+ {
+ ed_ungetchar(ep->ed,'=');
+ goto do_escape;
+ }
+ ep->ed->e_tabcount = 0;
+ }
+ do_default_processing:
+ default:
+
+ if ((eol+1) >= (scend)) /* will not fit on line */
+ {
+ ed_ungetchar(ep->ed,c); /* save character for next line */
+ goto process;
+ }
+ for(i= ++eol; i>cur; i--)
+ out[i] = out[i-1];
+ backslash = (c == '\\');
+ out[cur++] = c;
+ draw(ep,APPEND);
+ continue;
+ case cntl('Y') :
+ {
+ c = genlen(kstack);
+ if ((c + eol) > scend)
+ {
+ beep();
+ continue;
+ }
+ ep->mark = i;
+ for(i=eol;i>=cur;i--)
+ out[c+i] = out[i];
+ kptr=kstack;
+ while (i = *kptr++)
+ out[cur++] = i;
+ draw(ep,UPDATE);
+ eol = genlen(out);
+ continue;
+ }
+ case '\n':
+ case '\r':
+ c = '\n';
+ goto process;
+
+ case DELETE: /* delete char 0x7f */
+ case '\b': /* backspace, ^h */
+ case ERASECHAR :
+ if (count > i)
+ count = i;
+#ifdef ESH_KAPPEND
+ kptr = &kstack[count]; /* move old contents here */
+ if (killing) /* prepend to killbuf */
+ {
+ c = genlen(kstack) + CHARSIZE; /* include '\0' */
+ while(c--) /* copy stuff */
+ kptr[c] = kstack[c];
+ }
+ else
+ *kptr = 0; /* this is end of data */
+ killing = 2; /* we are killing */
+ i -= count;
+ eol -= count;
+ genncpy(kstack,out+i,cur-i);
+#else
+ while ((count--)&&(i>0))
+ {
+ i--;
+ eol--;
+ }
+ genncpy(kstack,out+i,cur-i);
+ kstack[cur-i] = 0;
+#endif /* ESH_KAPPEND */
+ gencpy(out+i,out+cur);
+ ep->mark = i;
+ goto update;
+ case cntl('W') :
+#ifdef ESH_KAPPEND
+ ++killing; /* keep killing flag */
+#endif
+ if (ep->mark > eol )
+ ep->mark = eol;
+ if (ep->mark == i)
+ continue;
+ if (ep->mark > i)
+ {
+ adjust = ep->mark - i;
+ ed_ungetchar(ep->ed,cntl('D'));
+ continue;
+ }
+ adjust = i - ep->mark;
+ ed_ungetchar(ep->ed,usrerase);
+ continue;
+ case cntl('D') :
+ ep->mark = i;
+#ifdef ESH_KAPPEND
+ if (killing)
+ kptr = &kstack[genlen(kstack)]; /* append here */
+ else
+ kptr = kstack;
+ killing = 2; /* we are now killing */
+#else
+ kptr = kstack;
+#endif /* ESH_KAPPEND */
+ while ((count--)&&(eol>0)&&(i<eol))
+ {
+ *kptr++ = out[i];
+ eol--;
+ while(1)
+ {
+ if ((out[i] = out[(i+1)])==0)
+ break;
+ i++;
+ }
+ i = cur;
+ }
+ *kptr = '\0';
+ goto update;
+ case cntl('C') :
+ case cntl('F') :
+ {
+ int cntlC = (c==cntl('C'));
+ while (count-- && eol>i)
+ {
+ if (cntlC)
+ {
+ c = out[i];
+#if SHOPT_MULTIBYTE
+ if((c&~STRIP)==0 && islower(c))
+#else
+ if(islower(c))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ c += 'A' - 'a';
+ out[i] = c;
+ }
+ }
+ i++;
+ }
+ goto update;
+ }
+ case cntl(']') :
+ c = ed_getchar(ep->ed,1);
+ if ((count == 0) || (count > eol))
+ {
+ beep();
+ continue;
+ }
+ if (out[i])
+ i++;
+ while (i < eol)
+ {
+ if (out[i] == c && --count==0)
+ goto update;
+ i++;
+ }
+ i = 0;
+ while (i < cur)
+ {
+ if (out[i] == c && --count==0)
+ break;
+ i++;
+ };
+
+update:
+ cur = i;
+ draw(ep,UPDATE);
+ continue;
+
+ case cntl('B') :
+ if (count > i)
+ count = i;
+ i -= count;
+ goto update;
+ case cntl('T') :
+ if ((sh_isoption(SH_EMACS))&& (eol!=i))
+ i++;
+ if (i >= 2)
+ {
+ c = out[i - 1];
+ out[i-1] = out[i-2];
+ out[i-2] = c;
+ }
+ else
+ {
+ if(sh_isoption(SH_EMACS))
+ i--;
+ beep();
+ continue;
+ }
+ goto update;
+ case cntl('A') :
+ i = 0;
+ goto update;
+ case cntl('E') :
+ i = eol;
+ goto update;
+ case cntl('U') :
+ adjust = 4*count;
+ continue;
+ case KILLCHAR :
+ cur = 0;
+ oadjust = -1;
+ case cntl('K') :
+ if(oadjust >= 0)
+ {
+#ifdef ESH_KAPPEND
+ killing = 2; /* set killing signal */
+#endif
+ ep->mark = count;
+ ed_ungetchar(ep->ed,cntl('W'));
+ continue;
+ }
+ i = cur;
+ eol = i;
+ ep->mark = i;
+#ifdef ESH_KAPPEND
+ if (killing) /* append to kill buffer */
+ gencpy(&kstack[genlen(kstack)], &out[i]);
+ else
+ gencpy(kstack,&out[i]);
+ killing = 2; /* set killing signal */
+#else
+ gencpy(kstack,&out[i]);
+#endif /* ESH_KAPPEND */
+ out[i] = 0;
+ draw(ep,UPDATE);
+ if (c == KILLCHAR)
+ {
+ if (ep->terminal == PAPER)
+ {
+ putchar(ep->ed,'\n');
+ putstring(ep,Prompt);
+ }
+ c = ed_getchar(ep->ed,0);
+ if (c != usrkill)
+ {
+ ed_ungetchar(ep->ed,c);
+ continue;
+ }
+ if (ep->terminal == PAPER)
+ ep->terminal = CRT;
+ else
+ {
+ ep->terminal = PAPER;
+ putchar(ep->ed,'\n');
+ putstring(ep,Prompt);
+ }
+ }
+ continue;
+ case cntl('L'):
+ if(!ep->ed->e_nocrnl)
+ ed_crlf(ep->ed);
+ draw(ep,REFRESH);
+ ep->ed->e_nocrnl = 0;
+ continue;
+ case cntl('[') :
+ do_escape:
+ adjust = escape(ep,out,oadjust);
+ continue;
+ case cntl('R') :
+ search(ep,out,count);
+ goto drawline;
+ case cntl('P') :
+#if SHOPT_EDPREDICT
+ if(ep->ed->hlist)
+ {
+ if(ep->ed->hoff == 0)
+ {
+ beep();
+ continue;
+ }
+ ep->ed->hoff--;
+ goto hupdate;
+ }
+#endif /* SHOPT_EDPREDICT */
+ if (count <= hloff)
+ hloff -= count;
+ else
+ {
+ hline -= count - hloff;
+ hloff = 0;
+ }
+#ifdef ESH_NFIRST
+ if (hline <= hismin)
+#else
+ if (hline < hismin)
+#endif /* ESH_NFIRST */
+ {
+ hline = hismin+1;
+ beep();
+#ifndef ESH_NFIRST
+ continue;
+#endif
+ }
+ goto common;
+
+ case cntl('O') :
+ location.hist_command = hline;
+ location.hist_line = hloff;
+ ep->CntrlO = 1;
+ c = '\n';
+ goto process;
+ case cntl('N') :
+#if SHOPT_EDPREDICT
+ if(ep->ed->hlist)
+ {
+ if(ep->ed->hoff >= ep->ed->hmax)
+ {
+ beep();
+ continue;
+ }
+ ep->ed->hoff++;
+ hupdate:
+ ed_histlist(ep->ed,*ep->ed->hlist!=0);
+ draw(ep,REFRESH);
+ continue;
+ }
+#endif /* SHOPT_EDPREDICT */
+#ifdef ESH_NFIRST
+ hline = location.hist_command; /* start at saved position */
+ hloff = location.hist_line;
+#endif /* ESH_NFIRST */
+ location = hist_locate(shgd->hist_ptr,hline,hloff,count);
+ if (location.hist_command > histlines)
+ {
+ beep();
+#ifdef ESH_NFIRST
+ location.hist_command = histlines;
+ location.hist_line = ep->in_mult;
+#else
+ continue;
+#endif /* ESH_NFIRST */
+ }
+ hline = location.hist_command;
+ hloff = location.hist_line;
+ common:
+#ifdef ESH_NFIRST
+ location.hist_command = hline; /* save current position */
+ location.hist_line = hloff;
+#endif
+ cur = 0;
+ draw(ep,UPDATE);
+ hist_copy((char*)out,MAXLINE, hline,hloff);
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)(out),out);
+#endif /* SHOPT_MULTIBYTE */
+ drawline:
+ eol = genlen(out);
+ cur = eol;
+ draw(ep,UPDATE);
+ continue;
+ }
+
+ }
+
+process:
+
+ if (c == (-1))
+ {
+ lookahead = 0;
+ beep();
+ *out = '\0';
+ }
+ draw(ep,FINAL);
+ tty_cooked(ERRIO);
+ if(ed->e_nlist)
+ {
+ ed->e_nlist = 0;
+ stakset(ed->e_stkptr,ed->e_stkoff);
+ }
+ if(c == '\n')
+ {
+ out[eol++] = '\n';
+ out[eol] = '\0';
+ ed_crlf(ep->ed);
+ }
+#if SHOPT_MULTIBYTE
+ ed_external(out,buff);
+#endif /* SHOPT_MULTIBYTE */
+ i = strlen(buff);
+ if (i)
+ return(i);
+ return(-1);
+}
+
+static void show_info(Emacs_t *ep,const char *str)
+{
+ register genchar *out = drawbuff;
+ register int c;
+ genchar string[LBUF];
+ int sav_cur = cur;
+ /* save current line */
+ genncpy(string,out,sizeof(string)/sizeof(*string));
+ *out = 0;
+ cur = 0;
+#if SHOPT_MULTIBYTE
+ ed_internal(str,out);
+#else
+ gencpy(out,str);
+#endif /* SHOPT_MULTIBYTE */
+ draw(ep,UPDATE);
+ c = ed_getchar(ep->ed,0);
+ if(c!=' ')
+ ed_ungetchar(ep->ed,c);
+ /* restore line */
+ cur = sav_cur;
+ genncpy(out,string,sizeof(string)/sizeof(*string));
+ draw(ep,UPDATE);
+}
+
+static void putstring(Emacs_t* ep,register char *sp)
+{
+ register int c;
+ while (c= *sp++)
+ putchar(ep->ed,c);
+}
+
+
+static int escape(register Emacs_t* ep,register genchar *out,int count)
+{
+ register int i,value;
+ int digit,ch;
+ digit = 0;
+ value = 0;
+ while ((i=ed_getchar(ep->ed,0)),isdigit(i))
+ {
+ value *= 10;
+ value += (i - '0');
+ digit = 1;
+ }
+ if (digit)
+ {
+ ed_ungetchar(ep->ed,i) ;
+#ifdef ESH_KAPPEND
+ ++killing; /* don't modify killing signal */
+#endif
+ return(value);
+ }
+ value = count;
+ if(value<0)
+ value = 1;
+ switch(ch=i)
+ {
+ case cntl('V'):
+ show_info(ep,fmtident(e_version));
+ return(-1);
+ case ' ':
+ ep->mark = cur;
+ return(-1);
+
+#ifdef ESH_KAPPEND
+ case '+': /* M-+ = append next kill */
+ killing = 2;
+ return -1; /* no argument for next command */
+#endif
+
+ case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
+ ed_ungetchar(ep->ed,cntl('Y'));
+ ed_ungetchar(ep->ed,cntl('W'));
+#ifdef ESH_KAPPEND
+ killing = 0; /* start fresh */
+#endif
+ return(-1);
+
+ case 'l': /* M-l == lower-case */
+ case 'd':
+ case 'c':
+ case 'f':
+ {
+ i = cur;
+ while(value-- && i<eol)
+ {
+ while ((out[i])&&(!isword(i)))
+ i++;
+ while ((out[i])&&(isword(i)))
+ i++;
+ }
+ if(ch=='l')
+ {
+ value = i-cur;
+ while (value-- > 0)
+ {
+ i = out[cur];
+#if SHOPT_MULTIBYTE
+ if((i&~STRIP)==0 && isupper(i))
+#else
+ if(isupper(i))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ i += 'a' - 'A';
+ out[cur] = i;
+ }
+ cur++;
+ }
+ draw(ep,UPDATE);
+ return(-1);
+ }
+
+ else if(ch=='f')
+ goto update;
+ else if(ch=='c')
+ {
+ ed_ungetchar(ep->ed,cntl('C'));
+ return(i-cur);
+ }
+ else
+ {
+ if (i-cur)
+ {
+ ed_ungetchar(ep->ed,cntl('D'));
+#ifdef ESH_KAPPEND
+ ++killing; /* keep killing signal */
+#endif
+ return(i-cur);
+ }
+ beep();
+ return(-1);
+ }
+ }
+
+
+ case 'b':
+ case DELETE :
+ case '\b':
+ case 'h':
+ {
+ i = cur;
+ while(value-- && i>0)
+ {
+ i--;
+ while ((i>0)&&(!isword(i)))
+ i--;
+ while ((i>0)&&(isword(i-1)))
+ i--;
+ }
+ if(ch=='b')
+ goto update;
+ else
+ {
+ ed_ungetchar(ep->ed,usrerase);
+#ifdef ESH_KAPPEND
+ ++killing;
+#endif
+ return(cur-i);
+ }
+ }
+
+ case '>':
+ ed_ungetchar(ep->ed,cntl('N'));
+#ifdef ESH_NFIRST
+ if (ep->in_mult)
+ {
+ location.hist_command = histlines;
+ location.hist_line = ep->in_mult - 1;
+ }
+ else
+ {
+ location.hist_command = histlines - 1;
+ location.hist_line = 0;
+ }
+#else
+ hline = histlines-1;
+ hloff = 0;
+#endif /* ESH_NFIRST */
+ return(0);
+
+ case '<':
+ ed_ungetchar(ep->ed,cntl('P'));
+ hloff = 0;
+#ifdef ESH_NFIRST
+ hline = hismin + 1;
+ return 0;
+#else
+ return(hline-hismin);
+#endif /* ESH_NFIRST */
+
+
+ case '#':
+ ed_ungetchar(ep->ed,'\n');
+ ed_ungetchar(ep->ed,(out[0]=='#')?cntl('D'):'#');
+ ed_ungetchar(ep->ed,cntl('A'));
+ return(-1);
+ case '_' :
+ case '.' :
+ {
+ genchar name[MAXLINE];
+ char buf[MAXLINE];
+ char *ptr;
+ ptr = hist_word(buf,MAXLINE,(count?count:-1));
+ if(ptr==0)
+ {
+ beep();
+ break;
+ }
+ if ((eol - cur) >= sizeof(name))
+ {
+ beep();
+ return(-1);
+ }
+ ep->mark = cur;
+ gencpy(name,&out[cur]);
+ while(*ptr)
+ {
+ out[cur++] = *ptr++;
+ eol++;
+ }
+ gencpy(&out[cur],name);
+ draw(ep,UPDATE);
+ return(-1);
+ }
+#if KSHELL
+
+#if SHOPT_EDPREDICT
+ case '\n': case '\t':
+ if(!ep->ed->hlist)
+ {
+ beep();
+ break;
+ }
+ if(ch=='\n')
+ ed_ungetchar(ep->ed,'\n');
+#endif /* SHOPT_EDPREDICT */
+ /* file name expansion */
+ case cntl('[') : /* filename completion */
+#if SHOPT_EDPREDICT
+ if(ep->ed->hlist)
+ {
+ value += ep->ed->hoff;
+ if(value > ep->ed->nhlist)
+ beep();
+ else
+ {
+ value = histlines - ep->ed->hlist[value-1]->index;
+ ed_histlist(ep->ed,0);
+ ed_ungetchar(ep->ed,cntl('P'));
+ return(value);
+ }
+ }
+#endif /* SHOPT_EDPREDICT */
+ i = '\\';
+ case '*': /* filename expansion */
+ case '=': /* escape = - list all matching file names */
+ ep->mark = cur;
+ if(ed_expand(ep->ed,(char*)out,&cur,&eol,i,count) < 0)
+ {
+ if(ep->ed->e_tabcount==1)
+ {
+ ep->ed->e_tabcount=2;
+ ed_ungetchar(ep->ed,cntl('\t'));
+ return(-1);
+ }
+ beep();
+ }
+ else if(i=='=')
+ {
+ draw(ep,REFRESH);
+ if(count>0)
+ ep->ed->e_tabcount=0;
+ else
+ {
+ i=ed_getchar(ep->ed,0);
+ ed_ungetchar(ep->ed,i);
+ if(isdigit(i))
+ ed_ungetchar(ep->ed,ESC);
+ }
+ }
+ else
+ {
+ if(i=='\\' && cur>ep->mark && (out[cur-1]=='/' || out[cur-1]==' '))
+ ep->ed->e_tabcount=0;
+ draw(ep,UPDATE);
+ }
+ return(-1);
+
+ /* search back for character */
+ case cntl(']'): /* feature not in book */
+ {
+ int c = ed_getchar(ep->ed,1);
+ if ((value == 0) || (value > eol))
+ {
+ beep();
+ return(-1);
+ }
+ i = cur;
+ if (i > 0)
+ i--;
+ while (i >= 0)
+ {
+ if (out[i] == c && --value==0)
+ goto update;
+ i--;
+ }
+ i = eol;
+ while (i > cur)
+ {
+ if (out[i] == c && --value==0)
+ break;
+ i--;
+ };
+
+ }
+ update:
+ cur = i;
+ draw(ep,UPDATE);
+ return(-1);
+
+#ifdef _cmd_tput
+ case cntl('L'): /* clear screen */
+ sh_trap("tput clear", 0);
+ draw(ep,REFRESH);
+ return(-1);
+#endif
+ case '[': /* feature not in book */
+ switch(i=ed_getchar(ep->ed,1))
+ {
+ case 'A':
+#if SHOPT_EDPREDICT
+ if(!ep->ed->hlist && cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
+#else
+ if(cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
+#endif /* SHOPT_EDPREDICT */
+ {
+ if(ep->lastdraw==APPEND && ep->prevdirection != -2)
+ {
+ out[cur] = 0;
+ gencpy((genchar*)lstring+1,out);
+#if SHOPT_MULTIBYTE
+ ed_external((genchar*)lstring+1,lstring+1);
+#endif /* SHOPT_MULTIBYTE */
+ *lstring = '^';
+ ep->prevdirection = -2;
+ }
+ if(*lstring)
+ {
+ ed_ungetchar(ep->ed,'\r');
+ ed_ungetchar(ep->ed,cntl('R'));
+ return(-1);
+ }
+ }
+ *lstring = 0;
+ ed_ungetchar(ep->ed,cntl('P'));
+ return(-1);
+ case 'B':
+ ed_ungetchar(ep->ed,cntl('N'));
+ return(-1);
+ case 'C':
+ ed_ungetchar(ep->ed,cntl('F'));
+ return(-1);
+ case 'D':
+ ed_ungetchar(ep->ed,cntl('B'));
+ return(-1);
+ case 'H':
+ ed_ungetchar(ep->ed,cntl('A'));
+ return(-1);
+ case 'Y':
+ ed_ungetchar(ep->ed,cntl('E'));
+ return(-1);
+ default:
+ ed_ungetchar(ep->ed,i);
+ }
+ i = '_';
+
+ default:
+ /* look for user defined macro definitions */
+ if(ed_macro(ep->ed,i))
+# ifdef ESH_BETTER
+ return(count); /* pass argument to macro */
+# else
+ return(-1);
+# endif /* ESH_BETTER */
+#else
+ update:
+ cur = i;
+ draw(ep,UPDATE);
+ return(-1);
+
+ default:
+#endif /* KSHELL */
+ beep();
+ return(-1);
+ }
+ return(-1);
+}
+
+
+/*
+ * This routine process all commands starting with ^X
+ */
+
+static void xcommands(register Emacs_t *ep,int count)
+{
+ register int i = ed_getchar(ep->ed,0);
+ NOT_USED(count);
+ switch(i)
+ {
+ case cntl('X'): /* exchange dot and mark */
+ if (ep->mark > eol)
+ ep->mark = eol;
+ i = ep->mark;
+ ep->mark = cur;
+ cur = i;
+ draw(ep,UPDATE);
+ return;
+
+#if KSHELL
+# ifdef ESH_BETTER
+ case cntl('E'): /* invoke emacs on current command */
+ if(ed_fulledit(ep->ed)==-1)
+ beep();
+ else
+ {
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)drawbuff,drawbuff);
+#endif /* SHOPT_MULTIBYTE */
+ ed_ungetchar(ep->ed,'\n');
+ }
+ return;
+
+# define itos(i) fmtbase((long)(i),0,0)/* want signed conversion */
+
+ case cntl('H'): /* ^X^H show history info */
+ {
+ char hbuf[MAXLINE];
+
+ strcpy(hbuf, "Current command ");
+ strcat(hbuf, itos(hline));
+ if (hloff)
+ {
+ strcat(hbuf, " (line ");
+ strcat(hbuf, itos(hloff+1));
+ strcat(hbuf, ")");
+ }
+ if ((hline != location.hist_command) ||
+ (hloff != location.hist_line))
+ {
+ strcat(hbuf, "; Previous command ");
+ strcat(hbuf, itos(location.hist_command));
+ if (location.hist_line)
+ {
+ strcat(hbuf, " (line ");
+ strcat(hbuf, itos(location.hist_line+1));
+ strcat(hbuf, ")");
+ }
+ }
+ show_info(ep,hbuf);
+ return;
+ }
+# if 0 /* debugging, modify as required */
+ case cntl('D'): /* ^X^D show debugging info */
+ {
+ char debugbuf[MAXLINE];
+
+ strcpy(debugbuf, "count=");
+ strcat(debugbuf, itos(count));
+ strcat(debugbuf, " eol=");
+ strcat(debugbuf, itos(eol));
+ strcat(debugbuf, " cur=");
+ strcat(debugbuf, itos(cur));
+ strcat(debugbuf, " crallowed=");
+ strcat(debugbuf, itos(crallowed));
+ strcat(debugbuf, " plen=");
+ strcat(debugbuf, itos(plen));
+ strcat(debugbuf, " w_size=");
+ strcat(debugbuf, itos(w_size));
+
+ show_info(ep,debugbuf);
+ return;
+ }
+# endif /* debugging code */
+# endif /* ESH_BETTER */
+#endif /* KSHELL */
+
+ default:
+ beep();
+ return;
+ }
+}
+
+static void search(Emacs_t* ep,genchar *out,int direction)
+{
+#ifndef ESH_NFIRST
+ Histloc_t location;
+#endif
+ register int i,sl;
+ genchar str_buff[LBUF];
+ register genchar *string = drawbuff;
+ /* save current line */
+ int sav_cur = cur;
+ genncpy(str_buff,string,sizeof(str_buff)/sizeof(*str_buff));
+ string[0] = '^';
+ string[1] = 'R';
+ string[2] = '\0';
+ sl = 2;
+ cur = sl;
+ draw(ep,UPDATE);
+ while ((i = ed_getchar(ep->ed,1))&&(i != '\r')&&(i != '\n'))
+ {
+ if (i==usrerase || i==DELETE || i=='\b' || i==ERASECHAR)
+ {
+ if (sl > 2)
+ {
+ string[--sl] = '\0';
+ cur = sl;
+ draw(ep,UPDATE);
+ }
+ else
+ goto restore;
+ continue;
+ }
+ if(i == ep->ed->e_intr)
+ goto restore;
+ if (i==usrkill)
+ {
+ beep();
+ goto restore;
+ }
+ if (i == '\\')
+ {
+ string[sl++] = '\\';
+ string[sl] = '\0';
+ cur = sl;
+ draw(ep,APPEND);
+ i = ed_getchar(ep->ed,1);
+ string[--sl] = '\0';
+ }
+ string[sl++] = i;
+ string[sl] = '\0';
+ cur = sl;
+ draw(ep,APPEND);
+ }
+ i = genlen(string);
+
+ if(ep->prevdirection == -2 && i!=2 || direction!=1)
+ ep->prevdirection = -1;
+ if (direction < 1)
+ {
+ ep->prevdirection = -ep->prevdirection;
+ direction = 1;
+ }
+ else
+ direction = -1;
+ if (i != 2)
+ {
+#if SHOPT_MULTIBYTE
+ ed_external(string,(char*)string);
+#endif /* SHOPT_MULTIBYTE */
+ strncpy(lstring,((char*)string)+2,SEARCHSIZE);
+ lstring[SEARCHSIZE-1] = 0;
+ ep->prevdirection = direction;
+ }
+ else
+ direction = ep->prevdirection ;
+ location = hist_find(shgd->hist_ptr,(char*)lstring,hline,1,direction);
+ i = location.hist_command;
+ if(i>0)
+ {
+ hline = i;
+#ifdef ESH_NFIRST
+ hloff = location.hist_line = 0; /* display first line of multi line command */
+#else
+ hloff = location.hist_line;
+#endif /* ESH_NFIRST */
+ hist_copy((char*)out,MAXLINE, hline,hloff);
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)out,out);
+#endif /* SHOPT_MULTIBYTE */
+ return;
+ }
+ if (i < 0)
+ {
+ beep();
+#ifdef ESH_NFIRST
+ location.hist_command = hline;
+ location.hist_line = hloff;
+#else
+ hloff = 0;
+ hline = histlines;
+#endif /* ESH_NFIRST */
+ }
+restore:
+ genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff));
+ cur = sav_cur;
+ return;
+}
+
+
+/* Adjust screen to agree with inputs: logical line and cursor */
+/* If 'first' assume screen is blank */
+/* Prompt is always kept on the screen */
+
+static void draw(register Emacs_t *ep,Draw_t option)
+{
+#define NORMAL ' '
+#define LOWER '<'
+#define BOTH '*'
+#define UPPER '>'
+
+ register genchar *sptr; /* Pointer within screen */
+ genchar nscreen[2*MAXLINE]; /* New entire screen */
+ genchar *ncursor; /* New cursor */
+ register genchar *nptr; /* Pointer to New screen */
+ char longline; /* Line overflow */
+ genchar *logcursor;
+ genchar *nscend; /* end of logical screen */
+ register int i;
+
+ nptr = nscreen;
+ sptr = drawbuff;
+ logcursor = sptr + cur;
+ longline = NORMAL;
+ ep->lastdraw = option;
+
+ if (option == FIRST || option == REFRESH)
+ {
+ ep->overflow = NORMAL;
+ ep->cursor = ep->screen;
+ ep->offset = 0;
+ ep->cr_ok = crallowed;
+ if (option == FIRST)
+ {
+ ep->scvalid = 1;
+ return;
+ }
+ *ep->cursor = '\0';
+ putstring(ep,Prompt); /* start with prompt */
+ }
+
+ /*********************
+ Do not update screen if pending characters
+ **********************/
+
+ if ((lookahead)&&(option != FINAL))
+ {
+
+ ep->scvalid = 0; /* Screen is out of date, APPEND will not work */
+
+ return;
+ }
+
+ /***************************************
+ If in append mode, cursor at end of line, screen up to date,
+ the previous character was a 'normal' character,
+ and the window has room for another character.
+ Then output the character and adjust the screen only.
+ *****************************************/
+
+
+ i = *(logcursor-1); /* last character inserted */
+#if SHOPT_EDPREDICT
+ if(option==FINAL)
+ {
+ if(ep->ed->hlist)
+ ed_histlist(ep->ed,0);
+ }
+ else if((option==UPDATE||option==APPEND) && drawbuff[0]=='#' && cur>1 && cur==eol && drawbuff[cur-1]!='*')
+ {
+ int n;
+ drawbuff[cur+1]=0;
+# if SHOPT_MULTIBYTE
+ ed_external(drawbuff,(char*)drawbuff);
+# endif /*SHOPT_MULTIBYTE */
+ n = ed_histgen(ep->ed,(char*)drawbuff);
+# if SHOPT_MULTIBYTE
+ ed_internal((char*)drawbuff,drawbuff);
+# endif /*SHOPT_MULTIBYTE */
+ if(ep->ed->hlist)
+ {
+ ed_histlist(ep->ed,n);
+ putstring(ep,Prompt);
+ ed_setcursor(ep->ed,ep->screen,0,ep->cursor-ep->screen, 0);
+ }
+ else
+ ed_ringbell();
+
+ }
+#endif /* SHOPT_EDPREDICT */
+
+ if ((option == APPEND)&&(ep->scvalid)&&(*logcursor == '\0')&&
+ print(i)&&((ep->cursor-ep->screen)<(w_size-1)))
+ {
+ putchar(ep->ed,i);
+ *ep->cursor++ = i;
+ *ep->cursor = '\0';
+ return;
+ }
+
+ /* copy the line */
+ ncursor = nptr + ed_virt_to_phys(ep->ed,sptr,nptr,cur,0,0);
+ nptr += genlen(nptr);
+ sptr += genlen(sptr);
+ nscend = nptr - 1;
+ if(sptr == logcursor)
+ ncursor = nptr;
+
+ /*********************
+ Does ncursor appear on the screen?
+ If not, adjust the screen offset so it does.
+ **********************/
+
+ i = ncursor - nscreen;
+
+ if ((ep->offset && i<=ep->offset)||(i >= (ep->offset+w_size)))
+ {
+ /* Center the cursor on the screen */
+ ep->offset = i - (w_size>>1);
+ if (--ep->offset < 0)
+ ep->offset = 0;
+ }
+
+ /*********************
+ Is the range of screen[0] thru screen[w_size] up-to-date
+ with nscreen[offset] thru nscreen[offset+w_size] ?
+ If not, update as need be.
+ ***********************/
+
+ nptr = &nscreen[ep->offset];
+ sptr = ep->screen;
+
+ i = w_size;
+
+ while (i-- > 0)
+ {
+
+ if (*nptr == '\0')
+ {
+ *(nptr + 1) = '\0';
+ *nptr = ' ';
+ }
+ if (*sptr == '\0')
+ {
+ *(sptr + 1) = '\0';
+ *sptr = ' ';
+ }
+ if (*nptr == *sptr)
+ {
+ nptr++;
+ sptr++;
+ continue;
+ }
+ setcursor(ep,sptr-ep->screen,*nptr);
+ *sptr++ = *nptr++;
+#if SHOPT_MULTIBYTE
+ while(*nptr==MARKER)
+ {
+ if(*sptr=='\0')
+ *(sptr + 1) = '\0';
+ *sptr++ = *nptr++;
+ i--;
+ ep->cursor++;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ }
+ if(ep->ed->e_multiline && option == REFRESH && ep->ed->e_nocrnl==0)
+ ed_setcursor(ep->ed, ep->screen, ep->cursor-ep->screen, ep->ed->e_peol, -1);
+
+
+ /******************
+
+ Screen overflow checks
+
+ ********************/
+
+ if (nscend >= &nscreen[ep->offset+w_size])
+ {
+ if (ep->offset > 0)
+ longline = BOTH;
+ else
+ longline = UPPER;
+ }
+ else
+ {
+ if (ep->offset > 0)
+ longline = LOWER;
+ }
+
+ /* Update screen overflow indicator if need be */
+
+ if (longline != ep->overflow)
+ {
+ setcursor(ep,w_size,longline);
+ ep->overflow = longline;
+ }
+ i = (ncursor-nscreen) - ep->offset;
+ setcursor(ep,i,0);
+ if(option==FINAL && ep->ed->e_multiline)
+ setcursor(ep,nscend+1-nscreen,0);
+ ep->scvalid = 1;
+ return;
+}
+
+/*
+ * put the cursor to the <newp> position within screen buffer
+ * if <c> is non-zero then output this character
+ * cursor is set to reflect the change
+ */
+
+static void setcursor(register Emacs_t *ep,register int newp,int c)
+{
+ register int oldp = ep->cursor - ep->screen;
+ newp = ed_setcursor(ep->ed, ep->screen, oldp, newp, 0);
+ if(c)
+ {
+ putchar(ep->ed,c);
+ newp++;
+ }
+ ep->cursor = ep->screen+newp;
+ return;
+}
+
+#if SHOPT_MULTIBYTE
+static int print(register int c)
+{
+ return((c&~STRIP)==0 && isprint(c));
+}
+
+static int _isword(register int c)
+{
+ return((c&~STRIP) || isalnum(c) || c=='_');
+}
+#endif /* SHOPT_MULTIBYTE */
diff --git a/src/cmd/ksh93/edit/hexpand.c b/src/cmd/ksh93/edit/hexpand.c
new file mode 100644
index 0000000..3e2d396
--- /dev/null
+++ b/src/cmd/ksh93/edit/hexpand.c
@@ -0,0 +1,734 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * bash style history expansion
+ *
+ * Author:
+ * Karsten Fleischer
+ * Omnium Software Engineering
+ * An der Luisenburg 7
+ * D-51379 Leverkusen
+ * Germany
+ *
+ * <K.Fleischer@omnium.de>
+ */
+
+
+#include "defs.h"
+#include "edit.h"
+
+#if ! SHOPT_HISTEXPAND
+
+NoN(hexpand)
+
+#else
+
+static char *modifiers = "htrepqxs&";
+static int mod_flags[] = { 0, 0, 0, 0, HIST_PRINT, HIST_QUOTE, HIST_QUOTE|HIST_QUOTE_BR, 0, 0 };
+
+#define DONE() {flag |= HIST_ERROR; cp = 0; stakseek(0); goto done;}
+
+struct subst
+{
+ char *str[2]; /* [0] is "old", [1] is "new" string */
+};
+
+
+/*
+ * parse an /old/new/ string, delimiter expected as first char.
+ * if "old" not specified, keep sb->str[0]
+ * if "new" not specified, set sb->str[1] to empty string
+ * read up to third delimeter char, \n or \0, whichever comes first.
+ * return adress is one past the last valid char in s:
+ * - the address containing \n or \0 or
+ * - one char beyond the third delimiter
+ */
+
+static char *parse_subst(const char *s, struct subst *sb)
+{
+ char *cp,del;
+ int off,n = 0;
+
+ /* build the strings on the stack, mainly for '&' substition in "new" */
+ off = staktell();
+
+ /* init "new" with empty string */
+ if(sb->str[1])
+ free(sb->str[1]);
+ sb->str[1] = strdup("");
+
+ /* get delimiter */
+ del = *s;
+
+ cp = (char*) s + 1;
+
+ while(n < 2)
+ {
+ if(*cp == del || *cp == '\n' || *cp == '\0')
+ {
+ /* delimiter or EOL */
+ if(staktell() != off)
+ {
+ /* dupe string on stack and rewind stack */
+ stakputc('\0');
+ if(sb->str[n])
+ free(sb->str[n]);
+ sb->str[n] = strdup(stakptr(off));
+ stakseek(off);
+ }
+ n++;
+
+ /* if not delimiter, we've reached EOL. Get outta here. */
+ if(*cp != del)
+ break;
+ }
+ else if(*cp == '\\')
+ {
+ if(*(cp+1) == del) /* quote delimiter */
+ {
+ stakputc(del);
+ cp++;
+ }
+ else if(*(cp+1) == '&' && n == 1)
+ { /* quote '&' only in "new" */
+ stakputc('&');
+ cp++;
+ }
+ else
+ stakputc('\\');
+ }
+ else if(*cp == '&' && n == 1 && sb->str[0])
+ /* substitute '&' with "old" in "new" */
+ stakputs(sb->str[0]);
+ else
+ stakputc(*cp);
+ cp++;
+ }
+
+ /* rewind stack */
+ stakseek(off);
+
+ return cp;
+}
+
+/*
+ * history expansion main routine
+ */
+
+int hist_expand(const char *ln, char **xp)
+{
+ int off, /* stack offset */
+ q, /* quotation flags */
+ p, /* flag */
+ c, /* current char */
+ flag=0; /* HIST_* flags */
+ Sfoff_t n, /* history line number, counter, etc. */
+ i, /* counter */
+ w[2]; /* word range */
+ char *sp, /* stack pointer */
+ *cp, /* current char in ln */
+ *str, /* search string */
+ *evp, /* event/word designator string, for error msgs */
+ *cc=0, /* copy of current line up to cp; temp ptr */
+ hc[3], /* default histchars */
+ *qc="\'\"`"; /* quote characters */
+ Sfio_t *ref=0, /* line referenced by event designator */
+ *tmp=0, /* temporary line buffer */
+ *tmp2=0;/* temporary line buffer */
+ Histloc_t hl; /* history location */
+ static Namval_t *np = 0; /* histchars variable */
+ static struct subst sb = {0,0}; /* substition strings */
+ static Sfio_t *wm=0; /* word match from !?string? event designator */
+
+ if(!wm)
+ wm = sfopen(NULL, NULL, "swr");
+
+ hc[0] = '!';
+ hc[1] = '^';
+ hc[2] = 0;
+ if((np = nv_open("histchars",sh.var_tree,0)) && (cp = nv_getval(np)))
+ {
+ if(cp[0])
+ {
+ hc[0] = cp[0];
+ if(cp[1])
+ {
+ hc[1] = cp[1];
+ if(cp[2])
+ hc[2] = cp[2];
+ }
+ }
+ }
+
+ /* save shell stack */
+ if(off = staktell())
+ sp = stakfreeze(0);
+
+ cp = (char*)ln;
+
+ while(cp && *cp)
+ {
+ /* read until event/quick substitution/comment designator */
+ if((*cp != hc[0] && *cp != hc[1] && *cp != hc[2])
+ || (*cp == hc[1] && cp != ln))
+ {
+ if(*cp == '\\') /* skip escaped designators */
+ stakputc(*cp++);
+ else if(*cp == '\'') /* skip quoted designators */
+ {
+ do
+ stakputc(*cp);
+ while(*++cp && *cp != '\'');
+ }
+ stakputc(*cp++);
+ continue;
+ }
+
+ if(hc[2] && *cp == hc[2]) /* history comment designator, skip rest of line */
+ {
+ stakputc(*cp++);
+ stakputs(cp);
+ DONE();
+ }
+
+ n = -1;
+ str = 0;
+ flag &= HIST_EVENT; /* save event flag for returning later */
+ evp = cp;
+ ref = 0;
+
+ if(*cp == hc[1]) /* shortcut substitution */
+ {
+ flag |= HIST_QUICKSUBST;
+ goto getline;
+ }
+
+ if(*cp == hc[0] && *(cp+1) == hc[0]) /* refer to line -1 */
+ {
+ cp += 2;
+ goto getline;
+ }
+
+ switch(c = *++cp) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\0':
+ case '=':
+ case '(':
+ stakputc(hc[0]);
+ continue;
+ case '#': /* the line up to current position */
+ flag |= HIST_HASH;
+ cp++;
+ n = staktell(); /* terminate string and dup */
+ stakputc('\0');
+ cc = strdup(stakptr(0));
+ stakseek(n); /* remove null byte again */
+ ref = sfopen(ref, cc, "s"); /* open as file */
+ n = 0; /* skip history file referencing */
+ break;
+ case '-': /* back reference by number */
+ if(!isdigit(*(cp+1)))
+ goto string_event;
+ cp++;
+ case '0': /* reference by number */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ while(isdigit(*cp))
+ n = n * 10 + (*cp++) - '0';
+ if(c == '-')
+ n = -n;
+ break;
+ case '$':
+ n = -1;
+ case ':':
+ break;
+ case '?':
+ cp++;
+ flag |= HIST_QUESTION;
+ string_event:
+ default:
+ /* read until end of string or word designator/modifier */
+ str = cp;
+ while(*cp)
+ {
+ cp++;
+ if((!(flag&HIST_QUESTION) &&
+ (*cp == ':' || isspace(*cp)
+ || *cp == '^' || *cp == '$'
+ || *cp == '*' || *cp == '-'
+ || *cp == '%')
+ )
+ || ((flag&HIST_QUESTION) && (*cp == '?' || *cp == '\n')))
+ {
+ c = *cp;
+ *cp = '\0';
+ }
+ }
+ break;
+ }
+
+getline:
+ flag |= HIST_EVENT;
+ if(str) /* !string or !?string? event designator */
+ {
+
+ /* search history for string */
+ hl = hist_find(shgd->hist_ptr, str,
+ shgd->hist_ptr->histind,
+ flag&HIST_QUESTION, -1);
+ if((n = hl.hist_command) == -1)
+ n = 0; /* not found */
+ }
+ if(n)
+ {
+ if(n < 0) /* determine index for backref */
+ n = shgd->hist_ptr->histind + n;
+ /* search and use history file if found */
+ if(n > 0 && hist_seek(shgd->hist_ptr, n) != -1)
+ ref = shgd->hist_ptr->histfp;
+
+ }
+ if(!ref)
+ {
+ /* string not found or command # out of range */
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR, "%s: event not found", evp);
+ *cp = c;
+ DONE();
+ }
+
+ if(str) /* string search: restore orig. line */
+ {
+ if(flag&HIST_QUESTION)
+ *cp++ = c; /* skip second question mark */
+ else
+ *cp = c;
+ }
+
+ /* colon introduces either word designators or modifiers */
+ if(*(evp = cp) == ':')
+ cp++;
+
+ w[0] = 0; /* -1 means last word, -2 means match from !?string? */
+ w[1] = -1; /* -1 means last word, -2 means suppress last word */
+
+ if(flag & HIST_QUICKSUBST) /* shortcut substitution */
+ goto getsel;
+
+ n = 0;
+ while(n < 2)
+ {
+ switch(c = *cp++) {
+ case '^': /* first word */
+ if(n == 0)
+ {
+ w[0] = w[1] = 1;
+ goto skip;
+ }
+ else
+ goto skip2;
+ case '$': /* last word */
+ w[n] = -1;
+ goto skip;
+ case '%': /* match from !?string? event designator */
+ if(n == 0)
+ {
+ if(!str)
+ {
+ w[0] = 0;
+ w[1] = -1;
+ ref = wm;
+ }
+ else
+ {
+ w[0] = -2;
+ w[1] = sftell(ref) + hl.hist_char;
+ }
+ sfseek(wm, 0, SEEK_SET);
+ goto skip;
+ }
+ default:
+ skip2:
+ cp--;
+ n = 2;
+ break;
+ case '*': /* until last word */
+ if(n == 0)
+ w[0] = 1;
+ w[1] = -1;
+ skip:
+ flag |= HIST_WORDDSGN;
+ n = 2;
+ break;
+ case '-': /* until last word or specified index */
+ w[1] = -2;
+ flag |= HIST_WORDDSGN;
+ n = 1;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': /* specify index */
+ if((*evp == ':') || w[1] == -2)
+ {
+ w[n] = c - '0';
+ while(isdigit(c=*cp++))
+ w[n] = w[n] * 10 + c - '0';
+ flag |= HIST_WORDDSGN;
+ if(n == 0)
+ w[1] = w[0];
+ n++;
+ }
+ else
+ n = 2;
+ cp--;
+ break;
+ }
+ }
+
+ if(w[0] != -2 && w[1] > 0 && w[0] > w[1])
+ {
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR, "%s: bad word specifier", evp);
+ *cp = c;
+ DONE();
+ }
+
+ /* no valid word designator after colon, rewind */
+ if(!(flag & HIST_WORDDSGN) && (*evp == ':'))
+ cp = evp;
+
+getsel:
+ /* open temp buffer, let sfio do the (re)allocation */
+ tmp = sfopen(NULL, NULL, "swr");
+
+ /* push selected words into buffer, squash
+ whitespace into single blank or a newline */
+ n = i = q = 0;
+
+ while((c = sfgetc(ref)) > 0)
+ {
+ if(isspace(c))
+ {
+ flag |= (c == '\n' ? HIST_NEWLINE : 0);
+ continue;
+ }
+
+ if(n >= w[0] && ((w[0] != -2) ? (w[1] < 0 || n <= w[1]) : 1))
+ {
+ if(w[0] < 0)
+ sfseek(tmp, 0, SEEK_SET);
+ else
+ i = sftell(tmp);
+
+ if(i > 0)
+ sfputc(tmp, flag & HIST_NEWLINE ? '\n' : ' ');
+
+ flag &= ~HIST_NEWLINE;
+ p = 1;
+ }
+ else
+ p = 0;
+
+ do
+ {
+ cc = strchr(qc, c);
+ q ^= cc ? 1<<(int)(cc - qc) : 0;
+ if(p)
+ sfputc(tmp, c);
+ }
+ while((c = sfgetc(ref)) > 0 && (!isspace(c) || q));
+
+ if(w[0] == -2 && sftell(ref) > w[1])
+ break;
+
+ flag |= (c == '\n' ? HIST_NEWLINE : 0);
+ n++;
+ }
+ if(w[0] != -2 && w[1] >= 0 && w[1] >= n)
+ {
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR, "%s: bad word specifier", evp);
+ *cp = c;
+ DONE();
+ }
+ else if(w[1] == -2) /* skip last word */
+ sfseek(tmp, i, SEEK_SET);
+
+ /* remove trailing newline */
+ if(sftell(tmp))
+ {
+ sfseek(tmp, -1, SEEK_CUR);
+ if(sfgetc(tmp) == '\n')
+ sfungetc(tmp, '\n');
+ }
+
+ sfputc(tmp, '\0');
+
+ if(str)
+ {
+ if(wm)
+ sfclose(wm);
+ wm = tmp;
+ }
+
+ if(cc && (flag&HIST_HASH))
+ {
+ /* close !# temp file */
+ sfclose(ref);
+ flag &= ~HIST_HASH;
+ free(cc);
+ cc = 0;
+ }
+
+ evp = cp;
+
+ /* selected line/words are now in buffer, now go for the modifiers */
+ while(*cp == ':' || (flag & HIST_QUICKSUBST))
+ {
+ if(flag & HIST_QUICKSUBST)
+ {
+ flag &= ~HIST_QUICKSUBST;
+ c = 's';
+ cp--;
+ }
+ else
+ c = *++cp;
+
+ sfseek(tmp, 0, SEEK_SET);
+ tmp2 = sfopen(tmp2, NULL, "swr");
+
+ if(c == 'g') /* global substitution */
+ {
+ flag |= HIST_GLOBALSUBST;
+ c = *++cp;
+ }
+
+ if(cc = strchr(modifiers, c))
+ flag |= mod_flags[cc - modifiers];
+ else
+ {
+ errormsg(SH_DICT, ERROR_ERROR, "%c: unrecognized history modifier", c);
+ DONE();
+ }
+
+ if(c == 'h' || c == 'r') /* head or base */
+ {
+ n = -1;
+ while((c = sfgetc(tmp)) > 0)
+ { /* remember position of / or . */
+ if((c == '/' && *cp == 'h') || (c == '.' && *cp == 'r'))
+ n = sftell(tmp2);
+ sfputc(tmp2, c);
+ }
+ if(n > 0)
+ { /* rewind to last / or . */
+ sfseek(tmp2, n, SEEK_SET);
+ /* end string there */
+ sfputc(tmp2, '\0');
+ }
+ }
+ else if(c == 't' || c == 'e') /* tail or suffix */
+ {
+ n = 0;
+ while((c = sfgetc(tmp)) > 0)
+ { /* remember position of / or . */
+ if((c == '/' && *cp == 't') || (c == '.' && *cp == 'e'))
+ n = sftell(tmp);
+ }
+ /* rewind to last / or . */
+ sfseek(tmp, n, SEEK_SET);
+ /* copy from there on */
+ while((c = sfgetc(tmp)) > 0)
+ sfputc(tmp2, c);
+ }
+ else if(c == 's' || c == '&')
+ {
+ cp++;
+
+ if(c == 's')
+ {
+ /* preset old with match from !?string? */
+ if(!sb.str[0] && wm)
+ sb.str[0] = strdup(sfsetbuf(wm, (Void_t*)1, 0));
+ cp = parse_subst(cp, &sb);
+ }
+
+ if(!sb.str[0] || !sb.str[1])
+ {
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR,
+ "%s%s: no previous substitution",
+ (flag & HIST_QUICKSUBST) ? ":s" : "",
+ evp);
+ *cp = c;
+ DONE();
+ }
+
+ /* need pointer for strstr() */
+ str = sfsetbuf(tmp, (Void_t*)1, 0);
+
+ flag |= HIST_SUBSTITUTE;
+ while(flag & HIST_SUBSTITUTE)
+ {
+ /* find string */
+ if(cc = strstr(str, sb.str[0]))
+ { /* replace it */
+ c = *cc;
+ *cc = '\0';
+ sfputr(tmp2, str, -1);
+ sfputr(tmp2, sb.str[1], -1);
+ *cc = c;
+ str = cc + strlen(sb.str[0]);
+ }
+ else if(!sftell(tmp2))
+ { /* not successfull */
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR,
+ "%s%s: substitution failed",
+ (flag & HIST_QUICKSUBST) ? ":s" : "",
+ evp);
+ *cp = c;
+ DONE();
+ }
+ /* loop if g modifier specified */
+ if(!cc || !(flag & HIST_GLOBALSUBST))
+ flag &= ~HIST_SUBSTITUTE;
+ }
+ /* output rest of line */
+ sfputr(tmp2, str, -1);
+ if(*cp)
+ cp--;
+ }
+
+ if(sftell(tmp2))
+ { /* if any substitions done, swap buffers */
+ if(wm != tmp)
+ sfclose(tmp);
+ tmp = tmp2;
+ tmp2 = 0;
+ }
+ cc = 0;
+ if(*cp)
+ cp++;
+ }
+
+ /* flush temporary buffer to stack */
+ if(tmp)
+ {
+ sfseek(tmp, 0, SEEK_SET);
+
+ if(flag & HIST_QUOTE)
+ stakputc('\'');
+
+ while((c = sfgetc(tmp)) > 0)
+ {
+ if(isspace(c))
+ {
+ flag = flag & ~HIST_NEWLINE;
+
+ /* squash white space to either a
+ blank or a newline */
+ do
+ flag |= (c == '\n' ? HIST_NEWLINE : 0);
+ while((c = sfgetc(tmp)) > 0 && isspace(c));
+
+ sfungetc(tmp, c);
+
+ c = (flag & HIST_NEWLINE) ? '\n' : ' ';
+
+ if(flag & HIST_QUOTE_BR)
+ {
+ stakputc('\'');
+ stakputc(c);
+ stakputc('\'');
+ }
+ else
+ stakputc(c);
+ }
+ else if((c == '\'') && (flag & HIST_QUOTE))
+ {
+ stakputc('\'');
+ stakputc('\\');
+ stakputc(c);
+ stakputc('\'');
+ }
+ else
+ stakputc(c);
+ }
+ if(flag & HIST_QUOTE)
+ stakputc('\'');
+ }
+ }
+
+ stakputc('\0');
+
+done:
+ if(cc && (flag&HIST_HASH))
+ {
+ /* close !# temp file */
+ sfclose(ref);
+ free(cc);
+ cc = 0;
+ }
+
+ /* error? */
+ if(staktell() && !(flag & HIST_ERROR))
+ *xp = strdup(stakfreeze(1));
+
+ /* restore shell stack */
+ if(off)
+ stakset(sp,off);
+ else
+ stakseek(0);
+
+ /* drop temporary files */
+
+ if(tmp && tmp != wm)
+ sfclose(tmp);
+ if(tmp2)
+ sfclose(tmp2);
+
+ return (flag & HIST_ERROR ? HIST_ERROR : flag & HIST_FLAG_RETURN_MASK);
+}
+
+#endif
diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c
new file mode 100644
index 0000000..99fc01d
--- /dev/null
+++ b/src/cmd/ksh93/edit/history.c
@@ -0,0 +1,1222 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * History file manipulation routines
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+/*
+ * Each command in the history file starts on an even byte is null terminated.
+ * The first byte must contain the special character HIST_UNDO and the second
+ * byte is the version number. The sequence HIST_UNDO 0, following a command,
+ * nullifies the previous command. A six byte sequence starting with
+ * HIST_CMDNO is used to store the command number so that it is not necessary
+ * to read the file from beginning to end to get to the last block of
+ * commands. This format of this sequence is different in version 1
+ * then in version 0. Version 1 allows commands to use the full 8 bit
+ * character set. It can understand version 0 format files.
+ */
+
+
+#define HIST_MAX (sizeof(int)*HIST_BSIZE)
+#define HIST_BIG (0100000-1024) /* 1K less than maximum short */
+#define HIST_LINE 32 /* typical length for history line */
+#define HIST_MARKSZ 6
+#define HIST_RECENT 600
+#define HIST_UNDO 0201 /* invalidate previous command */
+#define HIST_CMDNO 0202 /* next 3 bytes give command number */
+#define HIST_BSIZE 4096 /* size of history file buffer */
+#define HIST_DFLT 512 /* default size of history list */
+
+#if SHOPT_AUDIT
+# define _HIST_AUDIT Sfio_t *auditfp; \
+ char *tty; \
+ int auditmask;
+#else
+# define _HIST_AUDIT
+#endif
+
+#define _HIST_PRIVATE \
+ void *histshell; \
+ off_t histcnt; /* offset into history file */\
+ off_t histmarker; /* offset of last command marker */ \
+ int histflush; /* set if flushed outside of hflush() */\
+ int histmask; /* power of two mask for histcnt */ \
+ char histbuff[HIST_BSIZE+1]; /* history file buffer */ \
+ int histwfail; \
+ _HIST_AUDIT \
+ off_t histcmds[2]; /* offset for recent commands, must be last */
+
+#define hist_ind(hp,c) ((int)((c)&(hp)->histmask))
+
+#include <ast.h>
+#include <sfio.h>
+#include "FEATURE/time"
+#include <error.h>
+#include <ls.h>
+#if KSHELL
+# include "defs.h"
+# include "variables.h"
+# include "path.h"
+# include "builtins.h"
+# include "io.h"
+#else
+# include <ctype.h>
+#endif /* KSHELL */
+#include "history.h"
+
+#if !KSHELL
+# define new_of(type,x) ((type*)malloc((unsigned)sizeof(type)+(x)))
+# define NIL(type) ((type)0)
+# define path_relative(s,x) (s,x)
+# ifdef __STDC__
+# define nv_getval(s) getenv(#s)
+# else
+# define nv_getval(s) getenv("s")
+# endif /* __STDC__ */
+# define e_unknown "unknown"
+# define sh_translate(x) (x)
+ char login_sh = 0;
+ char hist_fname[] = "/.history";
+#endif /* KSHELL */
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif /* O_BINARY */
+
+int _Hist = 0;
+static void hist_marker(char*,long);
+static History_t* hist_trim(History_t*, int);
+static int hist_nearend(History_t*,Sfio_t*, off_t);
+static int hist_check(int);
+static int hist_clean(int);
+#ifdef SF_BUFCONST
+ static ssize_t hist_write(Sfio_t*, const void*, size_t, Sfdisc_t*);
+ static int hist_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
+#else
+ static int hist_write(Sfio_t*, const void*, int, Sfdisc_t*);
+ static int hist_exceptf(Sfio_t*, int, Sfdisc_t*);
+#endif
+
+
+static int histinit;
+static mode_t histmode;
+static History_t *wasopen;
+static History_t *hist_ptr;
+
+#if SHOPT_ACCTFILE
+ static int acctfd;
+ static char *logname;
+# include <pwd.h>
+
+ static int acctinit(History_t *hp)
+ {
+ register char *cp, *acctfile;
+ Namval_t *np = nv_search("ACCTFILE",((Shell_t*)hp->histshell)->var_tree,0);
+
+ if(!np || !(acctfile=nv_getval(np)))
+ return(0);
+ if(!(cp = getlogin()))
+ {
+ struct passwd *userinfo = getpwuid(getuid());
+ if(userinfo)
+ cp = userinfo->pw_name;
+ else
+ cp = "unknown";
+ }
+ logname = strdup(cp);
+ if((acctfd=sh_open(acctfile,
+ O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 &&
+ (unsigned)acctfd < 10)
+ {
+ int n;
+ if((n = fcntl(acctfd, F_DUPFD, 10)) >= 0)
+ {
+ close(acctfd);
+ acctfd = n;
+ }
+ }
+ if(acctfd < 0)
+ {
+ acctfd = 0;
+ return(0);
+ }
+ if(sh_isdevfd(acctfile))
+ {
+ char newfile[16];
+ sfsprintf(newfile,sizeof(newfile),"%.8s%d\0",e_devfdNN,acctfd);
+ nv_putval(np,newfile,NV_RDONLY);
+ }
+ else
+ fcntl(acctfd,F_SETFD,FD_CLOEXEC);
+ return(1);
+ }
+#endif /* SHOPT_ACCTFILE */
+
+#if SHOPT_AUDIT
+static int sh_checkaudit(History_t *hp, const char *name, char *logbuf, size_t len)
+{
+ char *buff, *cp, *last;
+ int id1, id2, r=0, n, fd;
+ if((fd=open(name, O_RDONLY)) < 0)
+ return(0);
+ if((n = read(fd, logbuf,len-1)) < 0)
+ goto done;
+ while(logbuf[n-1]=='\n')
+ n--;
+ logbuf[n] = 0;
+ if(!(cp=strchr(logbuf,';')) && !(cp=strchr(logbuf,' ')))
+ goto done;
+ *cp = 0;
+ do
+ {
+ cp++;
+ id1 = id2 = strtol(cp,&last,10);
+ if(*last=='-')
+ id1 = strtol(last+1,&last,10);
+ if(shgd->euserid >=id1 && shgd->euserid <= id2)
+ r |= 1;
+ if(shgd->userid >=id1 && shgd->userid <= id2)
+ r |= 2;
+ cp = last;
+ }
+ while(*cp==';' || *cp==' ');
+done:
+ close(fd);
+ return(r);
+
+}
+#endif /*SHOPT_AUDIT*/
+
+static const unsigned char hist_stamp[2] = { HIST_UNDO, HIST_VERSION };
+static const Sfdisc_t hist_disc = { NULL, hist_write, NULL, hist_exceptf, NULL};
+
+static void hist_touch(void *handle)
+{
+ touch((char*)handle, (time_t)0, (time_t)0, 0);
+}
+
+/*
+ * open the history file
+ * if HISTNAME is not given and userid==0 then no history file.
+ * if login_sh and HISTFILE is longer than HIST_MAX bytes then it is
+ * cleaned up.
+ * hist_open() returns 1, if history file is open
+ */
+int sh_histinit(void *sh_context)
+{
+ Shell_t *shp = (Shell_t*)sh_context;
+ register int fd;
+ register History_t *hp;
+ register char *histname;
+ char *fname=0;
+ int histmask, maxlines, hist_start=0;
+ register char *cp;
+ register off_t hsize = 0;
+
+ if(shgd->hist_ptr=hist_ptr)
+ return(1);
+ if(!(histname = nv_getval(HISTFILE)))
+ {
+ int offset = staktell();
+ if(cp=nv_getval(HOME))
+ stakputs(cp);
+ stakputs(hist_fname);
+ stakputc(0);
+ stakseek(offset);
+ histname = stakptr(offset);
+ }
+#ifdef future
+ if(hp=wasopen)
+ {
+ /* reuse history file if same name */
+ wasopen = 0;
+ shgd->hist_ptr = hist_ptr = hp;
+ if(strcmp(histname,hp->histname)==0)
+ return(1);
+ else
+ hist_free();
+ }
+#endif
+retry:
+ cp = path_relative(shp,histname);
+ if(!histinit)
+ histmode = S_IRUSR|S_IWUSR;
+ if((fd=open(cp,O_BINARY|O_APPEND|O_RDWR|O_CREAT,histmode))>=0)
+ {
+ hsize=lseek(fd,(off_t)0,SEEK_END);
+ }
+ if((unsigned)fd <=2)
+ {
+ int n;
+ if((n=fcntl(fd,F_DUPFD,10))>=0)
+ {
+ close(fd);
+ fd=n;
+ }
+ }
+ /* make sure that file has history file format */
+ if(hsize && hist_check(fd))
+ {
+ close(fd);
+ hsize = 0;
+ if(unlink(cp)>=0)
+ goto retry;
+ fd = -1;
+ }
+ if(fd < 0)
+ {
+#if KSHELL
+ /* don't allow root a history_file in /tmp */
+ if(shgd->userid)
+#endif /* KSHELL */
+ {
+ if(!(fname = pathtmp(NIL(char*),0,0,NIL(int*))))
+ return(0);
+ fd = open(fname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR);
+ }
+ }
+ if(fd<0)
+ return(0);
+ /* set the file to close-on-exec */
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ if(cp=nv_getval(HISTSIZE))
+ maxlines = (unsigned)strtol(cp, (char**)0, 10);
+ else
+ maxlines = HIST_DFLT;
+ for(histmask=16;histmask <= maxlines; histmask <<=1 );
+ if(!(hp=new_of(History_t,(--histmask)*sizeof(off_t))))
+ {
+ close(fd);
+ return(0);
+ }
+ shgd->hist_ptr = hist_ptr = hp;
+ hp->histshell = (void*)shp;
+ hp->histsize = maxlines;
+ hp->histmask = histmask;
+ hp->histfp= sfnew(NIL(Sfio_t*),hp->histbuff,HIST_BSIZE,fd,SF_READ|SF_WRITE|SF_APPENDWR|SF_SHARE);
+ memset((char*)hp->histcmds,0,sizeof(off_t)*(hp->histmask+1));
+ hp->histind = 1;
+ hp->histcmds[1] = 2;
+ hp->histcnt = 2;
+ hp->histname = strdup(histname);
+ hp->histdisc = hist_disc;
+ if(hsize==0)
+ {
+ /* put special characters at front of file */
+ sfwrite(hp->histfp,(char*)hist_stamp,2);
+ sfsync(hp->histfp);
+ }
+ /* initialize history list */
+ else
+ {
+ int first,last;
+ off_t mark,size = (HIST_MAX/4)+maxlines*HIST_LINE;
+ hp->histind = first = hist_nearend(hp,hp->histfp,hsize-size);
+ histinit = 1;
+ hist_eof(hp); /* this sets histind to last command */
+ if((hist_start = (last=(int)hp->histind)-maxlines) <=0)
+ hist_start = 1;
+ mark = hp->histmarker;
+ while(first > hist_start)
+ {
+ size += size;
+ first = hist_nearend(hp,hp->histfp,hsize-size);
+ hp->histind = first;
+ }
+ histinit = hist_start;
+ hist_eof(hp);
+ if(!histinit)
+ {
+ sfseek(hp->histfp,hp->histcnt=hsize,SEEK_SET);
+ hp->histind = last;
+ hp->histmarker = mark;
+ }
+ histinit = 0;
+ }
+ if(fname)
+ {
+ unlink(fname);
+ free((void*)fname);
+ }
+ if(hist_clean(fd) && hist_start>1 && hsize > HIST_MAX)
+ {
+#ifdef DEBUG
+ sfprintf(sfstderr,"%d: hist_trim hsize=%d\n",getpid(),hsize);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ hp = hist_trim(hp,(int)hp->histind-maxlines);
+ }
+ sfdisc(hp->histfp,&hp->histdisc);
+#if KSHELL
+ (HISTCUR)->nvalue.lp = (&hp->histind);
+#endif /* KSHELL */
+ sh_timeradd(1000L*(HIST_RECENT-30), 1, hist_touch, (void*)hp->histname);
+#if SHOPT_ACCTFILE
+ if(sh_isstate(SH_INTERACTIVE))
+ acctinit(hp);
+#endif /* SHOPT_ACCTFILE */
+#if SHOPT_AUDIT
+ {
+ char buff[SF_BUFSIZE];
+ hp->auditfp = 0;
+ if(sh_isstate(SH_INTERACTIVE) && (hp->auditmask=sh_checkaudit(hp,SHOPT_AUDITFILE, buff, sizeof(buff))))
+ {
+ if((fd=sh_open(buff,O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 && fd < 10)
+ {
+ int n;
+ if((n = sh_fcntl(fd,F_DUPFD, 10)) >= 0)
+ {
+ sh_close(fd);
+ fd = n;
+ }
+ }
+ if(fd>=0)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ hp->tty = strdup(ttyname(2));
+ hp->auditfp = sfnew((Sfio_t*)0,NULL,-1,fd,SF_WRITE);
+ }
+ }
+ }
+#endif
+ return(1);
+}
+
+/*
+ * close the history file and free the space
+ */
+
+void hist_close(register History_t *hp)
+{
+ sfclose(hp->histfp);
+#if SHOPT_AUDIT
+ if(hp->auditfp)
+ {
+ if(hp->tty)
+ free((void*)hp->tty);
+ sfclose(hp->auditfp);
+ }
+#endif /* SHOPT_AUDIT */
+ free((char*)hp);
+ hist_ptr = 0;
+ shgd->hist_ptr = 0;
+#if SHOPT_ACCTFILE
+ if(acctfd)
+ {
+ close(acctfd);
+ acctfd = 0;
+ }
+#endif /* SHOPT_ACCTFILE */
+}
+
+/*
+ * check history file format to see if it begins with special byte
+ */
+static int hist_check(register int fd)
+{
+ unsigned char magic[2];
+ lseek(fd,(off_t)0,SEEK_SET);
+ if((read(fd,(char*)magic,2)!=2) || (magic[0]!=HIST_UNDO))
+ return(1);
+ return(0);
+}
+
+/*
+ * clean out history file OK if not modified in HIST_RECENT seconds
+ */
+static int hist_clean(int fd)
+{
+ struct stat statb;
+ return(fstat(fd,&statb)>=0 && (time((time_t*)0)-statb.st_mtime) >= HIST_RECENT);
+}
+
+/*
+ * Copy the last <n> commands to a new file and make this the history file
+ */
+
+static History_t* hist_trim(History_t *hp, int n)
+{
+ register char *cp;
+ register int incmd=1, c=0;
+ register History_t *hist_new, *hist_old = hp;
+ char *buff, *endbuff, *tmpname=0;
+ off_t oldp,newp;
+ struct stat statb;
+ unlink(hist_old->histname);
+ if(access(hist_old->histname,F_OK) >= 0)
+ {
+ /* The unlink can fail on windows 95 */
+ int fd;
+ char *last, *name=hist_old->histname;
+ close(sffileno(hist_old->histfp));
+ tmpname = (char*)malloc(strlen(name)+14);
+ if(last = strrchr(name,'/'))
+ {
+ *last = 0;
+ pathtmp(tmpname,name,"hist",NIL(int*));
+ *last = '/';
+ }
+ else
+ pathtmp(tmpname,".","hist",NIL(int*));
+ if(rename(name,tmpname) < 0)
+ {
+ free(tmpname);
+ tmpname = name;
+ }
+ fd = open(tmpname,O_RDONLY);
+ sfsetfd(hist_old->histfp,fd);
+ if(tmpname==name)
+ tmpname = 0;
+ }
+ hist_ptr = 0;
+ if(fstat(sffileno(hist_old->histfp),&statb)>=0)
+ {
+ histinit = 1;
+ histmode = statb.st_mode;
+ }
+ if(!sh_histinit(hp->histshell))
+ {
+ /* use the old history file */
+ return hist_ptr = hist_old;
+ }
+ hist_new = hist_ptr;
+ hist_ptr = hist_old;
+ if(--n < 0)
+ n = 0;
+ newp = hist_seek(hist_old,++n);
+ while(1)
+ {
+ if(!incmd)
+ {
+ c = hist_ind(hist_new,++hist_new->histind);
+ hist_new->histcmds[c] = hist_new->histcnt;
+ if(hist_new->histcnt > hist_new->histmarker+HIST_BSIZE/2)
+ {
+ char locbuff[HIST_MARKSZ];
+ hist_marker(locbuff,hist_new->histind);
+ sfwrite(hist_new->histfp,locbuff,HIST_MARKSZ);
+ hist_new->histcnt += HIST_MARKSZ;
+ hist_new->histmarker = hist_new->histcmds[hist_ind(hist_new,c)] = hist_new->histcnt;
+ }
+ oldp = newp;
+ newp = hist_seek(hist_old,++n);
+ if(newp <=oldp)
+ break;
+ }
+ if(!(buff=(char*)sfreserve(hist_old->histfp,SF_UNBOUND,0)))
+ break;
+ *(endbuff=(cp=buff)+sfvalue(hist_old->histfp)) = 0;
+ /* copy to null byte */
+ incmd = 0;
+ while(*cp++);
+ if(cp > endbuff)
+ incmd = 1;
+ else if(*cp==0)
+ cp++;
+ if(cp > endbuff)
+ cp = endbuff;
+ c = cp-buff;
+ hist_new->histcnt += c;
+ sfwrite(hist_new->histfp,buff,c);
+ }
+ hist_cancel(hist_new);
+ sfclose(hist_old->histfp);
+ if(tmpname)
+ {
+ unlink(tmpname);
+ free(tmpname);
+ }
+ free((char*)hist_old);
+ return hist_ptr = hist_new;
+}
+
+/*
+ * position history file at size and find next command number
+ */
+static int hist_nearend(History_t *hp, Sfio_t *iop, register off_t size)
+{
+ register unsigned char *cp, *endbuff;
+ register int n, incmd=1;
+ unsigned char *buff, marker[4];
+ if(size <= 2L || sfseek(iop,size,SEEK_SET)<0)
+ goto begin;
+ /* skip to marker command and return the number */
+ /* numbering commands occur after a null and begin with HIST_CMDNO */
+ while(cp=buff=(unsigned char*)sfreserve(iop,SF_UNBOUND,SF_LOCKR))
+ {
+ n = sfvalue(iop);
+ *(endbuff=cp+n) = 0;
+ while(1)
+ {
+ /* check for marker */
+ if(!incmd && *cp++==HIST_CMDNO && *cp==0)
+ {
+ n = cp+1 - buff;
+ incmd = -1;
+ break;
+ }
+ incmd = 0;
+ while(*cp++);
+ if(cp>endbuff)
+ {
+ incmd = 1;
+ break;
+ }
+ if(*cp==0 && ++cp>endbuff)
+ break;
+ }
+ size += n;
+ sfread(iop,(char*)buff,n);
+ if(incmd < 0)
+ {
+ if((n=sfread(iop,(char*)marker,4))==4)
+ {
+ n = (marker[0]<<16)|(marker[1]<<8)|marker[2];
+ if(n < size/2)
+ {
+ hp->histmarker = hp->histcnt = size+4;
+ return(n);
+ }
+ n=4;
+ }
+ if(n >0)
+ size += n;
+ incmd = 0;
+ }
+ }
+begin:
+ sfseek(iop,(off_t)2,SEEK_SET);
+ hp->histmarker = hp->histcnt = 2L;
+ return(1);
+}
+
+/*
+ * This routine reads the history file from the present position
+ * to the end-of-file and puts the information in the in-core
+ * history table
+ * Note that HIST_CMDNO is only recognized at the beginning of a command
+ * and that HIST_UNDO as the first character of a command is skipped
+ * unless it is followed by 0. If followed by 0 then it cancels
+ * the previous command.
+ */
+
+void hist_eof(register History_t *hp)
+{
+ register char *cp,*first,*endbuff;
+ register int incmd = 0;
+ register off_t count = hp->histcnt;
+ int oldind,n,skip=0;
+ off_t last = sfseek(hp->histfp,(off_t)0,SEEK_END);
+ if(last < count)
+ {
+ last = -1;
+ count = 2+HIST_MARKSZ;
+ oldind = hp->histind;
+ if((hp->histind -= hp->histsize) < 0)
+ hp->histind = 1;
+ }
+again:
+ sfseek(hp->histfp,count,SEEK_SET);
+ while(cp=(char*)sfreserve(hp->histfp,SF_UNBOUND,0))
+ {
+ n = sfvalue(hp->histfp);
+ *(endbuff = cp+n) = 0;
+ first = cp += skip;
+ while(1)
+ {
+ while(!incmd)
+ {
+ if(cp>first)
+ {
+ count += (cp-first);
+ n = hist_ind(hp, ++hp->histind);
+#ifdef future
+ if(count==hp->histcmds[n])
+ {
+ sfprintf(sfstderr,"count match n=%d\n",n);
+ if(histinit)
+ {
+ histinit = 0;
+ return;
+ }
+ }
+ else if(n>=histinit)
+#endif
+ hp->histcmds[n] = count;
+ first = cp;
+ }
+ switch(*((unsigned char*)(cp++)))
+ {
+ case HIST_CMDNO:
+ if(*cp==0)
+ {
+ hp->histmarker=count+2;
+ cp += (HIST_MARKSZ-1);
+ hp->histind--;
+ if(!histinit && (cp <= endbuff))
+ {
+ unsigned char *marker = (unsigned char*)(cp-4);
+ hp->histind = ((marker[0]<<16)|(marker[1]<<8)|marker[2] -1);
+ }
+ }
+ break;
+ case HIST_UNDO:
+ if(*cp==0)
+ {
+ cp+=1;
+ hp->histind-=2;
+ }
+ break;
+ default:
+ cp--;
+ incmd = 1;
+ }
+ if(cp > endbuff)
+ {
+ cp++;
+ goto refill;
+ }
+ }
+ first = cp;
+ while(*cp++);
+ if(cp > endbuff)
+ break;
+ incmd = 0;
+ while(*cp==0)
+ {
+ if(++cp > endbuff)
+ goto refill;
+ }
+ }
+ refill:
+ count += (--cp-first);
+ skip = (cp-endbuff);
+ if(!incmd && !skip)
+ hp->histcmds[hist_ind(hp,++hp->histind)] = count;
+ }
+ hp->histcnt = count;
+ if(incmd && last)
+ {
+ sfputc(hp->histfp,0);
+ hist_cancel(hp);
+ count = 2;
+ skip = 0;
+ oldind -= hp->histind;
+ hp->histind = hp->histind-hp->histsize + oldind +2;
+ if(hp->histind<0)
+ hp->histind = 1;
+ if(last<0)
+ {
+ char buff[HIST_MARKSZ];
+ int fd = open(hp->histname,O_RDWR);
+ if(fd>=0)
+ {
+ hist_marker(buff,hp->histind);
+ write(fd,(char*)hist_stamp,2);
+ write(fd,buff,HIST_MARKSZ);
+ close(fd);
+ }
+ }
+ last = 0;
+ goto again;
+ }
+}
+
+/*
+ * This routine will cause the previous command to be cancelled
+ */
+
+void hist_cancel(register History_t *hp)
+{
+ register int c;
+ if(!hp)
+ return;
+ sfputc(hp->histfp,HIST_UNDO);
+ sfputc(hp->histfp,0);
+ sfsync(hp->histfp);
+ hp->histcnt += 2;
+ c = hist_ind(hp,--hp->histind);
+ hp->histcmds[c] = hp->histcnt;
+}
+
+/*
+ * flush the current history command
+ */
+
+void hist_flush(register History_t *hp)
+{
+ register char *buff;
+ if(hp)
+ {
+ if(buff=(char*)sfreserve(hp->histfp,0,SF_LOCKR))
+ {
+ hp->histflush = sfvalue(hp->histfp)+1;
+ sfwrite(hp->histfp,buff,0);
+ }
+ else
+ hp->histflush=0;
+ if(sfsync(hp->histfp)<0)
+ {
+ hist_close(hp);
+ if(!sh_histinit(hp->histshell))
+ sh_offoption(SH_HISTORY);
+ }
+ hp->histflush = 0;
+ }
+}
+
+/*
+ * This is the write discipline for the history file
+ * When called from hist_flush(), trailing newlines are deleted and
+ * a zero byte. Line sequencing is added as required
+ */
+
+#ifdef SF_BUFCONST
+static ssize_t hist_write(Sfio_t *iop,const void *buff,register size_t insize,Sfdisc_t* handle)
+#else
+static int hist_write(Sfio_t *iop,const void *buff,register int insize,Sfdisc_t* handle)
+#endif
+{
+ register History_t *hp = (History_t*)handle;
+ register char *bufptr = ((char*)buff)+insize;
+ register int c,size = insize;
+ register off_t cur;
+ int saved=0;
+ char saveptr[HIST_MARKSZ];
+ if(!hp->histflush)
+ return(write(sffileno(iop),(char*)buff,size));
+ if((cur = lseek(sffileno(iop),(off_t)0,SEEK_END)) <0)
+ {
+ errormsg(SH_DICT,2,"hist_flush: EOF seek failed errno=%d",errno);
+ return(-1);
+ }
+ hp->histcnt = cur;
+ /* remove whitespace from end of commands */
+ while(--bufptr >= (char*)buff)
+ {
+ c= *bufptr;
+ if(!isspace(c))
+ {
+ if(c=='\\' && *(bufptr+1)!='\n')
+ bufptr++;
+ break;
+ }
+ }
+ /* don't count empty lines */
+ if(++bufptr <= (char*)buff)
+ return(insize);
+ *bufptr++ = '\n';
+ *bufptr++ = 0;
+ size = bufptr - (char*)buff;
+#if SHOPT_AUDIT
+ if(hp->auditfp)
+ {
+ time_t t=time((time_t*)0);
+ sfprintf(hp->auditfp,"%u;%u;%s;%*s%c",sh_isoption(SH_PRIVILEGED)?shgd->euserid:shgd->userid,t,hp->tty,size,buff,0);
+ sfsync(hp->auditfp);
+ }
+#endif /* SHOPT_AUDIT */
+#if SHOPT_ACCTFILE
+ if(acctfd)
+ {
+ int timechars, offset;
+ offset = staktell();
+ stakputs(buff);
+ stakseek(staktell() - 1);
+ timechars = sfprintf(staksp, "\t%s\t%x\n",logname,time(NIL(long *)));
+ lseek(acctfd, (off_t)0, SEEK_END);
+ write(acctfd, stakptr(offset), size - 2 + timechars);
+ stakseek(offset);
+
+ }
+#endif /* SHOPT_ACCTFILE */
+ if(size&01)
+ {
+ size++;
+ *bufptr++ = 0;
+ }
+ hp->histcnt += size;
+ c = hist_ind(hp,++hp->histind);
+ hp->histcmds[c] = hp->histcnt;
+ if(hp->histflush>HIST_MARKSZ && hp->histcnt > hp->histmarker+HIST_BSIZE/2)
+ {
+ memcpy((void*)saveptr,(void*)bufptr,HIST_MARKSZ);
+ saved=1;
+ hp->histcnt += HIST_MARKSZ;
+ hist_marker(bufptr,hp->histind);
+ hp->histmarker = hp->histcmds[hist_ind(hp,c)] = hp->histcnt;
+ size += HIST_MARKSZ;
+ }
+ errno = 0;
+ size = write(sffileno(iop),(char*)buff,size);
+ if(saved)
+ memcpy((void*)bufptr,(void*)saveptr,HIST_MARKSZ);
+ if(size>=0)
+ {
+ hp->histwfail = 0;
+ return(insize);
+ }
+ return(-1);
+}
+
+/*
+ * Put history sequence number <n> into buffer <buff>
+ * The buffer must be large enough to hold HIST_MARKSZ chars
+ */
+
+static void hist_marker(register char *buff,register long cmdno)
+{
+ *buff++ = HIST_CMDNO;
+ *buff++ = 0;
+ *buff++ = (cmdno>>16);
+ *buff++ = (cmdno>>8);
+ *buff++ = cmdno;
+ *buff++ = 0;
+}
+
+/*
+ * return byte offset in history file for command <n>
+ */
+off_t hist_tell(register History_t *hp, int n)
+{
+ return(hp->histcmds[hist_ind(hp,n)]);
+}
+
+/*
+ * seek to the position of command <n>
+ */
+off_t hist_seek(register History_t *hp, int n)
+{
+ return(sfseek(hp->histfp,hp->histcmds[hist_ind(hp,n)],SEEK_SET));
+}
+
+/*
+ * write the command starting at offset <offset> onto file <outfile>.
+ * if character <last> appears before newline it is deleted
+ * each new-line character is replaced with string <nl>.
+ */
+
+void hist_list(register History_t *hp,Sfio_t *outfile, off_t offset,int last, char *nl)
+{
+ register int oldc=0;
+ register int c;
+ if(offset<0 || !hp)
+ {
+ sfputr(outfile,sh_translate(e_unknown),'\n');
+ return;
+ }
+ sfseek(hp->histfp,offset,SEEK_SET);
+ while((c = sfgetc(hp->histfp)) != EOF)
+ {
+ if(c && oldc=='\n')
+ sfputr(outfile,nl,-1);
+ else if(last && (c==0 || (c=='\n' && oldc==last)))
+ return;
+ else if(oldc)
+ sfputc(outfile,oldc);
+ oldc = c;
+ if(c==0)
+ return;
+ }
+ return;
+}
+
+/*
+ * find index for last line with given string
+ * If flag==0 then line must begin with string
+ * direction < 1 for backwards search
+*/
+
+Histloc_t hist_find(register History_t*hp,char *string,register int index1,int flag,int direction)
+{
+ register int index2;
+ off_t offset;
+ int *coffset=0;
+ Histloc_t location;
+ location.hist_command = -1;
+ location.hist_char = 0;
+ location.hist_line = 0;
+ if(!hp)
+ return(location);
+ /* leading ^ means beginning of line unless escaped */
+ if(flag)
+ {
+ index2 = *string;
+ if(index2=='\\')
+ string++;
+ else if(index2=='^')
+ {
+ flag=0;
+ string++;
+ }
+ }
+ if(flag)
+ coffset = &location.hist_char;
+ index2 = (int)hp->histind;
+ if(direction<0)
+ {
+ index2 -= hp->histsize;
+ if(index2<1)
+ index2 = 1;
+ if(index1 <= index2)
+ return(location);
+ }
+ else if(index1 >= index2)
+ return(location);
+ while(index1!=index2)
+ {
+ direction>0?++index1:--index1;
+ offset = hist_tell(hp,index1);
+ if((location.hist_line=hist_match(hp,offset,string,coffset))>=0)
+ {
+ location.hist_command = index1;
+ return(location);
+ }
+#if KSHELL
+ /* allow a search to be aborted */
+ if(((Shell_t*)hp->histshell)->trapnote&SH_SIGSET)
+ break;
+#endif /* KSHELL */
+ }
+ return(location);
+}
+
+/*
+ * search for <string> in history file starting at location <offset>
+ * If coffset==0 then line must begin with string
+ * returns the line number of the match if successful, otherwise -1
+ */
+
+int hist_match(register History_t *hp,off_t offset,char *string,int *coffset)
+{
+ register unsigned char *first, *cp;
+ register int m,n,c=1,line=0;
+#if SHOPT_MULTIBYTE
+ mbinit();
+#endif /* SHOPT_MULTIBYTE */
+ sfseek(hp->histfp,offset,SEEK_SET);
+ if(!(cp = first = (unsigned char*)sfgetr(hp->histfp,0,0)))
+ return(-1);
+ m = sfvalue(hp->histfp);
+ n = strlen(string);
+ while(m > n)
+ {
+ if(*cp==*string && memcmp(cp,string,n)==0)
+ {
+ if(coffset)
+ *coffset = (cp-first);
+ return(line);
+ }
+ if(!coffset)
+ break;
+ if(*cp=='\n')
+ line++;
+#if SHOPT_MULTIBYTE
+ if((c=mbsize(cp)) < 0)
+ c = 1;
+#endif /* SHOPT_MULTIBYTE */
+ cp += c;
+ m -= c;
+ }
+ return(-1);
+}
+
+
+#if SHOPT_ESH || SHOPT_VSH
+/*
+ * copy command <command> from history file to s1
+ * at most <size> characters copied
+ * if s1==0 the number of lines for the command is returned
+ * line=linenumber for emacs copy and only this line of command will be copied
+ * line < 0 for full command copy
+ * -1 returned if there is no history file
+ */
+
+int hist_copy(char *s1,int size,int command,int line)
+{
+ register int c;
+ register History_t *hp = shgd->hist_ptr;
+ register int count = 0;
+ register char *s1max = s1+size;
+ if(!hp)
+ return(-1);
+ hist_seek(hp,command);
+ while ((c = sfgetc(hp->histfp)) && c!=EOF)
+ {
+ if(c=='\n')
+ {
+ if(count++ ==line)
+ break;
+ else if(line >= 0)
+ continue;
+ }
+ if(s1 && (line<0 || line==count))
+ {
+ if(s1 >= s1max)
+ {
+ *--s1 = 0;
+ break;
+ }
+ *s1++ = c;
+ }
+
+ }
+ sfseek(hp->histfp,(off_t)0,SEEK_END);
+ if(s1==0)
+ return(count);
+ if(count && (c= *(s1-1)) == '\n')
+ s1--;
+ *s1 = '\0';
+ return(count);
+}
+
+/*
+ * return word number <word> from command number <command>
+ */
+
+char *hist_word(char *string,int size,int word)
+{
+ register int c;
+ register char *s1 = string;
+ register unsigned char *cp = (unsigned char*)s1;
+ register int flag = 0;
+ History_t *hp = hist_ptr;
+ if(!hp)
+ return(NIL(char*));
+ hist_copy(string,size,(int)hp->histind-1,-1);
+ for(;c = *cp;cp++)
+ {
+ c = isspace(c);
+ if(c && flag)
+ {
+ *cp = 0;
+ if(--word==0)
+ break;
+ flag = 0;
+ }
+ else if(c==0 && flag==0)
+ {
+ s1 = (char*)cp;
+ flag++;
+ }
+ }
+ *cp = 0;
+ if(s1 != string)
+ strcpy(string,s1);
+ return(string);
+}
+
+#endif /* SHOPT_ESH */
+
+#if SHOPT_ESH
+/*
+ * given the current command and line number,
+ * and number of lines back or foward,
+ * compute the new command and line number.
+ */
+
+Histloc_t hist_locate(History_t *hp,register int command,register int line,int lines)
+{
+ Histloc_t next;
+ line += lines;
+ if(!hp)
+ {
+ command = -1;
+ goto done;
+ }
+ if(lines > 0)
+ {
+ register int count;
+ while(command <= hp->histind)
+ {
+ count = hist_copy(NIL(char*),0, command,-1);
+ if(count > line)
+ goto done;
+ line -= count;
+ command++;
+ }
+ }
+ else
+ {
+ register int least = (int)hp->histind-hp->histsize;
+ while(1)
+ {
+ if(line >=0)
+ goto done;
+ if(--command < least)
+ break;
+ line += hist_copy(NIL(char*),0, command,-1);
+ }
+ command = -1;
+ }
+done:
+ next.hist_line = line;
+ next.hist_command = command;
+ return(next);
+}
+#endif /* SHOPT_ESH */
+
+
+/*
+ * Handle history file exceptions
+ */
+#ifdef SF_BUFCONST
+static int hist_exceptf(Sfio_t* fp, int type, void *data, Sfdisc_t *handle)
+#else
+static int hist_exceptf(Sfio_t* fp, int type, Sfdisc_t *handle)
+#endif
+{
+ register int newfd,oldfd;
+ History_t *hp = (History_t*)handle;
+ if(type==SF_WRITE)
+ {
+ if(errno==ENOSPC || hp->histwfail++ >= 10)
+ return(0);
+ /* write failure could be NFS problem, try to re-open */
+ close(oldfd=sffileno(fp));
+ if((newfd=open(hp->histname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) >= 0)
+ {
+ if(fcntl(newfd, F_DUPFD, oldfd) !=oldfd)
+ return(-1);
+ fcntl(oldfd,F_SETFD,FD_CLOEXEC);
+ close(newfd);
+ if(lseek(oldfd,(off_t)0,SEEK_END) < hp->histcnt)
+ {
+ register int index = hp->histind;
+ lseek(oldfd,(off_t)2,SEEK_SET);
+ hp->histcnt = 2;
+ hp->histind = 1;
+ hp->histcmds[1] = 2;
+ hist_eof(hp);
+ hp->histmarker = hp->histcnt;
+ hp->histind = index;
+ }
+ return(1);
+ }
+ errormsg(SH_DICT,2,"History file write error-%d %s: file unrecoverable",errno,hp->histname);
+ return(-1);
+ }
+ return(0);
+}
diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c
new file mode 100644
index 0000000..376e349
--- /dev/null
+++ b/src/cmd/ksh93/edit/vi.c
@@ -0,0 +1,2753 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/* Adapted for ksh by David Korn */
+/*+ VI.C P.D. Sullivan
+ *
+ * One line editor for the shell based on the vi editor.
+ *
+ * Questions to:
+ * P.D. Sullivan
+ * cbosgd!pds
+-*/
+
+
+#if KSHELL
+# include "defs.h"
+#else
+# include <ast.h>
+# include "FEATURE/options"
+# include <ctype.h>
+#endif /* KSHELL */
+#include "io.h"
+
+#include "history.h"
+#include "edit.h"
+#include "terminal.h"
+#include "FEATURE/time"
+
+#if SHOPT_OLDTERMIO
+# undef ECHOCTL
+# define echoctl (vp->ed->e_echoctl)
+#else
+# ifdef ECHOCTL
+# define echoctl ECHOCTL
+# else
+# define echoctl 0
+# endif /* ECHOCTL */
+#endif /*SHOPT_OLDTERMIO */
+
+#ifndef FIORDCHK
+# define NTICKS 5 /* number of ticks for typeahead */
+#endif /* FIORDCHK */
+
+#define MAXCHAR MAXLINE-2 /* max char per line */
+
+#if SHOPT_MULTIBYTE
+# include "lexstates.h"
+# define gencpy(a,b) ed_gencpy(a,b)
+# define genncpy(a,b,n) ed_genncpy(a,b,n)
+# define genlen(str) ed_genlen(str)
+# define digit(c) ((c&~STRIP)==0 && isdigit(c))
+# define is_print(c) ((c&~STRIP) || isprint(c))
+# if !_lib_iswprint && !defined(iswprint)
+# define iswprint(c) ((c&~0177) || isprint(c))
+# endif
+ static int _isalph(int);
+ static int _ismetach(int);
+ static int _isblank(int);
+# undef isblank
+# define isblank(v) _isblank(virtual[v])
+# define isalph(v) _isalph(virtual[v])
+# define ismetach(v) _ismetach(virtual[v])
+#else
+ static genchar _c;
+# define gencpy(a,b) strcpy((char*)(a),(char*)(b))
+# define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
+# define genlen(str) strlen(str)
+# define isalph(v) ((_c=virtual[v])=='_'||isalnum(_c))
+# undef isblank
+# define isblank(v) isspace(virtual[v])
+# define ismetach(v) ismeta(virtual[v])
+# define digit(c) isdigit(c)
+# define is_print(c) isprint(c)
+#endif /* SHOPT_MULTIBYTE */
+
+#if ( 'a' == 97) /* ASCII? */
+# define fold(c) ((c)&~040) /* lower and uppercase equivalent */
+#else
+# define fold(c) ((c)|0100) /* lower and uppercase equivalent */
+#endif
+
+#ifndef iswascii
+#define iswascii(c) (!((c)&(~0177)))
+#endif
+
+typedef struct _vi_
+{
+ int direction;
+ int lastmacro;
+ char addnl; /* boolean - add newline flag */
+ char last_find; /* last find command */
+ char last_cmd; /* last command */
+ char repeat_set;
+ char nonewline;
+ int findchar; /* last find char */
+ genchar *lastline;
+ int first_wind; /* first column of window */
+ int last_wind; /* last column in window */
+ int lastmotion; /* last motion */
+ int long_char; /* line bigger than window */
+ int long_line; /* line bigger than window */
+ int ocur_phys; /* old current physical position */
+ int ocur_virt; /* old last virtual position */
+ int ofirst_wind; /* old window first col */
+ int o_v_char; /* prev virtual[ocur_virt] */
+ int repeat; /* repeat count for motion cmds */
+ int lastrepeat; /* last repeat count for motion cmds */
+ int u_column; /* undo current column */
+ int U_saved; /* original virtual saved */
+ genchar *U_space; /* used for U command */
+ genchar *u_space; /* used for u command */
+#ifdef FIORDCHK
+ clock_t typeahead; /* typeahead occurred */
+#else
+ int typeahead; /* typeahead occurred */
+#endif /* FIORDCHK */
+#if SHOPT_MULTIBYTE
+ int bigvi;
+#endif
+ Edit_t *ed; /* pointer to edit data */
+} Vi_t;
+
+#define editb (*vp->ed)
+
+#undef putchar
+#define putchar(c) ed_putchar(vp->ed,c)
+
+#define crallowed editb.e_crlf
+#define cur_virt editb.e_cur /* current virtual column */
+#define cur_phys editb.e_pcur /* current phys column cursor is at */
+#define curhline editb.e_hline /* current history line */
+#define first_virt editb.e_fcol /* first allowable column */
+#define globals editb.e_globals /* local global variables */
+#define histmin editb.e_hismin
+#define histmax editb.e_hismax
+#define last_phys editb.e_peol /* last column in physical */
+#define last_virt editb.e_eol /* last column */
+#define lsearch editb.e_search /* last search string */
+#define lookahead editb.e_lookahead /* characters in buffer */
+#define previous editb.e_lbuf /* lookahead buffer */
+#define max_col editb.e_llimit /* maximum column */
+#define Prompt editb.e_prompt /* pointer to prompt */
+#define plen editb.e_plen /* length of prompt */
+#define physical editb.e_physbuf /* physical image */
+#define usreof editb.e_eof /* user defined eof char */
+#define usrerase editb.e_erase /* user defined erase char */
+#define usrlnext editb.e_lnext /* user defined next literal */
+#define usrkill editb.e_kill /* user defined kill char */
+#define virtual editb.e_inbuf /* pointer to virtual image buffer */
+#define window editb.e_window /* window buffer */
+#define w_size editb.e_wsize /* window size */
+#define inmacro editb.e_inmacro /* true when in macro */
+#define yankbuf editb.e_killbuf /* yank/delete buffer */
+
+
+#define ABORT -2 /* user abort */
+#define APPEND -10 /* append chars */
+#define BAD -1 /* failure flag */
+#define BIGVI -15 /* user wants real vi */
+#define CONTROL -20 /* control mode */
+#define ENTER -25 /* enter flag */
+#define GOOD 0 /* success flag */
+#define INPUT -30 /* input mode */
+#define INSERT -35 /* insert mode */
+#define REPLACE -40 /* replace chars */
+#define SEARCH -45 /* search flag */
+#define TRANSLATE -50 /* translate virt to phys only */
+
+#define INVALID (-1) /* invalid column */
+
+static const char paren_chars[] = "([{)]}"; /* for % command */
+
+static void cursor(Vi_t*, int);
+static void del_line(Vi_t*,int);
+static int getcount(Vi_t*,int);
+static void getline(Vi_t*,int);
+static int getrchar(Vi_t*);
+static int mvcursor(Vi_t*,int);
+static void pr_string(Vi_t*,const char*);
+static void putstring(Vi_t*,int, int);
+static void refresh(Vi_t*,int);
+static void replace(Vi_t*,int, int);
+static void restore_v(Vi_t*);
+static void save_last(Vi_t*);
+static void save_v(Vi_t*);
+static int search(Vi_t*,int);
+static void sync_cursor(Vi_t*);
+static int textmod(Vi_t*,int,int);
+
+/*+ VI_READ( fd, shbuf, nchar )
+ *
+ * This routine implements a one line version of vi and is
+ * called by _filbuf.c
+ *
+-*/
+
+/*
+ * if reedit is non-zero, initialize edit buffer with reedit chars
+ */
+int ed_viread(void *context, int fd, register char *shbuf, int nchar, int reedit)
+{
+ Edit_t *ed = (Edit_t*)context;
+ register int i; /* general variable */
+ register int term_char=0; /* read() termination character */
+ register Vi_t *vp = ed->e_vi;
+ char prompt[PRSIZE+2]; /* prompt */
+ genchar Physical[2*MAXLINE]; /* physical image */
+ genchar Ubuf[MAXLINE]; /* used for U command */
+ genchar ubuf[MAXLINE]; /* used for u command */
+ genchar Window[MAXLINE]; /* window image */
+ int Globals[9]; /* local global variables */
+ int esc_or_hang=0; /* <ESC> or hangup */
+ char cntl_char=0; /* TRUE if control character present */
+#if SHOPT_RAWONLY
+# define viraw 1
+#else
+ int viraw = (sh_isoption(SH_VIRAW) || ed->sh->st.trap[SH_KEYTRAP]);
+# ifndef FIORDCHK
+ clock_t oldtime, newtime;
+ struct tms dummy;
+# endif /* FIORDCHK */
+#endif /* SHOPT_RAWONLY */
+ if(!vp)
+ {
+ ed->e_vi = vp = newof(0,Vi_t,1,0);
+ vp->lastline = (genchar*)malloc(MAXLINE*CHARSIZE);
+ vp->direction = -1;
+ vp->ed = ed;
+ }
+
+ /*** setup prompt ***/
+
+ Prompt = prompt;
+ ed_setup(vp->ed,fd, reedit);
+ shbuf[reedit] = 0;
+
+#if !SHOPT_RAWONLY
+ if(!viraw)
+ {
+ /*** Change the eol characters to '\r' and eof ***/
+ /* in addition to '\n' and make eof an ESC */
+ if(tty_alt(ERRIO) < 0)
+ return(reexit?reedit:ed_read(context, fd, shbuf, nchar,0));
+
+#ifdef FIORDCHK
+ ioctl(fd,FIORDCHK,&vp->typeahead);
+#else
+ /* time the current line to determine typeahead */
+ oldtime = times(&dummy);
+#endif /* FIORDCHK */
+#if KSHELL
+ /* abort of interrupt has occurred */
+ if(ed->sh->trapnote&SH_SIGSET)
+ i = -1;
+ else
+#endif /* KSHELL */
+ /*** Read the line ***/
+ i = ed_read(context, fd, shbuf, nchar, 0);
+#ifndef FIORDCHK
+ newtime = times(&dummy);
+ vp->typeahead = ((newtime-oldtime) < NTICKS);
+#endif /* FIORDCHK */
+ if(echoctl)
+ {
+ if( i <= 0 )
+ {
+ /*** read error or eof typed ***/
+ tty_cooked(ERRIO);
+ return(i);
+ }
+ term_char = shbuf[--i];
+ if( term_char == '\r' )
+ term_char = '\n';
+ if( term_char=='\n' || term_char==ESC )
+ shbuf[i--] = '\0';
+ else
+ shbuf[i+1] = '\0';
+ }
+ else
+ {
+ register int c = shbuf[0];
+
+ /*** Save and remove the last character if its an eol, ***/
+ /* changing '\r' to '\n' */
+
+ if( i == 0 )
+ {
+ /*** ESC was typed as first char of line ***/
+ esc_or_hang = 1;
+ term_char = ESC;
+ shbuf[i--] = '\0'; /* null terminate line */
+ }
+ else if( i<0 || c==usreof )
+ {
+ /*** read error or eof typed ***/
+ tty_cooked(ERRIO);
+ if( c == usreof )
+ i = 0;
+ return(i);
+ }
+ else
+ {
+ term_char = shbuf[--i];
+ if( term_char == '\r' )
+ term_char = '\n';
+#if !defined(VEOL2) && !defined(ECHOCTL)
+ if(term_char=='\n')
+ {
+ tty_cooked(ERRIO);
+ return(i+1);
+ }
+#endif
+ if( term_char=='\n' || term_char==usreof )
+ {
+ /*** remove terminator & null terminate ***/
+ shbuf[i--] = '\0';
+ }
+ else
+ {
+ /** terminator was ESC, which is not xmitted **/
+ term_char = ESC;
+ shbuf[i+1] = '\0';
+ }
+ }
+ }
+ }
+ else
+#endif /* SHOPT_RAWONLY */
+ {
+ /*** Set raw mode ***/
+
+#if !SHOPT_RAWONLY
+ if( editb.e_ttyspeed == 0 )
+ {
+ /*** never did TCGETA, so do it ***/
+ /* avoids problem if user does 'sh -o viraw' */
+ tty_alt(ERRIO);
+ }
+#endif /* SHOPT_RAWONLY */
+ if(tty_raw(ERRIO,0) < 0 )
+ return(reedit?reedit:ed_read(context, fd, shbuf, nchar,0));
+ i = last_virt-1;
+ }
+
+ /*** Initialize some things ***/
+
+ virtual = (genchar*)shbuf;
+#if SHOPT_MULTIBYTE
+ virtual = (genchar*)roundof((char*)virtual-(char*)0,sizeof(genchar));
+ shbuf[i+1] = 0;
+ i = ed_internal(shbuf,virtual)-1;
+#endif /* SHOPT_MULTIBYTE */
+ globals = Globals;
+ cur_phys = i + 1;
+ cur_virt = i;
+ first_virt = 0;
+ vp->first_wind = 0;
+ last_virt = i;
+ last_phys = i;
+ vp->last_wind = i;
+ vp->long_line = ' ';
+ vp->long_char = ' ';
+ vp->o_v_char = '\0';
+ vp->ocur_phys = 0;
+ vp->ocur_virt = MAXCHAR;
+ vp->ofirst_wind = 0;
+ physical = Physical;
+ vp->u_column = INVALID - 1;
+ vp->U_space = Ubuf;
+ vp->u_space = ubuf;
+ window = Window;
+ window[0] = '\0';
+
+ if(!yankbuf)
+ yankbuf = (genchar*)malloc(MAXLINE*CHARSIZE);
+ if( vp->last_cmd == '\0' )
+ {
+ /*** first time for this shell ***/
+
+ vp->last_cmd = 'i';
+ vp->findchar = INVALID;
+ vp->lastmotion = '\0';
+ vp->lastrepeat = 1;
+ vp->repeat = 1;
+ *yankbuf = 0;
+ }
+
+ /*** fiddle around with prompt length ***/
+ if( nchar+plen > MAXCHAR )
+ nchar = MAXCHAR - plen;
+ max_col = nchar - 2;
+
+ if( !viraw )
+ {
+ int kill_erase = 0;
+ for(i=(echoctl?last_virt:0); i<last_virt; ++i )
+ {
+ /*** change \r to \n, check for control characters, ***/
+ /* delete appropriate ^Vs, */
+ /* and estimate last physical column */
+
+ if( virtual[i] == '\r' )
+ virtual[i] = '\n';
+ if(!echoctl)
+ {
+ register int c = virtual[i];
+ if( c<=usrerase)
+ {
+ /*** user typed escaped erase or kill char ***/
+ cntl_char = 1;
+ if(is_print(c))
+ kill_erase++;
+ }
+ else if( !is_print(c) )
+ {
+ cntl_char = 1;
+
+ if( c == usrlnext )
+ {
+ if( i == last_virt )
+ {
+ /*** eol/eof was escaped ***/
+ /* so replace ^V with it */
+ virtual[i] = term_char;
+ break;
+ }
+
+ /*** delete ^V ***/
+ gencpy((&virtual[i]), (&virtual[i+1]));
+ --cur_virt;
+ --last_virt;
+ }
+ }
+ }
+ }
+
+ /*** copy virtual image to window ***/
+ if(last_virt > 0)
+ last_phys = ed_virt_to_phys(vp->ed,virtual,physical,last_virt,0,0);
+ if( last_phys >= w_size )
+ {
+ /*** line longer than window ***/
+ vp->last_wind = w_size - 1;
+ }
+ else
+ vp->last_wind = last_phys;
+ genncpy(window, virtual, vp->last_wind+1);
+
+ if( term_char!=ESC && (last_virt==INVALID
+ || virtual[last_virt]!=term_char) )
+ {
+ /*** Line not terminated with ESC or escaped (^V) ***/
+ /* eol, so return after doing a total update */
+ /* if( (speed is greater or equal to 1200 */
+ /* and something was typed) and */
+ /* (control character present */
+ /* or typeahead occurred) ) */
+
+ tty_cooked(ERRIO);
+ if( editb.e_ttyspeed==FAST && last_virt!=INVALID
+ && (vp->typeahead || cntl_char) )
+ {
+ refresh(vp,TRANSLATE);
+ pr_string(vp,Prompt);
+ putstring(vp,0, last_phys+1);
+ if(echoctl)
+ ed_crlf(vp->ed);
+ else
+ while(kill_erase-- > 0)
+ putchar(' ');
+ }
+
+ if( term_char=='\n' )
+ {
+ if(!echoctl)
+ ed_crlf(vp->ed);
+ virtual[++last_virt] = '\n';
+ }
+ vp->last_cmd = 'i';
+ save_last(vp);
+#if SHOPT_MULTIBYTE
+ virtual[last_virt+1] = 0;
+ last_virt = ed_external(virtual,shbuf);
+ return(last_virt);
+#else
+ return(++last_virt);
+#endif /* SHOPT_MULTIBYTE */
+ }
+
+ /*** Line terminated with escape, or escaped eol/eof, ***/
+ /* so set raw mode */
+
+ if( tty_raw(ERRIO,0) < 0 )
+ {
+ tty_cooked(ERRIO);
+ /*
+ * The following prevents drivers that return 0 on
+ * causing an infinite loop
+ */
+ if(esc_or_hang)
+ return(-1);
+ virtual[++last_virt] = '\n';
+#if SHOPT_MULTIBYTE
+ virtual[last_virt+1] = 0;
+ last_virt = ed_external(virtual,shbuf);
+ return(last_virt);
+#else
+ return(++last_virt);
+#endif /* SHOPT_MULTIBYTE */
+ }
+
+ if(echoctl) /*** for cntl-echo erase the ^[ ***/
+ pr_string(vp,"\b\b\b\b \b\b");
+
+
+ if(crallowed)
+ {
+ /*** start over since there may be ***/
+ /*** a control char, or cursor might not ***/
+ /*** be at left margin (this lets us know ***/
+ /*** where we are ***/
+ cur_phys = 0;
+ window[0] = '\0';
+ pr_string(vp,Prompt);
+ if( term_char==ESC && (last_virt<0 || virtual[last_virt]!=ESC))
+ refresh(vp,CONTROL);
+ else
+ refresh(vp,INPUT);
+ }
+ else
+ {
+ /*** just update everything internally ***/
+ refresh(vp,TRANSLATE);
+ }
+ }
+
+ /*** Handle usrintr, usrquit, or EOF ***/
+
+ i = sigsetjmp(editb.e_env,0);
+ if( i != 0 )
+ {
+ if(vp->ed->e_multiline)
+ {
+ cur_virt = last_virt;
+ sync_cursor(vp);
+ }
+ virtual[0] = '\0';
+ tty_cooked(ERRIO);
+
+ switch(i)
+ {
+ case UEOF:
+ /*** EOF ***/
+ return(0);
+
+ case UINTR:
+ /** interrupt **/
+ return(-1);
+ }
+ return(-1);
+ }
+
+ /*** Get a line from the terminal ***/
+
+ vp->U_saved = 0;
+ if(reedit)
+ {
+ cur_phys = vp->first_wind;
+ vp->ofirst_wind = INVALID;
+ refresh(vp,INPUT);
+ }
+ if(viraw)
+ getline(vp,APPEND);
+ else if(last_virt>=0 && virtual[last_virt]==term_char)
+ getline(vp,APPEND);
+ else
+ getline(vp,ESC);
+ if(vp->ed->e_multiline)
+ cursor(vp, last_phys);
+ /*** add a new line if user typed unescaped \n ***/
+ /* to cause the shell to process the line */
+ tty_cooked(ERRIO);
+ if(ed->e_nlist)
+ {
+ ed->e_nlist = 0;
+ stakset(ed->e_stkptr,ed->e_stkoff);
+ }
+ if( vp->addnl )
+ {
+ virtual[++last_virt] = '\n';
+ ed_crlf(vp->ed);
+ }
+ if( ++last_virt >= 0 )
+ {
+#if SHOPT_MULTIBYTE
+ if(vp->bigvi)
+ {
+ vp->bigvi = 0;
+ shbuf[last_virt-1] = '\n';
+ }
+ else
+ {
+ virtual[last_virt] = 0;
+ last_virt = ed_external(virtual,shbuf);
+ }
+#endif /* SHOPT_MULTIBYTE */
+#if SHOPT_EDPREDICT
+ if(vp->ed->nhlist)
+ ed_histlist(vp->ed,0);
+#endif /* SHOPT_EDPREDICT */
+ return(last_virt);
+ }
+ else
+ return(-1);
+}
+
+
+/*{ APPEND( char, mode )
+ *
+ * This routine will append char after cur_virt in the virtual image.
+ * mode = APPEND, shift chars right before appending
+ * REPLACE, replace char if possible
+ *
+}*/
+
+static void append(Vi_t *vp,int c, int mode)
+{
+ register int i,j;
+
+ if( last_virt<max_col && last_phys<max_col )
+ {
+ if( mode==APPEND || (cur_virt==last_virt && last_virt>=0))
+ {
+ j = (cur_virt>=0?cur_virt:0);
+ for(i = ++last_virt; i > j; --i)
+ virtual[i] = virtual[i-1];
+ }
+ virtual[++cur_virt] = c;
+ }
+ else
+ ed_ringbell();
+ return;
+}
+
+/*{ BACKWORD( nwords, cmd )
+ *
+ * This routine will position cur_virt at the nth previous word.
+ *
+}*/
+
+static void backword(Vi_t *vp,int nwords, register int cmd)
+{
+ register int tcur_virt = cur_virt;
+ while( nwords-- && tcur_virt > first_virt )
+ {
+ if( !isblank(tcur_virt) && isblank(tcur_virt-1)
+ && tcur_virt>first_virt )
+ --tcur_virt;
+ else if(cmd != 'B')
+ {
+ register int last = isalph(tcur_virt-1);
+ register int cur = isalph(tcur_virt);
+ if((!cur && last) || (cur && !last))
+ --tcur_virt;
+ }
+ while( isblank(tcur_virt) && tcur_virt>=first_virt )
+ --tcur_virt;
+ if( cmd == 'B' )
+ {
+ while( !isblank(tcur_virt) && tcur_virt>=first_virt )
+ --tcur_virt;
+ }
+ else
+ {
+ if(isalph(tcur_virt))
+ while( isalph(tcur_virt) && tcur_virt>=first_virt )
+ --tcur_virt;
+ else
+ while( !isalph(tcur_virt) && !isblank(tcur_virt)
+ && tcur_virt>=first_virt )
+ --tcur_virt;
+ }
+ cur_virt = ++tcur_virt;
+ }
+ return;
+}
+
+/*{ CNTLMODE()
+ *
+ * This routine implements the vi command subset.
+ * The cursor will always be positioned at the char of interest.
+ *
+}*/
+
+static int cntlmode(Vi_t *vp)
+{
+ register int c;
+ register int i;
+ genchar tmp_u_space[MAXLINE]; /* temporary u_space */
+ genchar *real_u_space; /* points to real u_space */
+ int tmp_u_column = INVALID; /* temporary u_column */
+ int was_inmacro;
+
+ if(!vp->U_saved)
+ {
+ /*** save virtual image if never done before ***/
+ virtual[last_virt+1] = '\0';
+ gencpy(vp->U_space, virtual);
+ vp->U_saved = 1;
+ }
+
+ save_last(vp);
+
+ real_u_space = vp->u_space;
+ curhline = histmax;
+ first_virt = 0;
+ vp->repeat = 1;
+ if( cur_virt > INVALID )
+ {
+ /*** make sure cursor is at the last char ***/
+ sync_cursor(vp);
+ }
+
+ /*** Read control char until something happens to cause a ***/
+ /* return to APPEND/REPLACE mode */
+
+ while( c=ed_getchar(vp->ed,-1) )
+ {
+ vp->repeat_set = 0;
+ was_inmacro = inmacro;
+ if( c == '0' )
+ {
+ /*** move to leftmost column ***/
+ cur_virt = 0;
+ sync_cursor(vp);
+ continue;
+ }
+
+ if( digit(c) )
+ {
+ c = getcount(vp,c);
+ if( c == '.' )
+ vp->lastrepeat = vp->repeat;
+ }
+
+ /*** see if it's a move cursor command ***/
+
+ if(mvcursor(vp,c))
+ {
+ sync_cursor(vp);
+ vp->repeat = 1;
+ continue;
+ }
+
+ /*** see if it's a repeat of the last command ***/
+
+ if( c == '.' )
+ {
+ c = vp->last_cmd;
+ vp->repeat = vp->lastrepeat;
+ i = textmod(vp,c, c);
+ }
+ else
+ {
+ i = textmod(vp,c, 0);
+ }
+
+ /*** see if it's a text modification command ***/
+
+ switch(i)
+ {
+ case BAD:
+ break;
+
+ default: /** input mode **/
+ if(!was_inmacro)
+ {
+ vp->last_cmd = c;
+ vp->lastrepeat = vp->repeat;
+ }
+ vp->repeat = 1;
+ if( i == GOOD )
+ continue;
+ return(i);
+ }
+
+ switch( c )
+ {
+ /***** Other stuff *****/
+
+ case cntl('L'): /** Redraw line **/
+ /*** print the prompt and ***/
+ /* force a total refresh */
+ if(vp->nonewline==0 && !vp->ed->e_nocrnl)
+ putchar('\n');
+ vp->nonewline = 0;
+ pr_string(vp,Prompt);
+ window[0] = '\0';
+ cur_phys = vp->first_wind;
+ vp->ofirst_wind = INVALID;
+ vp->long_line = ' ';
+ break;
+
+ case cntl('V'):
+ {
+ register const char *p = fmtident(e_version);
+ save_v(vp);
+ del_line(vp,BAD);
+ while(c = *p++)
+ append(vp,c,APPEND);
+ refresh(vp,CONTROL);
+ ed_getchar(vp->ed,-1);
+ restore_v(vp);
+ break;
+ }
+
+ case '/': /** Search **/
+ case '?':
+ case 'N':
+ case 'n':
+ save_v(vp);
+ switch( search(vp,c) )
+ {
+ case GOOD:
+ /*** force a total refresh ***/
+ window[0] = '\0';
+ goto newhist;
+
+ case BAD:
+ /*** no match ***/
+ ed_ringbell();
+
+ default:
+ if( vp->u_column == INVALID )
+ del_line(vp,BAD);
+ else
+ restore_v(vp);
+ break;
+ }
+ break;
+
+ case 'j': /** get next command **/
+ case '+': /** get next command **/
+#if SHOPT_EDPREDICT
+ if(vp->ed->hlist)
+ {
+ if(vp->ed->hoff >= vp->ed->hmax)
+ goto ringbell;
+ vp->ed->hoff++;
+ goto hupdate;
+ }
+#endif /* SHOPT_EDPREDICT */
+ curhline += vp->repeat;
+ if( curhline > histmax )
+ {
+ curhline = histmax;
+ goto ringbell;
+ }
+ else if(curhline==histmax && tmp_u_column!=INVALID )
+ {
+ vp->u_space = tmp_u_space;
+ vp->u_column = tmp_u_column;
+ restore_v(vp);
+ vp->u_space = real_u_space;
+ break;
+ }
+ save_v(vp);
+ cur_virt = INVALID;
+ goto newhist;
+
+ case 'k': /** get previous command **/
+ case '-': /** get previous command **/
+#if SHOPT_EDPREDICT
+ if(vp->ed->hlist)
+ {
+ if(vp->ed->hoff == 0)
+ goto ringbell;
+ vp->ed->hoff--;
+ hupdate:
+ ed_histlist(vp->ed,*vp->ed->hlist!=0);
+ vp->nonewline++;
+ ed_ungetchar(vp->ed,cntl('L'));
+ continue;
+ }
+#endif /* SHOPT_EDPREDICT */
+ if( curhline == histmax )
+ {
+ vp->u_space = tmp_u_space;
+ i = vp->u_column;
+ save_v(vp);
+ vp->u_space = real_u_space;
+ tmp_u_column = vp->u_column;
+ vp->u_column = i;
+ }
+
+ curhline -= vp->repeat;
+ if( curhline <= histmin )
+ {
+ curhline += vp->repeat;
+ goto ringbell;
+ }
+ save_v(vp);
+ cur_virt = INVALID;
+ newhist:
+ if(curhline!=histmax || cur_virt==INVALID)
+ hist_copy((char*)virtual, MAXLINE, curhline,-1);
+ else
+ {
+ strcpy((char*)virtual,(char*)vp->u_space);
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)vp->u_space,vp->u_space);
+#endif /* SHOPT_MULTIBYTE */
+ }
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)virtual,virtual);
+#endif /* SHOPT_MULTIBYTE */
+ if((last_virt=genlen(virtual)-1) >= 0 && cur_virt == INVALID)
+ cur_virt = 0;
+#if SHOPT_EDPREDICT
+ if(vp->ed->hlist)
+ {
+ ed_histlist(vp->ed,0);
+ if(c=='\n')
+ ed_ungetchar(vp->ed,c);
+ ed_ungetchar(vp->ed,cntl('L'));
+ vp->nonewline = 1;
+ cur_virt = 0;
+ }
+#endif /*SHOPT_EDPREDICT */
+ break;
+
+
+ case 'u': /** undo the last thing done **/
+ restore_v(vp);
+ break;
+
+ case 'U': /** Undo everything **/
+ save_v(vp);
+ if( virtual[0] == '\0' )
+ goto ringbell;
+ else
+ {
+ gencpy(virtual, vp->U_space);
+ last_virt = genlen(vp->U_space) - 1;
+ cur_virt = 0;
+ }
+ break;
+
+#if KSHELL
+ case 'v':
+ if(vp->repeat_set==0)
+ goto vcommand;
+#endif /* KSHELL */
+
+ case 'G': /** goto command repeat **/
+ if(vp->repeat_set==0)
+ vp->repeat = histmin+1;
+ if( vp->repeat <= histmin || vp->repeat > histmax )
+ {
+ goto ringbell;
+ }
+ curhline = vp->repeat;
+ save_v(vp);
+ if(c == 'G')
+ {
+ cur_virt = INVALID;
+ goto newhist;
+ }
+
+#if KSHELL
+ vcommand:
+ if(ed_fulledit(vp->ed)==GOOD)
+ return(BIGVI);
+ else
+ goto ringbell;
+#endif /* KSHELL */
+
+ case '#': /** insert(delete) # to (no)comment command **/
+ if( cur_virt != INVALID )
+ {
+ register genchar *p = &virtual[last_virt+1];
+ *p = 0;
+ /*** see whether first char is comment char ***/
+ c = (virtual[0]=='#');
+ while(p-- >= virtual)
+ {
+ if(*p=='\n' || p<virtual)
+ {
+ if(c) /* delete '#' */
+ {
+ if(p[1]=='#')
+ {
+ last_virt--;
+ gencpy(p+1,p+2);
+ }
+ }
+ else
+ {
+ cur_virt = p-virtual;
+ append(vp,'#', APPEND);
+ }
+ }
+ }
+ if(c)
+ {
+ curhline = histmax;
+ cur_virt = 0;
+ break;
+ }
+ refresh(vp,INPUT);
+ }
+
+ case '\n': /** send to shell **/
+#if SHOPT_EDPREDICT
+ if(!vp->ed->hlist)
+ return(ENTER);
+ case '\t': /** bring choice to edit **/
+ if(vp->ed->hlist)
+ {
+ if(vp->repeat > vp->ed->nhlist-vp->ed->hoff)
+ goto ringbell;
+ curhline = vp->ed->hlist[vp->repeat+vp->ed->hoff-1]->index;
+ goto newhist;
+ }
+ goto ringbell;
+#else
+ return(ENTER);
+#endif /* SHOPT_EDPREDICT */
+ case ESC:
+ /* don't ring bell if next char is '[' */
+ if(!lookahead)
+ {
+ char x;
+ if(sfpkrd(editb.e_fd,&x,1,'\r',400L,-1)>0)
+ ed_ungetchar(vp->ed,x);
+ }
+ if(lookahead)
+ {
+ ed_ungetchar(vp->ed,c=ed_getchar(vp->ed,1));
+ if(c=='[')
+ {
+ vp->repeat = 1;
+ continue;
+ }
+ }
+ default:
+ ringbell:
+ ed_ringbell();
+ vp->repeat = 1;
+ continue;
+ }
+
+ refresh(vp,CONTROL);
+ vp->repeat = 1;
+ }
+/* NOTREACHED */
+ return(0);
+}
+
+/*{ CURSOR( new_current_physical )
+ *
+ * This routine will position the virtual cursor at
+ * physical column x in the window.
+ *
+}*/
+
+static void cursor(Vi_t *vp,register int x)
+{
+#if SHOPT_MULTIBYTE
+ while(physical[x]==MARKER)
+ x++;
+#endif /* SHOPT_MULTIBYTE */
+ cur_phys = ed_setcursor(vp->ed, physical, cur_phys,x,vp->first_wind);
+}
+
+/*{ DELETE( nchars, mode )
+ *
+ * Delete nchars from the virtual space and leave cur_virt positioned
+ * at cur_virt-1.
+ *
+ * If mode = 'c', do not save the characters deleted
+ * = 'd', save them in yankbuf and delete.
+ * = 'y', save them in yankbuf but do not delete.
+ *
+}*/
+
+static void cdelete(Vi_t *vp,register int nchars, int mode)
+{
+ register int i;
+ register genchar *cp;
+
+ if( cur_virt < first_virt )
+ {
+ ed_ringbell();
+ return;
+ }
+ if( nchars > 0 )
+ {
+ cp = virtual+cur_virt;
+ vp->o_v_char = cp[0];
+ if( (cur_virt-- + nchars) > last_virt )
+ {
+ /*** set nchars to number actually deleted ***/
+ nchars = last_virt - cur_virt;
+ }
+
+ /*** save characters to be deleted ***/
+
+ if( mode != 'c' )
+ {
+ i = cp[nchars];
+ cp[nchars] = 0;
+ gencpy(yankbuf,cp);
+ cp[nchars] = i;
+ }
+
+ /*** now delete these characters ***/
+
+ if( mode != 'y' )
+ {
+ gencpy(cp,cp+nchars);
+ last_virt -= nchars;
+ }
+ }
+ return;
+}
+
+/*{ DEL_LINE( mode )
+ *
+ * This routine will delete the line.
+ * mode = GOOD, do a save_v()
+ *
+}*/
+static void del_line(register Vi_t *vp, int mode)
+{
+ if( last_virt == INVALID )
+ return;
+
+ if( mode == GOOD )
+ save_v(vp);
+
+ cur_virt = 0;
+ first_virt = 0;
+ cdelete(vp,last_virt+1, BAD);
+ refresh(vp,CONTROL);
+
+ cur_virt = INVALID;
+ cur_phys = 0;
+ vp->findchar = INVALID;
+ last_phys = INVALID;
+ last_virt = INVALID;
+ vp->last_wind = INVALID;
+ vp->first_wind = 0;
+ vp->o_v_char = '\0';
+ vp->ocur_phys = 0;
+ vp->ocur_virt = MAXCHAR;
+ vp->ofirst_wind = 0;
+ window[0] = '\0';
+ return;
+}
+
+/*{ DELMOTION( motion, mode )
+ *
+ * Delete thru motion.
+ *
+ * mode = 'd', save deleted characters, delete
+ * = 'c', do not save characters, change
+ * = 'y', save characters, yank
+ *
+ * Returns 1 if operation successful; else 0.
+ *
+}*/
+
+static int delmotion(Vi_t *vp,int motion, int mode)
+{
+ register int begin, end, delta;
+ /* the following saves a register */
+
+ if( cur_virt == INVALID )
+ return(0);
+ if( mode != 'y' )
+ save_v(vp);
+ begin = cur_virt;
+
+ /*** fake out the motion routines by appending a blank ***/
+
+ virtual[++last_virt] = ' ';
+ end = mvcursor(vp,motion);
+ virtual[last_virt--] = 0;
+ if(!end)
+ return(0);
+
+ end = cur_virt;
+ if( mode=='c' && end>begin && strchr("wW", motion) )
+ {
+ /*** called by change operation, user really expects ***/
+ /* the effect of the eE commands, so back up to end of word */
+ while( end>begin && isblank(end-1) )
+ --end;
+ if( end == begin )
+ ++end;
+ }
+
+ delta = end - begin;
+ if( delta >= 0 )
+ {
+ cur_virt = begin;
+ if( strchr("eE;,TtFf%", motion) )
+ ++delta;
+ }
+ else
+ {
+ delta = -delta + (motion=='%');
+ }
+
+ cdelete(vp,delta, mode);
+ if( mode == 'y' )
+ cur_virt = begin;
+ return(1);
+}
+
+
+/*{ ENDWORD( nwords, cmd )
+ *
+ * This routine will move cur_virt to the end of the nth word.
+ *
+}*/
+
+static void endword(Vi_t *vp, int nwords, register int cmd)
+{
+ register int tcur_virt = cur_virt;
+ while( nwords-- )
+ {
+ if( !isblank(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ while( isblank(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ if( cmd == 'E' )
+ {
+ while( !isblank(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ }
+ else
+ {
+ if( isalph(tcur_virt) )
+ while( isalph(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ else
+ while( !isalph(tcur_virt) && !isblank(tcur_virt)
+ && tcur_virt<=last_virt )
+ ++tcur_virt;
+ }
+ if( tcur_virt > first_virt )
+ tcur_virt--;
+ }
+ cur_virt = tcur_virt;
+ return;
+}
+
+/*{ FORWARD( nwords, cmd )
+ *
+ * This routine will move cur_virt forward to the next nth word.
+ *
+}*/
+
+static void forward(Vi_t *vp,register int nwords, int cmd)
+{
+ register int tcur_virt = cur_virt;
+ while( nwords-- )
+ {
+ if( cmd == 'W' )
+ {
+ while( !isblank(tcur_virt) && tcur_virt < last_virt )
+ ++tcur_virt;
+ }
+ else
+ {
+ if( isalph(tcur_virt) )
+ {
+ while( isalph(tcur_virt) && tcur_virt<last_virt )
+ ++tcur_virt;
+ }
+ else
+ {
+ while( !isalph(tcur_virt) && !isblank(tcur_virt)
+ && tcur_virt < last_virt )
+ ++tcur_virt;
+ }
+ }
+ while( isblank(tcur_virt) && tcur_virt < last_virt )
+ ++tcur_virt;
+ }
+ cur_virt = tcur_virt;
+ return;
+}
+
+
+
+/*{ GETCOUNT(c)
+ *
+ * Set repeat to the user typed number and return the terminating
+ * character.
+ *
+}*/
+
+static int getcount(register Vi_t *vp,register int c)
+{
+ register int i;
+
+ /*** get any repeat count ***/
+
+ if( c == '0' )
+ return(c);
+
+ vp->repeat_set++;
+ i = 0;
+ while( digit(c) )
+ {
+ i = i*10 + c - '0';
+ c = ed_getchar(vp->ed,-1);
+ }
+
+ if( i > 0 )
+ vp->repeat *= i;
+ return(c);
+}
+
+
+/*{ GETLINE( mode )
+ *
+ * This routine will fetch a line.
+ * mode = APPEND, allow escape to cntlmode subroutine
+ * appending characters.
+ * = REPLACE, allow escape to cntlmode subroutine
+ * replacing characters.
+ * = SEARCH, no escape allowed
+ * = ESC, enter control mode immediately
+ *
+ * The cursor will always be positioned after the last
+ * char printed.
+ *
+ * This routine returns when cr, nl, or (eof in column 0) is
+ * received (column 0 is the first char position).
+ *
+}*/
+
+static void getline(register Vi_t* vp,register int mode)
+{
+ register int c;
+ register int tmp;
+ int max_virt=0, last_save=0;
+ genchar saveline[MAXLINE];
+ vp->addnl = 1;
+
+ if( mode == ESC )
+ {
+ /*** go directly to control mode ***/
+ goto escape;
+ }
+
+ for(;;)
+ {
+ if( (c=ed_getchar(vp->ed,mode==SEARCH?1:-2)) == usreof )
+ c = UEOF;
+ else if( c == usrerase )
+ c = UERASE;
+ else if( c == usrkill )
+ c = UKILL;
+ else if( c == editb.e_werase )
+ c = UWERASE;
+ else if( c == usrlnext )
+ c = ULNEXT;
+ else if(mode==SEARCH && c==editb.e_intr)
+ c = UINTR;
+
+ if( c == ULNEXT)
+ {
+ /*** implement ^V to escape next char ***/
+ c = ed_getchar(vp->ed,2);
+ append(vp,c, mode);
+ refresh(vp,INPUT);
+ continue;
+ }
+
+ switch( c )
+ {
+ case ESC: /** enter control mode **/
+ if(!sh_isoption(SH_VI))
+ {
+ append(vp,c, mode);
+ break;
+ }
+ if( mode == SEARCH )
+ {
+ ed_ringbell();
+ continue;
+ }
+ else
+ {
+ escape:
+ if( mode == REPLACE )
+ {
+ c = max_virt-cur_virt;
+ if(c > 0 && last_save>=cur_virt)
+ {
+ genncpy((&virtual[cur_virt]),&saveline[cur_virt],c);
+ if(last_virt>=last_save)
+ last_virt=last_save-1;
+ refresh(vp,INPUT);
+ }
+ --cur_virt;
+ }
+ tmp = cntlmode(vp);
+ if( tmp == ENTER || tmp == BIGVI )
+ {
+#if SHOPT_MULTIBYTE
+ vp->bigvi = (tmp==BIGVI);
+#endif /* SHOPT_MULTIBYTE */
+ return;
+ }
+ if( tmp == INSERT )
+ {
+ mode = APPEND;
+ continue;
+ }
+ mode = tmp;
+ if(mode==REPLACE)
+ {
+ c = last_save = last_virt+1;
+ if(c >= MAXLINE)
+ c = MAXLINE-1;
+ genncpy(saveline, virtual, c);
+ }
+ }
+ break;
+
+ case UINTR:
+ first_virt = 0;
+ cdelete(vp,cur_virt+1, BAD);
+ cur_virt = -1;
+ return;
+ case UERASE: /** user erase char **/
+ /*** treat as backspace ***/
+
+ case '\b': /** backspace **/
+ if( virtual[cur_virt] == '\\' )
+ {
+ cdelete(vp,1, BAD);
+ append(vp,usrerase, mode);
+ }
+ else
+ {
+ if( mode==SEARCH && cur_virt==0 )
+ {
+ first_virt = 0;
+ cdelete(vp,1, BAD);
+ return;
+ }
+ if(mode==REPLACE || (last_save>0 && last_virt<=last_save))
+ {
+ if(cur_virt<=first_virt)
+ ed_ringbell();
+ else if(mode==REPLACE)
+ --cur_virt;
+ mode = REPLACE;
+ sync_cursor(vp);
+ continue;
+ }
+ else
+ cdelete(vp,1, BAD);
+ }
+ break;
+
+ case UWERASE: /** delete back word **/
+ if( cur_virt > first_virt &&
+ !isblank(cur_virt) &&
+ !ispunct(virtual[cur_virt]) &&
+ isblank(cur_virt-1) )
+ {
+ cdelete(vp,1, BAD);
+ }
+ else
+ {
+ tmp = cur_virt;
+ backword(vp,1, 'W');
+ cdelete(vp,tmp - cur_virt + 1, BAD);
+ }
+ break;
+
+ case UKILL: /** user kill line char **/
+ if( virtual[cur_virt] == '\\' )
+ {
+ cdelete(vp,1, BAD);
+ append(vp,usrkill, mode);
+ }
+ else
+ {
+ if( mode == SEARCH )
+ {
+ cur_virt = 1;
+ delmotion(vp, '$', BAD);
+ }
+ else if(first_virt)
+ {
+ tmp = cur_virt;
+ cur_virt = first_virt;
+ cdelete(vp,tmp - cur_virt + 1, BAD);
+ }
+ else
+ del_line(vp,GOOD);
+ }
+ break;
+
+ case UEOF: /** eof char **/
+ if( cur_virt != INVALID )
+ continue;
+ vp->addnl = 0;
+
+ case '\n': /** newline or return **/
+ if( mode != SEARCH )
+ save_last(vp);
+ refresh(vp,INPUT);
+ last_phys++;
+ return;
+
+ case '\t': /** command completion **/
+ if(mode!=SEARCH && last_virt>=0 && (vp->ed->e_tabcount|| !isblank(cur_virt)) && vp->ed->sh->nextprompt)
+ {
+ if(virtual[cur_virt]=='\\')
+ {
+ virtual[cur_virt] = '\t';
+ break;
+ }
+ if(vp->ed->e_tabcount==0)
+ {
+ ed_ungetchar(vp->ed,'\\');
+ vp->ed->e_tabcount=1;
+ goto escape;
+ }
+ else if(vp->ed->e_tabcount==1)
+ {
+ ed_ungetchar(vp->ed,'=');
+ goto escape;
+ }
+ vp->ed->e_tabcount = 0;
+ }
+ /* FALL THRU*/
+ default:
+ if( mode == REPLACE )
+ {
+ if( cur_virt < last_virt )
+ {
+ replace(vp,c, 1);
+ if(cur_virt>max_virt)
+ max_virt = cur_virt;
+ continue;
+ }
+ cdelete(vp,1, BAD);
+ mode = APPEND;
+ max_virt = last_virt+3;
+ }
+ append(vp,c, mode);
+ break;
+ }
+ refresh(vp,INPUT);
+
+ }
+}
+
+/*{ MVCURSOR( motion )
+ *
+ * This routine will move the virtual cursor according to motion
+ * for repeat times.
+ *
+ * It returns GOOD if successful; else BAD.
+ *
+}*/
+
+static int mvcursor(register Vi_t* vp,register int motion)
+{
+ register int count;
+ register int tcur_virt;
+ register int incr = -1;
+ register int bound = 0;
+
+ switch(motion)
+ {
+ /***** Cursor move commands *****/
+
+ case '0': /** First column **/
+ tcur_virt = 0;
+ break;
+
+ case '^': /** First nonblank character **/
+ tcur_virt = first_virt;
+ while( isblank(tcur_virt) && tcur_virt < last_virt )
+ ++tcur_virt;
+ break;
+
+ case '|':
+ tcur_virt = vp->repeat-1;
+ if(tcur_virt <= last_virt)
+ break;
+ /* fall through */
+
+ case '$': /** End of line **/
+ tcur_virt = last_virt;
+ break;
+
+ case '[':
+ switch(motion=getcount(vp,ed_getchar(vp->ed,-1)))
+ {
+ case 'A':
+#if SHOPT_EDPREDICT
+ if(!vp->ed->hlist && cur_virt>=0 && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
+#else
+ if(cur_virt>=0 && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
+#endif /* SHOPT_EDPREDICT */
+ {
+ virtual[last_virt + 1] = '\0';
+#if SHOPT_MULTIBYTE
+ ed_external(virtual,lsearch+1);
+#else
+ strcpy(lsearch+1,virtual);
+#endif /* SHOPT_MULTIBYTE */
+ *lsearch = '^';
+ vp->direction = -2;
+ ed_ungetchar(vp->ed,'n');
+ }
+ else if(cur_virt==0 && vp->direction == -2)
+ ed_ungetchar(vp->ed,'n');
+ else
+ ed_ungetchar(vp->ed,'k');
+ return(1);
+ case 'B':
+ ed_ungetchar(vp->ed,'j');
+ return(1);
+ case 'C':
+ motion = last_virt;
+ incr = 1;
+ goto walk;
+ case 'D':
+ motion = first_virt;
+ goto walk;
+ case 'H':
+ tcur_virt = 0;
+ break;
+ case 'Y':
+ tcur_virt = last_virt;
+ break;
+ default:
+ ed_ungetchar(vp->ed,motion);
+ return(0);
+ }
+ break;
+
+ case 'h': /** Left one **/
+ case '\b':
+ motion = first_virt;
+ goto walk;
+
+ case ' ':
+ case 'l': /** Right one **/
+ motion = last_virt;
+ incr = 1;
+ walk:
+ tcur_virt = cur_virt;
+ if( incr*tcur_virt < motion)
+ {
+ tcur_virt += vp->repeat*incr;
+ if( incr*tcur_virt > motion)
+ tcur_virt = motion;
+ }
+ else
+ return(0);
+ break;
+
+ case 'B':
+ case 'b': /** back word **/
+ tcur_virt = cur_virt;
+ backword(vp,vp->repeat, motion);
+ if( cur_virt == tcur_virt )
+ return(0);
+ return(1);
+
+ case 'E':
+ case 'e': /** end of word **/
+ tcur_virt = cur_virt;
+ if(tcur_virt >=0)
+ endword(vp, vp->repeat, motion);
+ if( cur_virt == tcur_virt )
+ return(0);
+ return(1);
+
+ case ',': /** reverse find old char **/
+ case ';': /** find old char **/
+ switch(vp->last_find)
+ {
+ case 't':
+ case 'f':
+ if(motion==';')
+ {
+ bound = last_virt;
+ incr = 1;
+ }
+ goto find_b;
+
+ case 'T':
+ case 'F':
+ if(motion==',')
+ {
+ bound = last_virt;
+ incr = 1;
+ }
+ goto find_b;
+
+ default:
+ return(0);
+ }
+
+
+ case 't': /** find up to new char forward **/
+ case 'f': /** find new char forward **/
+ bound = last_virt;
+ incr = 1;
+
+ case 'T': /** find up to new char backward **/
+ case 'F': /** find new char backward **/
+ vp->last_find = motion;
+ if((vp->findchar=getrchar(vp))==ESC)
+ return(1);
+find_b:
+ tcur_virt = cur_virt;
+ count = vp->repeat;
+ while( count-- )
+ {
+ while( incr*(tcur_virt+=incr) <= bound
+ && virtual[tcur_virt] != vp->findchar );
+ if( incr*tcur_virt > bound )
+ {
+ return(0);
+ }
+ }
+ if( fold(vp->last_find) == 'T' )
+ tcur_virt -= incr;
+ break;
+
+ case '%':
+ {
+ int nextmotion;
+ int nextc;
+ tcur_virt = cur_virt;
+ while( tcur_virt <= last_virt
+ && strchr(paren_chars,virtual[tcur_virt])==(char*)0)
+ tcur_virt++;
+ if(tcur_virt > last_virt )
+ return(0);
+ nextc = virtual[tcur_virt];
+ count = strchr(paren_chars,nextc)-paren_chars;
+ if(count < 3)
+ {
+ incr = 1;
+ bound = last_virt;
+ nextmotion = paren_chars[count+3];
+ }
+ else
+ nextmotion = paren_chars[count-3];
+ count = 1;
+ while(count >0 && incr*(tcur_virt+=incr) <= bound)
+ {
+ if(virtual[tcur_virt] == nextmotion)
+ count--;
+ else if(virtual[tcur_virt]==nextc)
+ count++;
+ }
+ if(count)
+ return(0);
+ break;
+ }
+
+ case 'W':
+ case 'w': /** forward word **/
+ tcur_virt = cur_virt;
+ forward(vp,vp->repeat, motion);
+ if( tcur_virt == cur_virt )
+ return(0);
+ return(1);
+
+ default:
+ return(0);
+ }
+ cur_virt = tcur_virt;
+
+ return(1);
+}
+
+/*
+ * print a string
+ */
+
+static void pr_string(register Vi_t *vp, register const char *sp)
+{
+ /*** copy string sp ***/
+ register char *ptr = editb.e_outptr;
+ while(*sp)
+ *ptr++ = *sp++;
+ editb.e_outptr = ptr;
+ return;
+}
+
+/*{ PUTSTRING( column, nchars )
+ *
+ * Put nchars starting at column of physical into the workspace
+ * to be printed.
+ *
+}*/
+
+static void putstring(register Vi_t *vp,register int col, register int nchars)
+{
+ while( nchars-- )
+ putchar(physical[col++]);
+ return;
+}
+
+/*{ REFRESH( mode )
+ *
+ * This routine will refresh the crt so the physical image matches
+ * the virtual image and display the proper window.
+ *
+ * mode = CONTROL, refresh in control mode, ie. leave cursor
+ * positioned at last char printed.
+ * = INPUT, refresh in input mode; leave cursor positioned
+ * after last char printed.
+ * = TRANSLATE, perform virtual to physical translation
+ * and adjust left margin only.
+ *
+ * +-------------------------------+
+ * | | | virtual | | |
+ * +-------------------------------+
+ * cur_virt last_virt
+ *
+ * +-----------------------------------------------+
+ * | | | physical | | |
+ * +-----------------------------------------------+
+ * cur_phys last_phys
+ *
+ * 0 w_size - 1
+ * +-----------------------+
+ * | | | window |
+ * +-----------------------+
+ * cur_window = cur_phys - first_wind
+}*/
+
+static void refresh(register Vi_t* vp, int mode)
+{
+ register int p;
+ register int v;
+ register int first_w = vp->first_wind;
+ int p_differ;
+ int new_lw;
+ int ncur_phys;
+ int opflag; /* search optimize flag */
+
+# define w v
+
+ /*** find out if it's necessary to start translating at beginning ***/
+
+ if(lookahead>0)
+ {
+ p = previous[lookahead-1];
+ if(p != ESC && p != '\n' && p != '\r')
+ mode = TRANSLATE;
+ }
+ v = cur_virt;
+#if SHOPT_EDPREDICT
+ if(mode==INPUT && v>0 && virtual[0]=='#' && v==last_virt && virtual[v]!='*' && sh_isoption(SH_VI))
+ {
+ int n;
+ virtual[last_virt+1] = 0;
+# if SHOPT_MULTIBYTE
+ ed_external(virtual,(char*)virtual);
+# endif /* SHOPT_MULTIBYTE */
+ n = ed_histgen(vp->ed,(char*)virtual);
+# if SHOPT_MULTIBYTE
+ ed_internal((char*)virtual,virtual);
+# endif /* SHOPT_MULTIBYTE */
+ if(vp->ed->hlist)
+ {
+ ed_histlist(vp->ed,n);
+ pr_string(vp,Prompt);
+ vp->ocur_virt = INVALID;
+ ed_setcursor(vp->ed,physical,0,cur_phys,0);
+ }
+ else
+ ed_ringbell();
+ }
+ else if(mode==INPUT && v<=1 && vp->ed->hlist)
+ ed_histlist(vp->ed,0);
+#endif /* SHOPT_EDPREDICT */
+ if( v<vp->ocur_virt || vp->ocur_virt==INVALID
+ || ( v==vp->ocur_virt
+ && (!is_print(virtual[v]) || !is_print(vp->o_v_char))) )
+ {
+ opflag = 0;
+ p = 0;
+ v = 0;
+ }
+ else
+ {
+ opflag = 1;
+ p = vp->ocur_phys;
+ v = vp->ocur_virt;
+ if( !is_print(virtual[v]) )
+ {
+ /*** avoid double ^'s ***/
+ ++p;
+ ++v;
+ }
+ }
+ virtual[last_virt+1] = 0;
+ ncur_phys = ed_virt_to_phys(vp->ed,virtual,physical,cur_virt,v,p);
+ p = genlen(physical);
+ if( --p < 0 )
+ last_phys = 0;
+ else
+ last_phys = p;
+
+ /*** see if this was a translate only ***/
+
+ if( mode == TRANSLATE )
+ return;
+
+ /*** adjust left margin if necessary ***/
+
+ if( ncur_phys<first_w || ncur_phys>=(first_w + w_size) )
+ {
+ cursor(vp,first_w);
+ first_w = ncur_phys - (w_size>>1);
+ if( first_w < 0 )
+ first_w = 0;
+ vp->first_wind = cur_phys = first_w;
+ }
+
+ /*** attempt to optimize search somewhat to find ***/
+ /*** out where physical and window images differ ***/
+
+ if( first_w==vp->ofirst_wind && ncur_phys>=vp->ocur_phys && opflag==1 )
+ {
+ p = vp->ocur_phys;
+ w = p - first_w;
+ }
+ else
+ {
+ p = first_w;
+ w = 0;
+ }
+
+ for(; (p<=last_phys && w<=vp->last_wind); ++p, ++w)
+ {
+ if( window[w] != physical[p] )
+ break;
+ }
+ p_differ = p;
+
+ if( (p>last_phys || p>=first_w+w_size) && w>vp->last_wind
+ && cur_virt==vp->ocur_virt )
+ {
+ /*** images are identical ***/
+ return;
+ }
+
+ /*** copy the physical image to the window image ***/
+
+ if( last_virt != INVALID )
+ {
+ while( p <= last_phys && w < w_size )
+ window[w++] = physical[p++];
+ }
+ new_lw = w;
+
+ /*** erase trailing characters if needed ***/
+
+ while( w <= vp->last_wind )
+ window[w++] = ' ';
+ vp->last_wind = --w;
+
+ p = p_differ;
+
+ /*** move cursor to start of difference ***/
+
+ cursor(vp,p);
+
+ /*** and output difference ***/
+
+ w = p - first_w;
+ while( w <= vp->last_wind )
+ putchar(window[w++]);
+
+ cur_phys = w + first_w;
+ vp->last_wind = --new_lw;
+
+ if( last_phys >= w_size )
+ {
+ if( first_w == 0 )
+ vp->long_char = '>';
+ else if( last_phys < (first_w+w_size) )
+ vp->long_char = '<';
+ else
+ vp->long_char = '*';
+ }
+ else
+ vp->long_char = ' ';
+
+ if( vp->long_line != vp->long_char )
+ {
+ /*** indicate lines longer than window ***/
+ while( w++ < w_size )
+ {
+ putchar(' ');
+ ++cur_phys;
+ }
+ putchar(vp->long_char);
+ ++cur_phys;
+ vp->long_line = vp->long_char;
+ }
+
+ if(vp->ed->e_multiline && vp->ofirst_wind==INVALID && !vp->ed->e_nocrnl)
+ ed_setcursor(vp->ed, physical, last_phys+1, last_phys+1, -1);
+ vp->ed->e_nocrnl = 0;
+ vp->ocur_phys = ncur_phys;
+ vp->ocur_virt = cur_virt;
+ vp->ofirst_wind = first_w;
+
+ if( mode==INPUT && cur_virt>INVALID )
+ ++ncur_phys;
+
+ cursor(vp,ncur_phys);
+ ed_flush(vp->ed);
+ return;
+}
+
+/*{ REPLACE( char, increment )
+ *
+ * Replace the cur_virt character with char. This routine attempts
+ * to avoid using refresh().
+ *
+ * increment = 1, increment cur_virt after replacement.
+ * = 0, leave cur_virt where it is.
+ *
+}*/
+
+static void replace(register Vi_t *vp, register int c, register int increment)
+{
+ register int cur_window;
+
+ if( cur_virt == INVALID )
+ {
+ /*** can't replace invalid cursor ***/
+ ed_ringbell();
+ return;
+ }
+ cur_window = cur_phys - vp->first_wind;
+ if( vp->ocur_virt == INVALID || !is_print(c)
+ || !is_print(virtual[cur_virt])
+ || !is_print(vp->o_v_char)
+#if SHOPT_MULTIBYTE
+ || !iswascii(c) || mbwidth(vp->o_v_char)>1
+ || !iswascii(virtual[cur_virt])
+#endif /* SHOPT_MULTIBYTE */
+ || (increment && (cur_window==w_size-1)
+ || !is_print(virtual[cur_virt+1])) )
+ {
+ /*** must use standard refresh routine ***/
+
+ cdelete(vp,1, BAD);
+ append(vp,c, APPEND);
+ if( increment && cur_virt<last_virt )
+ ++cur_virt;
+ refresh(vp,CONTROL);
+ }
+ else
+ {
+ virtual[cur_virt] = c;
+ physical[cur_phys] = c;
+ window[cur_window] = c;
+ putchar(c);
+ if(increment)
+ {
+ c = virtual[++cur_virt];
+ ++cur_phys;
+ }
+ else
+ {
+ putchar('\b');
+ }
+ vp->o_v_char = c;
+ ed_flush(vp->ed);
+ }
+ return;
+}
+
+/*{ RESTORE_V()
+ *
+ * Restore the contents of virtual space from u_space.
+ *
+}*/
+
+static void restore_v(register Vi_t *vp)
+{
+ register int tmpcol;
+ genchar tmpspace[MAXLINE];
+
+ if( vp->u_column == INVALID-1 )
+ {
+ /*** never saved anything ***/
+ ed_ringbell();
+ return;
+ }
+ gencpy(tmpspace, vp->u_space);
+ tmpcol = vp->u_column;
+ save_v(vp);
+ gencpy(virtual, tmpspace);
+ cur_virt = tmpcol;
+ last_virt = genlen(tmpspace) - 1;
+ vp->ocur_virt = MAXCHAR; /** invalidate refresh optimization **/
+ return;
+}
+
+/*{ SAVE_LAST()
+ *
+ * If the user has typed something, save it in last line.
+ *
+}*/
+
+static void save_last(register Vi_t* vp)
+{
+ register int i;
+
+ if( (i = cur_virt - first_virt + 1) > 0 )
+ {
+ /*** save last thing user typed ***/
+ if(i >= MAXLINE)
+ i = MAXLINE-1;
+ genncpy(vp->lastline, (&virtual[first_virt]), i);
+ vp->lastline[i] = '\0';
+ }
+ return;
+}
+
+/*{ SAVE_V()
+ *
+ * This routine will save the contents of virtual in u_space.
+ *
+}*/
+
+static void save_v(register Vi_t *vp)
+{
+ if(!inmacro)
+ {
+ virtual[last_virt + 1] = '\0';
+ gencpy(vp->u_space, virtual);
+ vp->u_column = cur_virt;
+ }
+ return;
+}
+
+/*{ SEARCH( mode )
+ *
+ * Search history file for regular expression.
+ *
+ * mode = '/' require search string and search new to old
+ * mode = '?' require search string and search old to new
+ * mode = 'N' repeat last search in reverse direction
+ * mode = 'n' repeat last search
+ *
+}*/
+
+/*
+ * search for <string> in the current command
+ */
+static int curline_search(Vi_t *vp, const char *string)
+{
+ register int len=strlen(string);
+ register const char *dp,*cp=string, *dpmax;
+#if SHOPT_MULTIBYTE
+ ed_external(vp->u_space,(char*)vp->u_space);
+#endif /* SHOPT_MULTIBYTE */
+ for(dp=(char*)vp->u_space,dpmax=dp+strlen(dp)-len; dp<=dpmax; dp++)
+ {
+ if(*dp==*cp && memcmp(cp,dp,len)==0)
+ return(dp-(char*)vp->u_space);
+ }
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)vp->u_space,vp->u_space);
+#endif /* SHOPT_MULTIBYTE */
+ return(-1);
+}
+
+static int search(register Vi_t* vp,register int mode)
+{
+ register int new_direction;
+ register int oldcurhline;
+ register int i;
+ Histloc_t location;
+
+ if( vp->direction == -2 && mode != 'n')
+ vp->direction = -1;
+ if( mode == '/' || mode == '?')
+ {
+ /*** new search expression ***/
+ del_line(vp,BAD);
+ append(vp,mode, APPEND);
+ refresh(vp,INPUT);
+ first_virt = 1;
+ getline(vp,SEARCH);
+ first_virt = 0;
+ virtual[last_virt + 1] = '\0'; /*** make null terminated ***/
+ vp->direction = mode=='/' ? -1 : 1;
+ }
+
+ if( cur_virt == INVALID )
+ {
+ /*** no operation ***/
+ return(ABORT);
+ }
+
+ if( cur_virt==0 || fold(mode)=='N' )
+ {
+ /*** user wants repeat of last search ***/
+ del_line(vp,BAD);
+ strcpy( ((char*)virtual)+1, lsearch);
+#if SHOPT_MULTIBYTE
+ *((char*)virtual) = '/';
+ ed_internal((char*)virtual,virtual);
+#endif /* SHOPT_MULTIBYTE */
+ }
+
+ if( mode == 'N' )
+ new_direction = -vp->direction;
+ else
+ new_direction = vp->direction;
+
+
+ /*** now search ***/
+
+ oldcurhline = curhline;
+#if SHOPT_MULTIBYTE
+ ed_external(virtual,(char*)virtual);
+#endif /* SHOPT_MULTIBYTE */
+ if(mode=='?' && (i=curline_search(vp,((char*)virtual)+1))>=0)
+ {
+ location.hist_command = curhline;
+ location.hist_char = i;
+ }
+ else
+ {
+ i = INVALID;
+ if( new_direction==1 && curhline >= histmax )
+ curhline = histmin + 1;
+ location = hist_find(shgd->hist_ptr,((char*)virtual)+1, curhline, 1, new_direction);
+ }
+ cur_virt = i;
+ strncpy(lsearch, ((char*)virtual)+1, SEARCHSIZE);
+ lsearch[SEARCHSIZE-1] = 0;
+ if( (curhline=location.hist_command) >=0 )
+ {
+ vp->ocur_virt = INVALID;
+ return(GOOD);
+ }
+
+ /*** could not find matching line ***/
+
+ curhline = oldcurhline;
+ return(BAD);
+}
+
+/*{ SYNC_CURSOR()
+ *
+ * This routine will move the physical cursor to the same
+ * column as the virtual cursor.
+ *
+}*/
+
+static void sync_cursor(register Vi_t *vp)
+{
+ register int p;
+ register int v;
+ register int c;
+ int new_phys;
+
+ if( cur_virt == INVALID )
+ return;
+
+ /*** find physical col that corresponds to virtual col ***/
+
+ new_phys = 0;
+ if(vp->first_wind==vp->ofirst_wind && cur_virt>vp->ocur_virt && vp->ocur_virt!=INVALID)
+ {
+ /*** try to optimize search a little ***/
+ p = vp->ocur_phys + 1;
+#if SHOPT_MULTIBYTE
+ while(physical[p]==MARKER)
+ p++;
+#endif /* SHOPT_MULTIBYTE */
+ v = vp->ocur_virt + 1;
+ }
+ else
+ {
+ p = 0;
+ v = 0;
+ }
+ for(; v <= last_virt; ++p, ++v)
+ {
+#if SHOPT_MULTIBYTE
+ int d;
+ c = virtual[v];
+ if((d = mbwidth(c)) > 1)
+ {
+ if( v != cur_virt )
+ p += (d-1);
+ }
+ else if(!iswprint(c))
+#else
+ c = virtual[v];
+ if(!isprint(c))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ if( c == '\t' )
+ {
+ p -= ((p+editb.e_plen)%TABSIZE);
+ p += (TABSIZE-1);
+ }
+ else
+ {
+ ++p;
+ }
+ }
+ if( v == cur_virt )
+ {
+ new_phys = p;
+ break;
+ }
+ }
+
+ if( new_phys < vp->first_wind || new_phys >= vp->first_wind + w_size )
+ {
+ /*** asked to move outside of window ***/
+
+ window[0] = '\0';
+ refresh(vp,CONTROL);
+ return;
+ }
+
+ cursor(vp,new_phys);
+ ed_flush(vp->ed);
+ vp->ocur_phys = cur_phys;
+ vp->ocur_virt = cur_virt;
+ vp->o_v_char = virtual[vp->ocur_virt];
+
+ return;
+}
+
+/*{ TEXTMOD( command, mode )
+ *
+ * Modify text operations.
+ *
+ * mode != 0, repeat previous operation
+ *
+}*/
+
+static int textmod(register Vi_t *vp,register int c, int mode)
+{
+ register int i;
+ register genchar *p = vp->lastline;
+ register int trepeat = vp->repeat;
+ genchar *savep;
+
+ if(mode && (fold(vp->lastmotion)=='F' || fold(vp->lastmotion)=='T'))
+ vp->lastmotion = ';';
+
+ if( fold(c) == 'P' )
+ {
+ /*** change p from lastline to yankbuf ***/
+ p = yankbuf;
+ }
+
+addin:
+ switch( c )
+ {
+ /***** Input commands *****/
+
+#if KSHELL
+ case '\t':
+ if(vp->ed->e_tabcount!=1)
+ return(BAD);
+ c = '=';
+ case '*': /** do file name expansion in place **/
+ case '\\': /** do file name completion in place **/
+ if( cur_virt == INVALID )
+ return(BAD);
+ case '=': /** list file name expansions **/
+ save_v(vp);
+ i = last_virt;
+ ++last_virt;
+ mode = cur_virt-1;
+ virtual[last_virt] = 0;
+ if(ed_expand(vp->ed,(char*)virtual, &cur_virt, &last_virt, c, vp->repeat_set?vp->repeat:-1)<0)
+ {
+ if(vp->ed->e_tabcount)
+ {
+ vp->ed->e_tabcount=2;
+ ed_ungetchar(vp->ed,'\t');
+ --last_virt;
+ return(APPEND);
+ }
+ last_virt = i;
+ ed_ringbell();
+ }
+ else if(c == '=' && !vp->repeat_set)
+ {
+ last_virt = i;
+ vp->nonewline++;
+ ed_ungetchar(vp->ed,cntl('L'));
+ return(GOOD);
+ }
+ else
+ {
+ --cur_virt;
+ --last_virt;
+ vp->ocur_virt = MAXCHAR;
+ if(c=='=' || (mode<cur_virt && (virtual[cur_virt]==' ' || virtual[cur_virt]=='/')))
+ vp->ed->e_tabcount = 0;
+ return(APPEND);
+ }
+ break;
+
+ case '@': /** macro expansion **/
+ if( mode )
+ c = vp->lastmacro;
+ else
+ if((c=getrchar(vp))==ESC)
+ return(GOOD);
+ if(!inmacro)
+ vp->lastmacro = c;
+ if(ed_macro(vp->ed,c))
+ {
+ save_v(vp);
+ inmacro++;
+ return(GOOD);
+ }
+ ed_ringbell();
+ return(BAD);
+
+#endif /* KSHELL */
+ case '_': /** append last argument of prev command **/
+ save_v(vp);
+ {
+ genchar tmpbuf[MAXLINE];
+ if(vp->repeat_set==0)
+ vp->repeat = -1;
+ p = (genchar*)hist_word((char*)tmpbuf,MAXLINE,vp->repeat);
+ if(p==0)
+ {
+ ed_ringbell();
+ break;
+ }
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)p,tmpbuf);
+ p = tmpbuf;
+#endif /* SHOPT_MULTIBYTE */
+ i = ' ';
+ do
+ {
+ append(vp,i,APPEND);
+ }
+ while(i = *p++);
+ return(APPEND);
+ }
+
+ case 'A': /** append to end of line **/
+ cur_virt = last_virt;
+ sync_cursor(vp);
+
+ case 'a': /** append **/
+ if( fold(mode) == 'A' )
+ {
+ c = 'p';
+ goto addin;
+ }
+ save_v(vp);
+ if( cur_virt != INVALID )
+ {
+ first_virt = cur_virt + 1;
+ cursor(vp,cur_phys + 1);
+ ed_flush(vp->ed);
+ }
+ return(APPEND);
+
+ case 'I': /** insert at beginning of line **/
+ cur_virt = first_virt;
+ sync_cursor(vp);
+
+ case 'i': /** insert **/
+ if( fold(mode) == 'I' )
+ {
+ c = 'P';
+ goto addin;
+ }
+ save_v(vp);
+ if( cur_virt != INVALID )
+ {
+ vp->o_v_char = virtual[cur_virt];
+ first_virt = cur_virt--;
+ }
+ return(INSERT);
+
+ case 'C': /** change to eol **/
+ c = '$';
+ goto chgeol;
+
+ case 'c': /** change **/
+ if( mode )
+ c = vp->lastmotion;
+ else
+ c = getcount(vp,ed_getchar(vp->ed,-1));
+chgeol:
+ vp->lastmotion = c;
+ if( c == 'c' )
+ {
+ del_line(vp,GOOD);
+ return(APPEND);
+ }
+
+ if(!delmotion(vp, c, 'c'))
+ return(BAD);
+
+ if( mode == 'c' )
+ {
+ c = 'p';
+ trepeat = 1;
+ goto addin;
+ }
+ first_virt = cur_virt + 1;
+ return(APPEND);
+
+ case 'D': /** delete to eol **/
+ c = '$';
+ goto deleol;
+
+ case 'd': /** delete **/
+ if( mode )
+ c = vp->lastmotion;
+ else
+ c = getcount(vp,ed_getchar(vp->ed,-1));
+deleol:
+ vp->lastmotion = c;
+ if( c == 'd' )
+ {
+ del_line(vp,GOOD);
+ break;
+ }
+ if(!delmotion(vp, c, 'd'))
+ return(BAD);
+ if( cur_virt < last_virt )
+ ++cur_virt;
+ break;
+
+ case 'P':
+ if( p[0] == '\0' )
+ return(BAD);
+ if( cur_virt != INVALID )
+ {
+ i = virtual[cur_virt];
+ if(!is_print(i))
+ vp->ocur_virt = INVALID;
+ --cur_virt;
+ }
+
+ case 'p': /** print **/
+ if( p[0] == '\0' )
+ return(BAD);
+
+ if( mode != 's' && mode != 'c' )
+ {
+ save_v(vp);
+ if( c == 'P' )
+ {
+ /*** fix stored cur_virt ***/
+ ++vp->u_column;
+ }
+ }
+ if( mode == 'R' )
+ mode = REPLACE;
+ else
+ mode = APPEND;
+ savep = p;
+ for(i=0; i<trepeat; ++i)
+ {
+ while(c= *p++)
+ append(vp,c,mode);
+ p = savep;
+ }
+ break;
+
+ case 'R': /* Replace many chars **/
+ if( mode == 'R' )
+ {
+ c = 'P';
+ goto addin;
+ }
+ save_v(vp);
+ if( cur_virt != INVALID )
+ first_virt = cur_virt;
+ return(REPLACE);
+
+ case 'r': /** replace **/
+ if( mode )
+ c = *p;
+ else
+ if((c=getrchar(vp))==ESC)
+ return(GOOD);
+ *p = c;
+ save_v(vp);
+ while(trepeat--)
+ replace(vp,c, trepeat!=0);
+ return(GOOD);
+
+ case 'S': /** Substitute line - cc **/
+ c = 'c';
+ goto chgeol;
+
+ case 's': /** substitute **/
+ save_v(vp);
+ cdelete(vp,vp->repeat, BAD);
+ if( mode )
+ {
+ c = 'p';
+ trepeat = 1;
+ goto addin;
+ }
+ first_virt = cur_virt + 1;
+ return(APPEND);
+
+ case 'Y': /** Yank to end of line **/
+ c = '$';
+ goto yankeol;
+
+ case 'y': /** yank thru motion **/
+ if( mode )
+ c = vp->lastmotion;
+ else
+ c = getcount(vp,ed_getchar(vp->ed,-1));
+yankeol:
+ vp->lastmotion = c;
+ if( c == 'y' )
+ {
+ gencpy(yankbuf, virtual);
+ }
+ else if(!delmotion(vp, c, 'y'))
+ {
+ return(BAD);
+ }
+ break;
+
+ case 'x': /** delete repeat chars forward - dl **/
+ c = 'l';
+ goto deleol;
+
+ case 'X': /** delete repeat chars backward - dh **/
+ c = 'h';
+ goto deleol;
+
+ case '~': /** invert case and advance **/
+ if( cur_virt != INVALID )
+ {
+ save_v(vp);
+ i = INVALID;
+ while(trepeat-->0 && i!=cur_virt)
+ {
+ i = cur_virt;
+ c = virtual[cur_virt];
+#if SHOPT_MULTIBYTE
+ if((c&~STRIP)==0)
+#endif /* SHOPT_MULTIBYTE */
+ if( isupper(c) )
+ c = tolower(c);
+ else if( islower(c) )
+ c = toupper(c);
+ replace(vp,c, 1);
+ }
+ return(GOOD);
+ }
+ else
+ return(BAD);
+
+ default:
+ return(BAD);
+ }
+ refresh(vp,CONTROL);
+ return(GOOD);
+}
+
+
+#if SHOPT_MULTIBYTE
+ static int _isalph(register int v)
+ {
+#ifdef _lib_iswalnum
+ return(iswalnum(v) || v=='_');
+#else
+ return((v&~STRIP) || isalnum(v) || v=='_');
+#endif
+ }
+
+
+ static int _isblank(register int v)
+ {
+ return((v&~STRIP)==0 && isspace(v));
+ }
+
+ static int _ismetach(register int v)
+ {
+ return((v&~STRIP)==0 && ismeta(v));
+ }
+
+#endif /* SHOPT_MULTIBYTE */
+
+/*
+ * get a character, after ^V processing
+ */
+static int getrchar(register Vi_t *vp)
+{
+ register int c;
+ if((c=ed_getchar(vp->ed,1))== usrlnext)
+ c = ed_getchar(vp->ed,2);
+ return(c);
+}
diff --git a/src/cmd/ksh93/features/cmds b/src/cmd/ksh93/features/cmds
new file mode 100644
index 0000000..c759068
--- /dev/null
+++ b/src/cmd/ksh93/features/cmds
@@ -0,0 +1,4 @@
+cmd newgrp,test,id,wc,cut,logname,universe,pfexec,tput
+pth ed fail{
+ echo '#define _pth_ed "ed" /* ed not found on standard PATH */'
+}end
diff --git a/src/cmd/ksh93/features/dynamic b/src/cmd/ksh93/features/dynamic
new file mode 100644
index 0000000..33f2d13
--- /dev/null
+++ b/src/cmd/ksh93/features/dynamic
@@ -0,0 +1,12 @@
+cat{
+ #if SHOPT_DYNAMIC
+ #include <dlldefs.h>
+ #endif
+ #if !defined(SHOPT_FS_3D) && SHOPT_DYNAMIC
+ # define SHOPT_FS_3D 1
+ #endif /* !SHOPT_FS_3D */
+ #if SHOPT_FS_3D
+ # undef mount
+ # include <fs3d.h>
+ #endif /* SHOPT_FS_3D */
+}end
diff --git a/src/cmd/ksh93/features/externs b/src/cmd/ksh93/features/externs
new file mode 100644
index 0000000..bc26759
--- /dev/null
+++ b/src/cmd/ksh93/features/externs
@@ -0,0 +1,13 @@
+set prototyped
+hdr nc,exec_attr
+mem exception.name,_exception.name math.h
+lib setreuid,setregid,nice,fork,spawnveg,fchdir
+lib pathnative,pathposix,uwin_path,uwin_unpath,fts_notify
+lib memcntl sys/mman.h
+lib getexecuser,free_execattr exec_attr.h -lsecdb
+
+reference unistd.h
+
+extern nice int (int)
+extern setreuid int (uid_t,uid_t)
+extern setregid int (gid_t,gid_t)
diff --git a/src/cmd/ksh93/features/locale b/src/cmd/ksh93/features/locale
new file mode 100644
index 0000000..4155b53
--- /dev/null
+++ b/src/cmd/ksh93/features/locale
@@ -0,0 +1,27 @@
+hdr locale,wchar,wctype
+lib locale,localeconv,wctype,iswctype,iswblank
+lib wctrans,towctrans wctype.h
+typ wctrans_t wctype.h
+cat{
+ #if _PACKAGE_ast
+ # undef _hdr_locale
+ # define _hdr_locale 1
+ #else
+ # ifdef _hdr_locale
+ # include <locale.h>
+ # ifndef LC_MESSAGES
+ # define LC_MESSAGES LC_ALL
+ # endif /* LC_MESSAGES */
+ # endif /* _hdr_locale */
+ #endif /* _PACKAGE_ast */
+ #ifdef _hdr_locale
+ # ifdef _lib_localeconv
+ static struct lconv *lp;
+ # define GETDECIMAL(x) (((lp=localeconv()) && lp->decimal_point && *lp->decimal_point) ? *lp->decimal_point : '.' )
+ # else
+ # define GETDECIMAL(x) ('.')
+ # endif /* _lib_localeconv */
+ #else
+ # define GETDECIMAL(x) ('.')
+ #endif /* _hdr_locale */
+}end
diff --git a/src/cmd/ksh93/features/math.sh b/src/cmd/ksh93/features/math.sh
new file mode 100644
index 0000000..c2b6b3b
--- /dev/null
+++ b/src/cmd/ksh93/features/math.sh
@@ -0,0 +1,305 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+: generate the ksh math builtin table
+: include math.tab
+
+# @(#)math.sh (AT&T Research) 2010-10-26
+
+command=$0
+iffeflags="-n -v"
+iffehdrs="math.h"
+iffelibs="-lm"
+table=/dev/null
+
+eval $1
+shift
+table=$1
+
+: check long double
+
+eval `iffe $iffeflags -c "$cc" - typ long.double 2>&$stderr`
+
+: check ast_standards.h
+
+eval `iffe $iffeflags -F ast_standards.h -c "$cc" - tst use_ast_standards -lm 'note{' 'math.h needs ast_standards.h' '}end' 'link{' '#include <math.h>' '#ifndef isgreater' '#define isgreater(a,b) 0' '#endif' 'int main() { return isgreater(0.0,1.0); }' '}end'`
+case $_use_ast_standards in
+1) iffeflags="$iffeflags -F ast_standards.h" ;;
+esac
+eval `iffe $iffeflags -c "$cc" - tst use_ieeefp -lm 'note{' 'ieeefp.h plays nice' '}end' 'link{' '#include <math.h>' '#include <ieeefp.h>' 'int main() { return 0; }' '}end'`
+case $_use_ieeefp in
+1) iffehdrs="$iffehdrs ieeefp.h" ;;
+esac
+
+: read the table
+
+exec < $table
+ifs=$IFS
+libs=
+names=
+nums=
+while read type args name aka
+do case $type in
+ [fix]) names="$names $name"
+ libs="$libs,$name"
+ case $_typ_long_double in
+ 1) libs="$libs,${name}l" ;;
+ esac
+ for a in $aka
+ do case $a in
+ '{'*) break
+ ;;
+ *=*) IFS='=|'
+ set $a
+ IFS=$ifs
+ case ",$libs" in
+ *,$1,*) ;;
+ *) names="$names $1"
+ libs="$libs,$1"
+ case $_typ_long_double in
+ 1) libs="$libs,${1}l" ;;
+ esac
+ ;;
+ esac
+ shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case ",$nums" in
+ *,$1,*) ;;
+ *) nums="$nums,$1" ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ done
+ eval TYPE_$name='$type' ARGS_$name='$args' AKA_$name='$aka'
+ ;;
+ esac
+done
+
+: check the math library
+
+eval `iffe $iffeflags -c "$cc" - lib $libs $iffehdrs $iffelibs 2>&$stderr`
+lib=
+for name in $names
+do eval x='$'_lib_${name}l y='$'_lib_${name}
+ case $x in
+ 1) lib="$lib,${name}l" ;;
+ esac
+ case $y in
+ 1) case $x in
+ '') lib="$lib,${name}" ;;
+ esac
+ ;;
+ esac
+done
+eval `iffe $iffeflags -c "$cc" - dat,npt,mac $lib $iffehdrs $iffelibs 2>&$stderr`
+eval `iffe $iffeflags -c "$cc" - num $nums $iffehdrs $iffelibs 2>&$stderr`
+
+cat <<!
+#pragma prototyped
+
+/* : : generated by $command from $table : : */
+
+typedef Sfdouble_t (*Math_f)(Sfdouble_t,...);
+
+!
+case $_use_ast_standards in
+1) echo "#include <ast_standards.h>" ;;
+esac
+echo "#include <math.h>"
+case $_hdr_ieeefp in
+1) echo "#include <ieeefp.h>" ;;
+esac
+echo
+
+: generate the intercept functions and table entries
+
+nl='
+'
+ht=' '
+tab=
+for name in $names
+do eval x='$'_lib_${name}l y='$'_lib_${name} r='$'TYPE_${name} a='$'ARGS_${name} aka='$'AKA_${name}
+ case $r in
+ i) L=int R=1 ;;
+ x) L=Sfdouble_t R=4 ;;
+ *) L=Sfdouble_t R=0 ;;
+ esac
+ F=local_$name
+ case $x:$y in
+ 1:*) f=${name}l
+ t=Sfdouble_t
+ local=
+ ;;
+ *:1) f=${name}
+ t=double
+ local=$_typ_long_double
+ ;;
+ *) body=
+ for k in $aka
+ do case $body in
+ ?*) body="$body $k"
+ continue
+ ;;
+ esac
+ case $k in
+ '{'*) body=$k
+ ;;
+ *=*) IFS='=|'
+ set $k
+ IFS=$ifs
+ f=$1
+ shift
+ v=$*
+ eval x='$'_lib_${f}l y='$'_lib_${f}
+ case $x:$y in
+ 1:*) f=${f}l
+ ;;
+ *:1) ;;
+ *) continue
+ ;;
+ esac
+ y=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ eval x='$'_num_$1
+ case $x in
+ 1) case $y in
+ ?*) y="$y || " ;;
+ esac
+ y="${y}q == $1"
+ ;;
+ esac
+ shift
+ done
+ case $y in
+ '') ;;
+ *) r=int R=1
+ echo "static $r $F(Sfdouble_t a1) { $r q = $f(a1); return $y; }"
+ tab="$tab$nl$ht\"\\0${R}${a}${name}\",$ht(Math_f)${F},"
+ break
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $body in
+ ?*) code="static $L $F("
+ sep=
+ ta=
+ tc=
+ td=
+ for p in 1 2 3 4 5 6 7 8 9
+ do case $R:$p in
+ 4:2) T=int ;;
+ *) T=Sfdouble_t ;;
+ esac
+ code="$code${sep}$T a$p"
+ ta="$ta${sep}a$p"
+ tc="$tc${sep}0"
+ td="${td}$T a$p;"
+ case $a in
+ $p) break ;;
+ esac
+ sep=","
+ done
+ _it_links_=0
+ eval `iffe $iffeflags -c "$cc" - tst it_links_ note{ $F function links }end link{ "static $L $F($ta)$td${body}int main(){return $F($tc)!=0;}" }end sfio.h $iffehdrs $iffelibs 2>&$stderr`
+ case $_it_links_ in
+ 1) code="$code)$body"
+ echo "$code"
+ tab="$tab$nl$ht\"\\0${R}${a}${name}\",$ht(Math_f)${F},"
+ ;;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ case $r in
+ i) r=int ;;
+ *) r=$t ;;
+ esac
+ eval n='$'_npt_$f m='$'_mac_$f d='$'_dat_$f
+ case $d:$m:$n in
+ 1:*:*|*:1:*)
+ ;;
+ *:*:1) code="extern $r $f("
+ sep=
+ for p in 1 2 3 4 5 6 7
+ do code="$code${sep}$t"
+ case $a in
+ $p) break ;;
+ esac
+ sep=","
+ done
+ code="$code);"
+ echo "$code"
+ ;;
+ esac
+ case $local:$m:$n:$d in
+ 1:*:*:*|*:1:*:*|*:*:1:)
+ args=
+ code="static $L local_$f("
+ sep=
+ for p in 1 2 3 4 5 6 7 8 9
+ do args="$args${sep}a$p"
+ case $R:$p in
+ 4:2) T=int ;;
+ *) T=Sfdouble_t ;;
+ esac
+ code="$code${sep}$T a$p"
+ case $a in
+ $p) break ;;
+ esac
+ sep=","
+ done
+ code="$code){return $f($args);}"
+ echo "$code"
+ f=local_$f
+ ;;
+ esac
+ for x in $name $aka
+ do case $x in
+ '{'*) break
+ ;;
+ *=*) continue
+ ;;
+ esac
+ tab="$tab$nl$ht\"\\0${R}${a}${x}\",$ht(Math_f)$f,"
+ done
+done
+tab="$tab$nl$ht\"\",$ht$ht(Math_f)0"
+
+cat <<!
+
+/*
+ * first byte is two-digit octal number. Last digit is number of args
+ * first digit is 0 if return value is double, 1 for integer
+ */
+const struct mathtab shtab_math[] =
+{$tab
+};
+!
diff --git a/src/cmd/ksh93/features/options b/src/cmd/ksh93/features/options
new file mode 100755
index 0000000..c3f48b6
--- /dev/null
+++ b/src/cmd/ksh93/features/options
@@ -0,0 +1,47 @@
+# SHOPT_* option probe
+
+tst cross{
+ : check for shell magic #!
+ cat > /tmp/file$$ <<!
+ #! /bin/echo
+ exit 1
+ !
+ chmod 755 /tmp/file$$
+ if /tmp/file$$ > /dev/null
+ then echo "#define SHELLMAGIC 1"
+ fi
+ rm -f /tmp/file$$
+
+ option() # name value
+ {
+ case $2 in
+ 0) echo "#ifndef SHOPT_$1"
+ echo "# define SHOPT_$1 1"
+ echo "#endif"
+ ;;
+ *) echo "#undef SHOPT_$1"
+ ;;
+ esac
+ }
+
+ ls /dev/fd/9 9<&0 >/dev/null 2>&1
+ option DEVFD $?
+ exec 9<&-
+ case `echo a | tr a '\012' | wc -l` in
+ *1*) option MULTIBYTE 0 ;;
+ esac
+ test -x /bin/pfexec -o -x /usr/bin/pfexec
+ option PFSH $?
+ /bin/test ! -l . 2> /dev/null
+ option TEST_L $?
+ test -f /etc/ksh.kshrc -o -f /etc/bash.bashrc &&
+ option SYSRC 0
+ test -f /bin/universe && univ=`/bin/universe` > /dev/null 2>&1 -a ucb = "$univ"
+ option UCB $?
+}end
+
+cat{
+ #if !_PACKAGE_ast && ( (MB_LEN_MAX-1)<=0 || !defined(_lib_mbtowc) )
+ # undef SHOPT_MULTIBYTE
+ #endif
+}end
diff --git a/src/cmd/ksh93/features/poll b/src/cmd/ksh93/features/poll
new file mode 100644
index 0000000..da21990
--- /dev/null
+++ b/src/cmd/ksh93/features/poll
@@ -0,0 +1,157 @@
+ref -lsocket -lnsl
+hdr,sys poll,socket,netinet/in
+lib select,poll,socket
+lib htons,htonl sys/types.h sys/socket.h netinet/in.h
+lib getaddrinfo sys/types.h sys/socket.h netdb.h
+typ fd_set sys/socket.h sys/select.h
+typ socklen_t unistd.h sys/socket.h = unsigned int
+tst pipe_socketpair note{ use socketpair() for peekable pipe() }end execute{
+ #include <ast.h>
+ #include <signal.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #ifndef SHUT_RD
+ #define SHUT_RD 0
+ #endif
+ #ifndef SHUT_WR
+ #define SHUT_WR 1
+ #endif
+ static void handler(sig)
+ int sig;
+ {
+ _exit(0);
+ }
+ int main()
+ {
+ int n;
+ int pfd[2];
+ int sfd[2];
+ char buf[256];
+ pid_t pid;
+ static char msg[] = "hello world\n";
+ close(0);
+ if (pipe(pfd) < 0 ||
+ socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[1], SHUT_RD) < 0 ||
+ shutdown(sfd[0], SHUT_WR) < 0)
+ return(1);
+ if ((pid = fork()) < 0)
+ return(1);
+ if (pid)
+ {
+ close(pfd[1]);
+ close(sfd[1]);
+ wait(&n);
+ if (sfpkrd(pfd[0], buf, sizeof(buf), '\n', -1, 1) >= 0 ||
+ sfpkrd(sfd[0], buf, sizeof(buf), '\n', -1, 1) < 0)
+ return(1);
+ }
+ else
+ {
+ close(pfd[0]);
+ close(sfd[0]);
+ write(pfd[1], msg, sizeof(msg) - 1);
+ write(sfd[1], msg, sizeof(msg) - 1);
+ return(0);
+ }
+ close(pfd[0]);
+ close(sfd[0]);
+ signal(SIGPIPE, handler);
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[1], SHUT_RD) < 0 ||
+ shutdown(sfd[0], SHUT_WR) < 0)
+ return(1);
+ close(sfd[0]);
+ write(sfd[1], msg, sizeof(msg) - 1);
+ return(1);
+ }
+}end
+tst socketpair_devfd note{ /dev/fd/N handles socketpair() }end execute{
+ #include <ast.h>
+ #include <fs3d.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ int main()
+ {
+ int devfd;
+ int n;
+ int sfd[2];
+ fs3d(FS3D_OFF);
+ close(0);
+ open("/dev/null", O_RDONLY);
+ if ((n = open("/dev/fd/0", O_RDONLY)) < 0)
+ return(1);
+ close(n);
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[0], 1) < 0 ||
+ shutdown(sfd[1], 0) < 0)
+ return(1);
+ close(0);
+ dup(sfd[0]);
+ close(sfd[0]);
+ if ((n = open("/dev/fd/0", O_RDONLY)) < 0)
+ return(1);
+ return(0);
+ }
+}end
+tst socketpair_shutdown_mode note{ fchmod() after socketpair() shutdown() }end execute{
+ #include <ast.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+ int main()
+ {
+ int sfd[2];
+ struct stat st0;
+ struct stat st1;
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[0], 1) < 0 ||
+ shutdown(sfd[1], 0) < 0)
+ return(1);
+ if (fstat(sfd[0], &st0) < 0 || fstat(sfd[1], &st1) < 0)
+ return(1);
+ if ((st0.st_mode & (S_IRUSR|S_IWUSR)) == S_IRUSR &&
+ (st1.st_mode & (S_IRUSR|S_IWUSR)) == S_IWUSR)
+ return(1);
+ if (fchmod(sfd[0], S_IRUSR) < 0 ||
+ fstat(sfd[0], &st0) < 0 ||
+ (st0.st_mode & (S_IRUSR|S_IWUSR)) != S_IRUSR)
+ return(1);
+ if (fchmod(sfd[1], S_IWUSR) < 0 ||
+ fstat(sfd[1], &st1) < 0 ||
+ (st1.st_mode & (S_IRUSR|S_IWUSR)) != S_IWUSR)
+ return(1);
+ return(0);
+ }
+}end
+cat{
+ #pragma prototyped
+ #ifdef _lib_poll
+ # define poll _SYS_poll
+ #else
+ # undef _hdr_poll
+ # undef _sys_poll
+ #endif /* _lib_poll */
+ #ifdef _hdr_poll
+ # include <poll.h>
+ #else
+ # ifdef _sys_poll
+ # include <sys/poll.h>
+ # endif /* _sys_poll */
+ #endif /* _hdr_poll */
+ #ifdef _lib_poll
+ # undef poll
+ extern int poll(struct pollfd*,unsigned long,int);
+ #endif /* _lib_poll */
+ #ifdef _lib_select
+ # ifndef FD_ZERO
+ # define FD_ZERO(x) (*(x)=0)
+ # endif /* FD_ZERO */
+ # ifndef FD_SET
+ # define FD_SET(n,x) (*(x)|=(1L<<(n)))
+ # endif /* FD_SET */
+ # ifndef _typ_fd_set
+ typedef long fd_set;
+ # endif /*_typ_fd_set */
+ #endif /* _lib_select */
+}end
diff --git a/src/cmd/ksh93/features/rlimits b/src/cmd/ksh93/features/rlimits
new file mode 100644
index 0000000..ad7d2e1
--- /dev/null
+++ b/src/cmd/ksh93/features/rlimits
@@ -0,0 +1,3 @@
+hdr,sys resource,vlimit sys/time.h
+lib getrlimit,ulimit,vlimit
+typ rlim_t sys/types.h sys/time.h sys/resource.h
diff --git a/src/cmd/ksh93/features/setjmp b/src/cmd/ksh93/features/setjmp
new file mode 100644
index 0000000..a3504ee
--- /dev/null
+++ b/src/cmd/ksh93/features/setjmp
@@ -0,0 +1,18 @@
+lib sigsetjmp,_setjmp,_longjmp
+typ sigjmp_buf setjmp.h
+cat{
+ #undef sigsetjmp
+ #undef siglongjmp
+ #undef sigjmp_buf
+ #define sigjmp_buf jmp_buf
+ #ifdef _lib__setjmp
+ # define sigsetjmp(a,b) _setjmp(a)
+ #else
+ # define sigsetjmp(a,b) setjmp(a)
+ #endif /* _lib__setjmp */
+ #ifdef _lib__longjmp
+ # define siglongjmp(a,b) _longjmp(a,b)
+ #else
+ # define siglongjmp(a,b) longjmp(a,b)
+ #endif /* _lib__longjmp */
+}end
diff --git a/src/cmd/ksh93/features/sigfeatures b/src/cmd/ksh93/features/sigfeatures
new file mode 100644
index 0000000..58beaf8
--- /dev/null
+++ b/src/cmd/ksh93/features/sigfeatures
@@ -0,0 +1,49 @@
+lib sigblock,sigrelse,sigsetmask,sigprocmask,sigvec
+typ sigset_t ast.h signal.h
+mem sigvec.sv_mask signal.h
+cat{
+ #ifndef _mem_sigvec_sv_mask
+ # undef _lib_sigvec
+ #endif
+ #ifdef _lib_sigprocmask
+ # define sh_sigaction(s,action) do { sigset_t ss;\
+ sigemptyset(&ss); \
+ if(s) sigaddset(&ss,(s)); \
+ sigprocmask(action,&ss,0); \
+ }while(0)
+ # define sigrelease(s) sh_sigaction(s,SIG_UNBLOCK)
+ # define sigblock(s) sh_sigaction(s,SIG_BLOCK)
+ # define sig_begin() sh_sigaction(0,SIG_SETMASK)
+ #else
+ # ifndef _lib_sigblock
+ # define sigblock(s)
+ # endif
+ # ifdef _lib_sigsetmask
+ # define sigrelease(s) sigsetmask(0)
+ # define sig_begin() sigsetmask(0)
+ # else
+ # ifdef _lib_sigrelse
+ # define sigrelease sigrelse
+ # define sig_begin()
+ # else
+ # define sig_begin() (0)
+ # define sigrelease(s) (0)
+ # endif /* _lib_sigrelse */
+ # endif /* _lib_sigsetmask */
+ #endif /* _lib_sigprocmask */
+}end
+tst output{
+ #include <signal.h>
+ int main()
+ {
+ #ifdef SIGRTMIN
+ printf("#undef _SIGRTMIN\n");
+ printf("#define _SIGRTMIN %d\n", SIGRTMIN);
+ #endif
+ #ifdef SIGRTMAX
+ printf("#undef _SIGRTMAX\n");
+ printf("#define _SIGRTMAX %d\n", SIGRTMAX);
+ #endif
+ return 0;
+ }
+}end
diff --git a/src/cmd/ksh93/features/time b/src/cmd/ksh93/features/time
new file mode 100644
index 0000000..f8d2129
--- /dev/null
+++ b/src/cmd/ksh93/features/time
@@ -0,0 +1,35 @@
+hdr utime
+lib gettimeofday,setitimer
+mem timeval.tv_usec sys/time.h
+tst lib_2_timeofday note{ 2 arg gettimeofday() }end link{
+ #include <sys/types.h>
+ #include <sys/time.h>
+ int main()
+ {
+ struct timeval tv;
+ struct timezone tz;
+ return gettimeofday(&tv, &tz);
+ }
+}end
+tst lib_1_timeofday note{ 1 arg gettimeofday() }end link{
+ #include <sys/types.h>
+ #include <sys/time.h>
+ int main()
+ {
+ struct timeval tv;
+ return gettimeofday(&tv);
+ }
+}end
+cat{
+ #undef _def_time
+ #include <times.h>
+ #define _def_time 1
+ #undef timeofday
+ #if _lib_2_timeofday
+ #define timeofday(p) gettimeofday(p,(struct timezone*)0)
+ #else
+ #if _lib_1_timeofday
+ #define timeofday(p) gettimeofday(p)
+ #endif
+ #endif
+}end
diff --git a/src/cmd/ksh93/features/ttys b/src/cmd/ksh93/features/ttys
new file mode 100644
index 0000000..693dbd1
--- /dev/null
+++ b/src/cmd/ksh93/features/ttys
@@ -0,0 +1,3 @@
+hdr termios,termio,sgtty
+sys termios,termio,ioctl,bsdtty,nttyio,filio
+lib tcgetattr,tcgetpgrp termios.h
diff --git a/src/cmd/ksh93/fun/dirs b/src/cmd/ksh93/fun/dirs
new file mode 100755
index 0000000..0329970
--- /dev/null
+++ b/src/cmd/ksh93/fun/dirs
@@ -0,0 +1,108 @@
+#
+# DIRECTORY MANIPULATION FUNCTIONS, REPLACES CD
+#
+# Uses global parameters _push_max _push_top _push_stack
+integer _push_max=${CDSTACK-32} _push_top=${CDSTACK-32}
+unalias cd
+alias cd=_cd
+# Display directory stack -- $HOME displayed as ~
+function dirs
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ PS3=
+ select i in "$dir" "${_push_stack[@]}"
+ do :
+ done < /dev/null
+}
+
+# Change directory and put directory on front of stack
+function _cd
+{
+ typeset dir=
+ integer n=0 type=4
+ case $1 in
+ -|-1|2) # \cd -
+ n=_push_top type=1
+ ;;
+ -[1-9]*([0-9])) # \cd -n
+ n=_push_top+${1#-}-1 type=2
+ ;;
+ 1) # keep present directory
+ print -r - "$PWD"
+ return
+ ;;
+ [1-9]*([0-9])) # \cd n
+ n=_push_top+${1}-2 type=2
+ ;;
+ *) if ((_push_top <= 0))
+ then type=3 n=_push_max
+ fi
+ esac
+ if ((type<3))
+ then if ((n >= _push_max+1))
+ then print -u2 cd: Directory stack not that deep.
+ return 1
+ else dir=${_push_stack[n]}
+ fi
+ fi
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ \cd "${dir:-$@}" >| /dev/null || return 1
+ dir=${OLDPWD#$HOME/}
+ case $TERM in
+ 630)
+ print "\033[?${#PWD};2v$PWD\c"
+ ;;
+ esac
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ case $type in
+ 1) # swap first two elements
+ _push_stack[_push_top]=$dir
+ ;;
+ 2|3) # put $dir on top and shift down by one until top
+ integer i=_push_top
+ for dir in "$dir" "${_push_stack[@]}"
+ do ((i > n)) && break
+ _push_stack[i]=$dir
+ i=i+1
+ done
+ ;;
+ 4) # push name
+ _push_stack[_push_top=_push_top-1]=$dir
+ ;;
+ esac
+ print -r - "$PWD"
+}
+
+# Menu driven change directory command
+function mcd
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ PS3='Select by number or enter a name: '
+ select dir in "$dir" "${_push_stack[@]}"
+ do if _cd $REPLY
+ then return
+ fi
+ done
+}
diff --git a/src/cmd/ksh93/fun/popd b/src/cmd/ksh93/fun/popd
new file mode 100755
index 0000000..1bc9346
--- /dev/null
+++ b/src/cmd/ksh93/fun/popd
@@ -0,0 +1,111 @@
+#
+# DIRECTORY MANIPULATION FUNCTIONS PUSHD, POPD AND DIRS
+#
+# Uses global parameters _push_max _push_top _push_stack
+integer _push_max=100 _push_top=100
+# Display directory stack -- $HOME displayed as ~
+function dirs
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ print -r - "$dir ${_push_stack[@]}"
+}
+
+# Change directory and put directory on front of stack
+function pushd
+{
+ typeset dir= type=0
+ integer i
+ case $1 in
+ "") # pushd
+ if ((_push_top >= _push_max))
+ then print pushd: No other directory.
+ return 1
+ fi
+ type=1 dir=${_push_stack[_push_top]}
+ ;;
+ +[1-9]|+[1-9][0-9]) # pushd +n
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ type=2 dir=${_push_stack[i]}
+ ;;
+ *) if ((_push_top <= 0))
+ then print pushd: Directory stack overflow.
+ return 1
+ fi
+ esac
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "${dir:-$1}" > /dev/null || return 1
+ dir=${OLDPWD#$HOME/}
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ case $type in
+ 0) # pushd name
+ _push_stack[_push_top=_push_top-1]=$dir
+ ;;
+ 1) # pushd
+ _push_stack[_push_top]=$dir
+ ;;
+ 2) # push +n
+ type=${1#+} i=_push_top-1
+ set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
+ shift $type
+ for dir
+ do (((i=i+1) < _push_max)) || break
+ _push_stack[i]=$dir
+ done
+ esac
+ dirs
+}
+
+# Pops the top directory
+function popd
+{
+ typeset dir
+ if ((_push_top >= _push_max))
+ then print popd: Nothing to pop.
+ return 1
+ fi
+ case $1 in
+ "")
+ dir=${_push_stack[_push_top]}
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "$dir" || return 1
+ ;;
+ +[1-9]|+[1-9][0-9])
+ typeset savedir
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ while ((i > _push_top))
+ do _push_stack[i]=${_push_stack[i-1]}
+ i=i-1
+ done
+ ;;
+ *) print pushd: Bad directory.
+ return 1
+ esac
+ unset '_push_stack[_push_top]'
+ _push_top=_push_top+1
+ dirs
+}
diff --git a/src/cmd/ksh93/fun/pushd b/src/cmd/ksh93/fun/pushd
new file mode 100755
index 0000000..1bc9346
--- /dev/null
+++ b/src/cmd/ksh93/fun/pushd
@@ -0,0 +1,111 @@
+#
+# DIRECTORY MANIPULATION FUNCTIONS PUSHD, POPD AND DIRS
+#
+# Uses global parameters _push_max _push_top _push_stack
+integer _push_max=100 _push_top=100
+# Display directory stack -- $HOME displayed as ~
+function dirs
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ print -r - "$dir ${_push_stack[@]}"
+}
+
+# Change directory and put directory on front of stack
+function pushd
+{
+ typeset dir= type=0
+ integer i
+ case $1 in
+ "") # pushd
+ if ((_push_top >= _push_max))
+ then print pushd: No other directory.
+ return 1
+ fi
+ type=1 dir=${_push_stack[_push_top]}
+ ;;
+ +[1-9]|+[1-9][0-9]) # pushd +n
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ type=2 dir=${_push_stack[i]}
+ ;;
+ *) if ((_push_top <= 0))
+ then print pushd: Directory stack overflow.
+ return 1
+ fi
+ esac
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "${dir:-$1}" > /dev/null || return 1
+ dir=${OLDPWD#$HOME/}
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ case $type in
+ 0) # pushd name
+ _push_stack[_push_top=_push_top-1]=$dir
+ ;;
+ 1) # pushd
+ _push_stack[_push_top]=$dir
+ ;;
+ 2) # push +n
+ type=${1#+} i=_push_top-1
+ set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
+ shift $type
+ for dir
+ do (((i=i+1) < _push_max)) || break
+ _push_stack[i]=$dir
+ done
+ esac
+ dirs
+}
+
+# Pops the top directory
+function popd
+{
+ typeset dir
+ if ((_push_top >= _push_max))
+ then print popd: Nothing to pop.
+ return 1
+ fi
+ case $1 in
+ "")
+ dir=${_push_stack[_push_top]}
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "$dir" || return 1
+ ;;
+ +[1-9]|+[1-9][0-9])
+ typeset savedir
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ while ((i > _push_top))
+ do _push_stack[i]=${_push_stack[i-1]}
+ i=i-1
+ done
+ ;;
+ *) print pushd: Bad directory.
+ return 1
+ esac
+ unset '_push_stack[_push_top]'
+ _push_top=_push_top+1
+ dirs
+}
diff --git a/src/cmd/ksh93/include/argnod.h b/src/cmd/ksh93/include/argnod.h
new file mode 100644
index 0000000..2ed7302
--- /dev/null
+++ b/src/cmd/ksh93/include/argnod.h
@@ -0,0 +1,145 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef ARG_RAW
+/*
+ * struct to hold a word argument
+ * Written by David Korn
+ *
+ */
+
+#include <stak.h>
+
+struct ionod
+{
+ unsigned iofile;
+ char *ioname;
+ struct ionod *ionxt;
+ struct ionod *iolst;
+ char *iodelim;
+ off_t iooffset;
+ long iosize;
+ char *iovname;
+};
+
+struct comnod
+{
+ int comtyp;
+ struct ionod *comio;
+ struct argnod *comarg;
+ struct argnod *comset;
+ void *comnamp;
+ void *comnamq;
+ void *comstate;
+ int comline;
+};
+
+#define COMBITS 4
+#define COMMSK ((1<<COMBITS)-1)
+#define COMSCAN (01<<COMBITS)
+#define COMFIXED (02<<COMBITS)
+
+struct slnod /* struct for link list of stacks */
+{
+ struct slnod *slnext;
+ struct slnod *slchild;
+ Stak_t *slptr;
+ /* slpad aligns struct functnod = struct slnod + 1 on some architectures */
+ struct slnod *slpad;
+};
+
+/*
+ * This struct is use to hold $* lists and arrays
+ */
+
+struct dolnod
+{
+ int dolrefcnt; /* reference count */
+ int dolmax; /* size of dolval array */
+ int dolnum; /* number of elements */
+ int dolbot; /* current first element */
+ struct dolnod *dolnxt; /* used when list are chained */
+ char *dolval[1]; /* array of value pointers */
+};
+
+/*
+ * This struct is used to hold word arguments of variable size during
+ * parsing and during expansion. The flags indicate what processing
+ * is required on the argument.
+ */
+
+struct argnod
+{
+ union
+ {
+ struct argnod *ap;
+ char *cp;
+ } argnxt;
+ union
+ {
+ struct argnod *ap;
+ char *cp;
+ int len;
+ } argchn;
+ unsigned char argflag;
+ char argval[4];
+};
+
+
+
+/* The following should evaluate to the offset of argval in argnod */
+#define ARGVAL offsetof(struct argnod,argval[0])
+#define sh_argstr(ap) ((ap)->argflag&ARG_RAW?sh_fmtq((ap)->argval):(ap)->argval)
+#define ARG_SPARE 1
+
+
+/* legal argument flags */
+#define ARG_RAW 0x1 /* string needs no processing */
+#define ARG_MAKE 0x2 /* bit set during argument expansion */
+#define ARG_COMSUB 0x2 /* command sub */
+#define ARG_MAC 0x4 /* string needs macro expansion */
+#define ARG_EXP 0x8 /* string needs file expansion */
+#define ARG_ASSIGN 0x10 /* argument is an assignment */
+#define ARG_QUOTED 0x20 /* word contained quote characters */
+#define ARG_MESSAGE 0x40 /* contains international string */
+#define ARG_APPEND 0x80 /* for += assignment */
+/* The following can be passed as options to sh_macexpand() */
+#define ARG_ARITH 0x100 /* arithmetic expansion */
+#define ARG_OPTIMIZE 0x200 /* try to optimize */
+#define ARG_NOGLOB 0x400 /* no file name expansion */
+#define ARG_LET 0x800 /* processing let command arguments */
+#define ARG_ARRAYOK 0x1000 /* $x[sub] ==> ${x[sub]} */
+
+extern struct dolnod *sh_argcreate(char*[]);
+extern char *sh_argdolminus(void*);
+extern int sh_argopts(int,char*[],void*);
+
+
+extern const char e_heading[];
+extern const char e_off[];
+extern const char e_on[];
+extern const char e_sptbnl[];
+extern const char e_subst[];
+extern const char e_option[];
+extern const char e_exec[];
+extern const char e_devfdNN[];
+extern const char e_devfdstd[];
+
+#endif /* ARG_RAW */
diff --git a/src/cmd/ksh93/include/builtins.h b/src/cmd/ksh93/include/builtins.h
new file mode 100644
index 0000000..b9b4233
--- /dev/null
+++ b/src/cmd/ksh93/include/builtins.h
@@ -0,0 +1,202 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef SYSDECLARE
+
+#include <option.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+#include "shtable.h"
+
+#define SYSLOGIN (shgd->bltin_cmds)
+#define SYSEXEC (shgd->bltin_cmds+1)
+#define SYSSET (shgd->bltin_cmds+2)
+#define SYSTRUE (shgd->bltin_cmds+4)
+#define SYSCOMMAND (shgd->bltin_cmds+5)
+#define SYSCD (shgd->bltin_cmds+6)
+#define SYSBREAK (shgd->bltin_cmds+7)
+#define SYSCONT (shgd->bltin_cmds+8)
+#define SYSTYPESET (shgd->bltin_cmds+9)
+#define SYSTEST (shgd->bltin_cmds+10)
+#define SYSBRACKET (shgd->bltin_cmds+11)
+#define SYSLET (shgd->bltin_cmds+12)
+#define SYSEXPORT (shgd->bltin_cmds+13)
+#define SYSDOT (shgd->bltin_cmds+14)
+#define SYSRETURN (shgd->bltin_cmds+15)
+#if SHOPT_BASH
+# define SYSLOCAL (shgd->bltin_cmds+16)
+#else
+# define SYSLOCAL 0
+#endif
+
+/* entry point for shell special builtins */
+
+#if _BLD_shell && defined(__EXPORT__)
+# define extern __EXPORT__
+#endif
+
+extern int b_alias(int, char*[],Shbltin_t*);
+extern int b_break(int, char*[],Shbltin_t*);
+extern int b_dot_cmd(int, char*[],Shbltin_t*);
+extern int b_enum(int, char*[],Shbltin_t*);
+extern int b_exec(int, char*[],Shbltin_t*);
+extern int b_eval(int, char*[],Shbltin_t*);
+extern int b_return(int, char*[],Shbltin_t*);
+extern int B_login(int, char*[],Shbltin_t*);
+extern int b_true(int, char*[],Shbltin_t*);
+extern int b_false(int, char*[],Shbltin_t*);
+extern int b_readonly(int, char*[],Shbltin_t*);
+extern int b_set(int, char*[],Shbltin_t*);
+extern int b_shift(int, char*[],Shbltin_t*);
+extern int b_trap(int, char*[],Shbltin_t*);
+extern int b_typeset(int, char*[],Shbltin_t*);
+extern int b_unset(int, char*[],Shbltin_t*);
+extern int b_unalias(int, char*[],Shbltin_t*);
+
+/* The following are for job control */
+#if defined(SIGCLD) || defined(SIGCHLD)
+ extern int b_jobs(int, char*[],Shbltin_t*);
+ extern int b_kill(int, char*[],Shbltin_t*);
+# ifdef SIGTSTP
+ extern int b_bg(int, char*[],Shbltin_t*);
+# endif /* SIGTSTP */
+#endif
+
+/* The following utilities are built-in because of side-effects */
+extern int b_builtin(int, char*[],Shbltin_t*);
+extern int b_cd(int, char*[],Shbltin_t*);
+extern int b_command(int, char*[],Shbltin_t*);
+extern int b_getopts(int, char*[],Shbltin_t*);
+extern int b_hist(int, char*[],Shbltin_t*);
+extern int b_let(int, char*[],Shbltin_t*);
+extern int b_read(int, char*[],Shbltin_t*);
+extern int b_ulimit(int, char*[],Shbltin_t*);
+extern int b_umask(int, char*[],Shbltin_t*);
+#ifdef _cmd_universe
+ extern int b_universe(int, char*[],Shbltin_t*);
+#endif /* _cmd_universe */
+#if SHOPT_FS_3D
+ extern int b_vpath(int, char*[],Shbltin_t*);
+#endif /* SHOPT_FS_3D */
+extern int b_wait(int, char*[],Shbltin_t*);
+extern int b_whence(int, char*[],Shbltin_t*);
+
+extern int b_alarm(int, char*[],Shbltin_t*);
+extern int b_print(int, char*[],Shbltin_t*);
+extern int b_printf(int, char*[],Shbltin_t*);
+extern int b_pwd(int, char*[],Shbltin_t*);
+extern int b_sleep(int, char*[],Shbltin_t*);
+extern int b_test(int, char*[],Shbltin_t*);
+#if !SHOPT_ECHOPRINT
+ extern int B_echo(int, char*[],Shbltin_t*);
+#endif /* SHOPT_ECHOPRINT */
+
+#undef extern
+
+extern const char e_alrm1[];
+extern const char e_alrm2[];
+extern const char e_badfun[];
+extern const char e_baddisc[];
+extern const char e_nofork[];
+extern const char e_nosignal[];
+extern const char e_nolabels[];
+extern const char e_notimp[];
+extern const char e_nosupport[];
+extern const char e_badbase[];
+extern const char e_overlimit[];
+
+extern const char e_eneedsarg[];
+extern const char e_oneoperand[];
+extern const char e_toodeep[];
+extern const char e_badname[];
+extern const char e_badsyntax[];
+#ifdef _cmd_universe
+ extern const char e_nouniverse[];
+#endif /* _cmd_universe */
+extern const char e_histopen[];
+extern const char e_condition[];
+extern const char e_badrange[];
+extern const char e_trap[];
+extern const char e_direct[];
+extern const char e_defedit[];
+extern const char e_cneedsarg[];
+extern const char e_defined[];
+#if SHOPT_FS_3D
+ extern const char e_cantset[];
+ extern const char e_cantget[];
+ extern const char e_mapping[];
+ extern const char e_versions[];
+#endif /* SHOPT_FS_3D */
+
+/* for option parsing */
+extern const char sh_set[];
+extern const char sh_optalarm[];
+extern const char sh_optalias[];
+extern const char sh_optbreak[];
+extern const char sh_optbuiltin[];
+extern const char sh_optcd[];
+extern const char sh_optcommand[];
+extern const char sh_optcont[];
+extern const char sh_optdot[];
+#ifndef ECHOPRINT
+ extern const char sh_optecho[];
+#endif /* !ECHOPRINT */
+extern const char sh_opteval[];
+extern const char sh_optexec[];
+extern const char sh_optexit[];
+extern const char sh_optexport[];
+extern const char sh_optgetopts[];
+extern const char sh_optbg[];
+extern const char sh_optdisown[];
+extern const char sh_optfg[];
+extern const char sh_opthist[];
+extern const char sh_optjobs[];
+extern const char sh_optkill[];
+extern const char sh_optksh[];
+extern const char sh_optlet[];
+extern const char sh_optprint[];
+extern const char sh_optprintf[];
+extern const char sh_optpwd[];
+extern const char sh_optread[];
+extern const char sh_optreadonly[];
+extern const char sh_optreturn[];
+extern const char sh_optset[];
+extern const char sh_optshift[];
+extern const char sh_optsleep[];
+extern const char sh_opttrap[];
+extern const char sh_opttypeset[];
+extern const char sh_optulimit[];
+extern const char sh_optumask[];
+extern const char sh_optunalias[];
+extern const char sh_optwait[];
+#ifdef _cmd_universe
+ extern const char sh_optuniverse[];
+#endif /* _cmd_universe */
+extern const char sh_optunset[];
+#if SHOPT_FS_3D
+ extern const char sh_optvpath[];
+ extern const char sh_optvmap[];
+#endif /* SHOPT_FS_3D */
+extern const char sh_optwhence[];
+#endif /* SYSDECLARE */
+
+extern const char e_dict[];
+
diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h
new file mode 100644
index 0000000..dd80552
--- /dev/null
+++ b/src/cmd/ksh93/include/defs.h
@@ -0,0 +1,509 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Shell interface private definitions
+ *
+ */
+#ifndef defs_h_defined
+#define defs_h_defined
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include "FEATURE/externs"
+#include "FEATURE/options"
+#include <cdt.h>
+#include <history.h>
+#include "fault.h"
+#include "argnod.h"
+#include "name.h"
+#include <ctype.h>
+
+#ifndef pointerof
+#define pointerof(x) ((void*)((char*)0+(x)))
+#endif
+
+#define Empty ((char*)(e_sptbnl+3))
+
+#define env_change() (++ast.env_serial)
+#if SHOPT_ENV
+# include <env.h>
+#else
+# define Env_t void
+# define sh_envput(e,p) env_change()
+# define env_delete(e,p) env_change()
+#endif
+
+extern char* sh_getenv(const char*);
+extern char* sh_setenviron(const char*);
+
+/*
+ * note that the first few fields have to be the same as for
+ * Shscoped_t in <shell.h>
+ */
+
+
+struct sh_scoped
+{
+ struct sh_scoped *prevst; /* pointer to previous state */
+ int dolc;
+ char **dolv;
+ char *cmdname;
+ char *filename;
+ char *funname;
+ int lineno;
+ Dt_t *save_tree; /* var_tree for calling function */
+ struct sh_scoped *self; /* pointer to copy of this scope*/
+ Dt_t *var_local; /* local level variables for name() */
+ struct slnod *staklist; /* link list of function stacks */
+ int states;
+ int breakcnt;
+ int execbrk;
+ int loopcnt;
+ int firstline;
+ int32_t optindex;
+ int32_t optnum;
+ int32_t tmout; /* value for TMOUT */
+ short optchar;
+ short opterror;
+ int ioset;
+ unsigned short trapmax;
+ char *trap[SH_DEBUGTRAP+1];
+ char **trapcom;
+ char **otrapcom;
+ void *timetrap;
+ struct Ufunction *real_fun; /* current 'function name' function */
+};
+
+struct limits
+{
+ long arg_max; /* max arg+env exec() size */
+ int open_max; /* maximum number of file descriptors */
+ int clk_tck; /* number of ticks per second */
+ int child_max; /* maxumum number of children */
+ int ngroups_max; /* maximum number of process groups */
+ unsigned char posix_version; /* posix version number */
+ unsigned char posix_jobcontrol;/* non-zero for job control systems */
+ unsigned char fs3d; /* non-zero for 3-d file system */
+};
+
+#ifndef SH_wait_f_defined
+ typedef int (*Shwait_f)(int, long, int);
+# define SH_wait_f_defined
+#endif
+
+
+struct shared
+{
+ struct limits lim;
+ uid_t userid;
+ uid_t euserid;
+ gid_t groupid;
+ gid_t egroupid;
+ pid_t pid;
+ int32_t ppid;
+ unsigned char sigruntime[2];
+ Namval_t *bltin_nodes;
+ Namval_t *bltin_cmds;
+ History_t *hist_ptr;
+ char *shpath;
+ char *user;
+ char **sigmsg;
+ char *rcfile;
+ char **login_files;
+ void *ed_context;
+ void *init_context;
+ void *job_context;
+ int *stats;
+ int bltin_nnodes; /* number of bltins nodes */
+ int sigmax;
+ int nforks;
+ Shwait_f waitevent;
+};
+
+#define _SH_PRIVATE \
+ struct shared *gd; /* global data */ \
+ struct sh_scoped st; /* scoped information */ \
+ Stk_t *stk; /* stack poiter */ \
+ Sfio_t *heredocs; /* current here-doc temp file */ \
+ Sfio_t *funlog; /* for logging function definitions */ \
+ int **fdptrs; /* pointer to file numbers */ \
+ int savexit; \
+ char *lastarg; \
+ char *lastpath; /* last alsolute path found */ \
+ int path_err; /* last error on path search */ \
+ Dt_t *track_tree; /* for tracked aliases*/ \
+ Dt_t *var_base; /* global level variables */ \
+ Namval_t *namespace; /* current active namespace*/ \
+ Namval_t *last_table; /* last table used in last nv_open */ \
+ Namval_t *prev_table; /* previous table used in nv_open */ \
+ Sfio_t *outpool; /* ouput stream pool */ \
+ long timeout; /* read timeout */ \
+ short curenv; /* current subshell number */ \
+ short jobenv; /* subshell number for jobs */ \
+ int infd; /* input file descriptor */ \
+ short nextprompt; /* next prompt is PS<nextprompt> */ \
+ short poolfiles; \
+ Namval_t *posix_fun; /* points to last name() function */ \
+ char *outbuff; /* pointer to output buffer */ \
+ char *errbuff; /* pointer to stderr buffer */ \
+ char *prompt; /* pointer to prompt string */ \
+ char *shname; /* shell name */ \
+ char *comdiv; /* points to sh -c argument */ \
+ char *prefix; /* prefix for compound assignment */ \
+ sigjmp_buf *jmplist; /* longjmp return stack */ \
+ char *fifo; /* fifo name for process sub */ \
+ int oldexit; \
+ pid_t bckpid; /* background process id */ \
+ pid_t cpid; \
+ pid_t spid; /* subshell process id */ \
+ pid_t pipepid; \
+ pid_t outpipepid; \
+ int topfd; \
+ int savesig; \
+ unsigned char *sigflag; /* pointer to signal states */ \
+ char openmatch; \
+ char intrap; \
+ char login_sh; \
+ char lastbase; \
+ char forked; \
+ char binscript; \
+ char deftype; \
+ char funload; \
+ char used_pos; /* used postional parameter */\
+ char universe; \
+ char winch; \
+ char inarith; /* set when in ((...)) */ \
+ char indebug; /* set when in debug trap */ \
+ unsigned char ignsig; /* ignored signal in subshell */ \
+ unsigned char lastsig; /* last signal received */ \
+ char pathinit; /* pathinit called from subshell */ \
+ char comsub; /* set when in $() comsub */ \
+ char subshare; /* set when in ${..} comsub */ \
+ char toomany; /* set when out of fd's */ \
+ char instance; /* in set_instance */ \
+ char decomma; /* decimal_point=',' */ \
+ char redir0; /* redirect of 0 */ \
+ char *readscript; /* set before reading a script */ \
+ int subdup; /* bitmask for dups of 1 */ \
+ int *inpipe; /* input pipe pointer */ \
+ int *outpipe; /* output pipe pointer */ \
+ int cpipe[3]; \
+ int coutpipe; \
+ int inuse_bits; \
+ struct argnod *envlist; \
+ struct dolnod *arglist; \
+ int fn_depth; \
+ int fn_reset; \
+ int dot_depth; \
+ int hist_depth; \
+ int xargmin; \
+ int xargmax; \
+ int xargexit; \
+ int nenv; \
+ mode_t mask; \
+ Env_t *env; \
+ void *init_context; \
+ void *mac_context; \
+ void *lex_context; \
+ void *arg_context; \
+ void *job_context; \
+ void *pathlist; \
+ void *defpathlist; \
+ void *cdpathlist; \
+ char **argaddr; \
+ void *optlist; \
+ struct sh_scoped global; \
+ struct checkpt checkbase; \
+ Shinit_f userinit; \
+ Shbltin_f bltinfun; \
+ Shbltin_t bltindata; \
+ char *cur_line; \
+ int offsets[10]; \
+ Sfio_t **sftable; \
+ unsigned char *fdstatus; \
+ const char *pwd; \
+ void *jmpbuffer; \
+ void *mktype; \
+ Sfio_t *strbuf; \
+ Sfio_t *strbuf2; \
+ Dt_t *first_root; \
+ Dt_t *prefix_root; \
+ Dt_t *last_root; \
+ Dt_t *prev_root; \
+ Dt_t *fpathdict; \
+ Dt_t *typedict; \
+ Dt_t *inpool; \
+ Dt_t *transdict; \
+ char ifstable[256]; \
+ unsigned long test; \
+ Shopt_t offoptions; \
+ Shopt_t glob_options; \
+ Namval_t *typeinit; \
+ Namfun_t nvfun; \
+ char *mathnodes; \
+ void *coshell; \
+ struct Regress_s*regress;
+
+#include <shell.h>
+
+#include "shtable.h"
+#include "regress.h"
+
+/* error exits from various parts of shell */
+#define NIL(type) ((type)0)
+
+#define new_of(type,x) ((type*)malloc((unsigned)sizeof(type)+(x)))
+
+#define exitset() (sh.savexit=sh.exitval)
+
+#ifndef SH_DICT
+#define SH_DICT (void*)e_dict
+#endif
+
+#ifndef SH_CMDLIB_DIR
+#define SH_CMDLIB_DIR "/opt/ast/bin"
+#endif
+
+/* states */
+/* low numbered states are same as options */
+#define SH_NOFORK 0 /* set when fork not necessary */
+#define SH_FORKED 7 /* set when process has been forked */
+#define SH_PROFILE 8 /* set when processing profiles */
+#define SH_NOALIAS 9 /* do not expand non-exported aliases */
+#define SH_NOTRACK 10 /* set to disable sftrack() function */
+#define SH_STOPOK 11 /* set for stopable builtins */
+#define SH_GRACE 12 /* set for timeout grace period */
+#define SH_TIMING 13 /* set while timing pipelines */
+#define SH_DEFPATH 14 /* set when using default path */
+#define SH_INIT 15 /* set when initializing the shell */
+#define SH_TTYWAIT 16 /* waiting for keyboard input */
+#define SH_FCOMPLETE 17 /* set for filename completion */
+#define SH_PREINIT 18 /* set with SH_INIT before parsing options */
+#define SH_COMPLETE 19 /* set for command completion */
+
+#define SH_BASH 41
+#define SH_BRACEEXPAND 42
+#define SH_POSIX 46
+#define SH_MULTILINE 47
+
+#define SH_NOPROFILE 78
+#define SH_NOUSRPROFILE 79
+#define SH_LOGIN_SHELL 67
+#define SH_COMMANDLINE 0x100
+#define SH_BASHEXTRA 0x200
+#define SH_BASHOPT 0x400
+
+#define SH_ID "ksh" /* ksh id */
+#define SH_STD "sh" /* standard sh id */
+
+/* defines for sh_type() */
+
+#define SH_TYPE_SH 001
+#define SH_TYPE_KSH 002
+#define SH_TYPE_BASH 004
+#define SH_TYPE_LOGIN 010
+#define SH_TYPE_PROFILE 020
+#define SH_TYPE_RESTRICTED 040
+
+#if SHOPT_BASH
+# ifndef SHOPT_HISTEXPAND
+# define SHOPT_HISTEXPAND 1
+# endif
+/*
+ * define for all the bash options
+ */
+# define SH_CDABLE_VARS 51
+# define SH_CDSPELL 52
+# define SH_CHECKHASH 53
+# define SH_CHECKWINSIZE 54
+# define SH_CMDHIST 55
+# define SH_DOTGLOB 56
+# define SH_EXECFAIL 57
+# define SH_EXPAND_ALIASES 58
+# define SH_EXTGLOB 59
+# define SH_HOSTCOMPLETE 63
+# define SH_HUPONEXIT 64
+# define SH_INTERACTIVE_COMM 65
+# define SH_LITHIST 66
+# define SH_MAILWARN 68
+# define SH_NOEMPTYCMDCOMPL 69
+# define SH_NOCASEGLOB 70
+# define SH_NULLGLOB 71
+# define SH_PHYSICAL 45
+# define SH_PROGCOMP 72
+# define SH_PROMPTVARS 73
+# define SH_RESTRICTED2 74
+# define SH_SHIFT_VERBOSE 75
+# define SH_SOURCEPATH 76
+# define SH_XPG_ECHO 77
+#endif
+
+#if SHOPT_HISTEXPAND
+# define SH_HISTAPPEND 60
+# define SH_HISTEXPAND 43
+# define SH_HISTORY2 44
+# define SH_HISTREEDIT 61
+# define SH_HISTVERIFY 62
+#endif
+
+#ifndef PIPE_BUF
+# define PIPE_BUF 512
+#endif
+
+#if SHOPT_PFSH && ( !_lib_getexecuser || !_lib_free_execattr )
+# undef SHOPT_PFSH
+#endif
+
+#define MATCH_MAX 64
+
+#define SH_READEVAL 0x4000 /* for sh_eval */
+#define SH_FUNEVAL 0x10000 /* for sh_eval for function load */
+
+extern struct shared *shgd;
+extern Shell_t *nv_shell(Namval_t*);
+extern int sh_addlib(Shell_t*,void*);
+extern void sh_applyopts(Shell_t*,Shopt_t);
+extern char **sh_argbuild(Shell_t*,int*,const struct comnod*,int);
+extern struct dolnod *sh_argfree(Shell_t *, struct dolnod*,int);
+extern struct dolnod *sh_argnew(Shell_t*,char*[],struct dolnod**);
+extern void *sh_argopen(Shell_t*);
+extern struct argnod *sh_argprocsub(Shell_t*,struct argnod*);
+extern void sh_argreset(Shell_t*,struct dolnod*,struct dolnod*);
+extern Namval_t *sh_assignok(Namval_t*,int);
+extern struct dolnod *sh_arguse(Shell_t*);
+extern char *sh_checkid(char*,char*);
+extern void sh_chktrap(Shell_t*);
+extern void sh_deparse(Sfio_t*,const Shnode_t*,int);
+extern int sh_debug(Shell_t *shp,const char*,const char*,const char*,char *const[],int);
+extern int sh_echolist(Shell_t*,Sfio_t*, int, char**);
+extern struct argnod *sh_endword(Shell_t*,int);
+extern char **sh_envgen(void);
+#if SHOPT_ENV
+extern void sh_envput(Env_t*, Namval_t*);
+#endif
+extern void sh_envnolocal(Namval_t*,void*);
+extern Sfdouble_t sh_arith(Shell_t*,const char*);
+extern void *sh_arithcomp(Shell_t *,char*);
+extern pid_t sh_fork(Shell_t*,int,int*);
+extern pid_t _sh_fork(Shell_t*,pid_t, int ,int*);
+extern char *sh_mactrim(Shell_t*,char*,int);
+extern int sh_macexpand(Shell_t*,struct argnod*,struct argnod**,int);
+extern int sh_macfun(Shell_t*,const char*,int);
+extern void sh_machere(Shell_t*,Sfio_t*, Sfio_t*, char*);
+extern void *sh_macopen(Shell_t*);
+extern char *sh_macpat(Shell_t*,struct argnod*,int);
+extern Sfdouble_t sh_mathfun(Shell_t*, void*, int, Sfdouble_t*);
+extern int sh_outtype(Shell_t*, Sfio_t*);
+extern char *sh_mactry(Shell_t*,char*);
+extern int sh_mathstd(const char*);
+extern void sh_printopts(Shopt_t,int,Shopt_t*);
+extern int sh_readline(Shell_t*,char**,int,int,long);
+extern Sfio_t *sh_sfeval(char*[]);
+extern void sh_setmatch(Shell_t*,const char*,int,int,int[],int);
+extern Dt_t *sh_subaliastree(int);
+extern void sh_scope(Shell_t*, struct argnod*, int);
+extern Namval_t *sh_scoped(Shell_t*, Namval_t*);
+extern Dt_t *sh_subfuntree(int);
+extern void sh_subjobcheck(pid_t);
+extern int sh_subsavefd(int);
+extern void sh_subtmpfile(Shell_t*);
+extern char *sh_substitute(const char*,const char*,char*);
+extern void sh_timetraps(Shell_t*);
+extern const char *_sh_translate(const char*);
+extern int sh_trace(Shell_t*,char*[],int);
+extern void sh_trim(char*);
+extern int sh_type(const char*);
+extern void sh_unscope(Shell_t*);
+extern void sh_utol(const char*, char*);
+extern int sh_whence(char**,int);
+#if SHOPT_COSHELL
+ extern int sh_coaddfile(Shell_t*,char*);
+ extern int sh_copipe(Shell_t*, int[], int);
+ extern int sh_coaccept(Shell_t*,int[],int);
+#endif /* SHOPT_COSHELL */
+#if SHOPT_NAMESPACE
+ extern Namval_t *sh_fsearch(Shell_t*,const char *,int);
+#endif /* SHOPT_NAMESPACE */
+
+#ifndef ERROR_dictionary
+# define ERROR_dictionary(s) (s)
+#endif
+#define sh_translate(s) _sh_translate(ERROR_dictionary(s))
+
+#define WBITS (sizeof(long)*8)
+#define WMASK (0xff)
+
+#define is_option(s,x) ((s)->v[((x)&WMASK)/WBITS] & (1L << ((x) % WBITS)))
+#define on_option(s,x) ((s)->v[((x)&WMASK)/WBITS] |= (1L << ((x) % WBITS)))
+#define off_option(s,x) ((s)->v[((x)&WMASK)/WBITS] &= ~(1L << ((x) % WBITS)))
+#define sh_isoption(x) is_option(&sh.options,x)
+#define sh_onoption(x) on_option(&sh.options,x)
+#define sh_offoption(x) off_option(&sh.options,x)
+
+
+#define sh_state(x) ( 1<<(x))
+#define sh_isstate(x) (sh.st.states&sh_state(x))
+#define sh_onstate(x) (sh.st.states |= sh_state(x))
+#define sh_offstate(x) (sh.st.states &= ~sh_state(x))
+#define sh_getstate() (sh.st.states)
+#define sh_setstate(x) (sh.st.states = (x))
+
+#define sh_sigcheck(shp) do{if(shp->trapnote&SH_SIGSET)sh_exit(SH_EXITSIG);} while(0)
+
+extern int32_t sh_mailchk;
+extern const char e_dict[];
+
+/* sh_printopts() mode flags -- set --[no]option by default */
+
+#define PRINT_VERBOSE 0x01 /* option on|off list */
+#define PRINT_ALL 0x02 /* list unset options too */
+#define PRINT_NO_HEADER 0x04 /* omit listing header */
+#define PRINT_SHOPT 0x08 /* shopt -s|-u */
+#define PRINT_TABLE 0x10 /* table of all options */
+
+#ifdef SHOPT_STATS
+ /* performance statistics */
+# define STAT_ARGHITS 0
+# define STAT_ARGEXPAND 1
+# define STAT_COMSUB 2
+# define STAT_FORKS 3
+# define STAT_FUNCT 4
+# define STAT_GLOBS 5
+# define STAT_READS 6
+# define STAT_NVHITS 7
+# define STAT_NVOPEN 8
+# define STAT_PATHS 9
+# define STAT_SVFUNCT 10
+# define STAT_SCMDS 11
+# define STAT_SPAWN 12
+# define STAT_SUBSHELL 13
+ extern const Shtable_t shtab_stats[];
+# define sh_stats(x) (shgd->stats[(x)]++)
+#else
+# define sh_stats(x)
+#endif /* SHOPT_STATS */
+
+
+#endif
diff --git a/src/cmd/ksh93/include/edit.h b/src/cmd/ksh93/include/edit.h
new file mode 100644
index 0000000..239158e
--- /dev/null
+++ b/src/cmd/ksh93/include/edit.h
@@ -0,0 +1,286 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SEARCHSIZE
+/*
+ * edit.h - common data structure for vi and emacs edit options
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#define SEARCHSIZE 80
+
+#include "FEATURE/options"
+#include "FEATURE/locale"
+#if !SHOPT_VSH && !SHOPT_ESH
+# define ed_winsize() (SEARCHSIZE)
+#else
+
+#if !KSHELL
+# include <setjmp.h>
+# include <sig.h>
+# include <ctype.h>
+#endif /* KSHELL */
+
+#include "FEATURE/setjmp"
+#include "terminal.h"
+
+#define STRIP 0377
+#define LOOKAHEAD 80
+
+#if SHOPT_MULTIBYTE
+# ifndef ESS_MAXCHAR
+# include "national.h"
+# endif /* ESS_MAXCHAR */
+ typedef wchar_t genchar;
+# define CHARSIZE (sizeof(wchar_t)<=2?3:sizeof(wchar_t))
+#else
+ typedef char genchar;
+# define CHARSIZE 1
+#endif /* SHOPT_MULTIBYTE */
+
+#define TABSIZE 8
+#define PRSIZE 160
+#define MAXLINE 1024 /* longest edit line permitted */
+
+typedef struct _edit_pos
+{
+ unsigned short line;
+ unsigned short col;
+} Edpos_t;
+
+#if SHOPT_EDPREDICT
+typedef struct Histmatch
+{
+ struct Histmatch *next;
+ int index;
+ short len;
+ short count;
+ char data[1];
+} Histmatch_t;
+#endif /* SHOPT_EDPREDICT */
+
+
+
+typedef struct edit
+{
+ sigjmp_buf e_env;
+ int e_intr;
+ int e_kill;
+ int e_erase;
+ int e_werase;
+ int e_eof;
+ int e_lnext;
+ int e_fchar;
+ int e_plen; /* length of prompt string */
+ char e_crlf; /* zero if cannot return to beginning of line */
+ char e_nocrnl; /* don't put a new-line with ^L */
+ char e_keytrap; /* set when in keytrap */
+ int e_llimit; /* line length limit */
+ int e_hline; /* current history line number */
+ int e_hloff; /* line number offset for command */
+ int e_hismin; /* minimum history line number */
+ int e_hismax; /* maximum history line number */
+ int e_raw; /* set when in raw mode or alt mode */
+ int e_cur; /* current line position */
+ int e_eol; /* end-of-line position */
+ int e_pcur; /* current physical line position */
+ int e_peol; /* end of physical line position */
+ int e_mode; /* edit mode */
+ int e_lookahead; /* index in look-ahead buffer */
+ int e_repeat;
+ int e_saved;
+ int e_fcol; /* first column */
+ int e_ucol; /* column for undo */
+ int e_wsize; /* width of display window */
+ char *e_outbase; /* pointer to start of output buffer */
+ char *e_outptr; /* pointer to position in output buffer */
+ char *e_outlast; /* pointer to end of output buffer */
+ genchar *e_inbuf; /* pointer to input buffer */
+ char *e_prompt; /* pointer to buffer containing the prompt */
+ genchar *e_ubuf; /* pointer to the undo buffer */
+ genchar *e_killbuf; /* pointer to delete buffer */
+ char e_search[SEARCHSIZE]; /* search string */
+ genchar *e_Ubuf; /* temporary workspace buffer */
+ genchar *e_physbuf; /* temporary workspace buffer */
+ int e_lbuf[LOOKAHEAD];/* pointer to look-ahead buffer */
+ int e_fd; /* file descriptor */
+ int e_ttyspeed; /* line speed, also indicates tty parms are valid */
+ int e_tabcount;
+#ifdef _hdr_utime
+ ino_t e_tty_ino;
+ dev_t e_tty_dev;
+ char *e_tty;
+#endif
+#if SHOPT_OLDTERMIO
+ char e_echoctl;
+ char e_tcgeta;
+ struct termio e_ott;
+#endif
+#if SHOPT_MULTIBYTE
+ int e_curchar;
+ int e_cursize;
+#endif
+ int *e_globals; /* global variables */
+ genchar *e_window; /* display window image */
+ char e_inmacro; /* processing macro expansion */
+#if KSHELL
+ char e_vi_insert[2]; /* for sh_keytrap */
+ int32_t e_col; /* for sh_keytrap */
+#else
+ char e_prbuff[PRSIZE]; /* prompt buffer */
+#endif /* KSHELL */
+ struct termios e_ttyparm; /* initial tty parameters */
+ struct termios e_nttyparm; /* raw tty parameters */
+ struct termios e_savetty; /* saved terminal state */
+ int e_savefd; /* file descriptor for saved terminal state */
+ char e_macro[4]; /* macro buffer */
+ void *e_vi; /* vi specific data */
+ void *e_emacs; /* emacs specific data */
+ Shell_t *sh; /* interpreter pointer */
+ char *e_stkptr; /* saved stack pointer */
+ int e_stkoff; /* saved stack offset */
+ char **e_clist; /* completion list after <ESC>= */
+ int e_nlist; /* number of elements on completion list */
+ int e_multiline; /* allow multiple lines for editing */
+ int e_winsz; /* columns in window */
+ Edpos_t e_curpos; /* cursor line and column */
+ Namval_t *e_default; /* variable containing default value */
+ Namval_t *e_term; /* TERM variable */
+ char e_termname[80]; /* terminal name */
+#if SHOPT_EDPREDICT
+ Histmatch_t **hlist;
+ Histmatch_t *hfirst;
+ unsigned short nhlist;
+ unsigned short hoff;
+ unsigned short hmax;
+ char *hpat;
+ char *hstak;
+#endif /* SHOPT_EDPREDICT */
+} Edit_t;
+
+#undef MAXWINDOW
+#define MAXWINDOW 300 /* maximum width window */
+#define FAST 2
+#define SLOW 1
+#define ESC cntl('[')
+#define UEOF -2 /* user eof char synonym */
+#define UINTR -3 /* user intr char synonym */
+#define UERASE -4 /* user erase char synonym */
+#define UKILL -5 /* user kill char synonym */
+#define UWERASE -6 /* user word erase char synonym */
+#define ULNEXT -7 /* user next literal char synonym */
+
+#if ( 'a' == 97) /* ASCII? */
+# define cntl(x) (x&037)
+#else
+# define cntl(c) (c=='D'?55:(c=='E'?45:(c=='F'?46:(c=='G'?'\a':(c=='H'?'\b': \
+ (c=='I'?'\t':(c=='J'?'\n':(c=='T'?60:(c=='U'?61:(c=='V'?50: \
+ (c=='W'?38:(c=='Z'?63:(c=='['?39:(c==']'?29: \
+ (c<'J'?c+1-'A':(c+10-'J'))))))))))))))))
+#endif
+
+#if !KSHELL
+# define STRIP 0377
+# define GMACS 1
+# define EMACS 2
+# define VIRAW 4
+# define EDITVI 8
+# define NOHIST 16
+# define EDITMASK 15
+# define is_option(m) (opt_flag&(m))
+ extern char opt_flag;
+# ifdef SYSCALL
+# define read(fd,buff,n) syscall(3,fd,buff,n)
+# else
+# define read(fd,buff,n) rEAd(fd,buff,n)
+# endif /* SYSCALL */
+#endif /* KSHELL */
+
+extern void ed_crlf(Edit_t*);
+extern void ed_putchar(Edit_t*, int);
+extern void ed_ringbell(void);
+extern void ed_setup(Edit_t*,int, int);
+extern void ed_flush(Edit_t*);
+extern int ed_getchar(Edit_t*,int);
+extern int ed_virt_to_phys(Edit_t*,genchar*,genchar*,int,int,int);
+extern int ed_window(void);
+extern void ed_ungetchar(Edit_t*,int);
+extern int ed_viread(void*, int, char*, int, int);
+extern int ed_read(void*, int, char*, int, int);
+extern int ed_emacsread(void*, int, char*, int, int);
+extern Edpos_t ed_curpos(Edit_t*, genchar*, int, int, Edpos_t);
+extern int ed_setcursor(Edit_t*, genchar*, int, int, int);
+#if KSHELL
+ extern int ed_macro(Edit_t*,int);
+ extern int ed_expand(Edit_t*, char[],int*,int*,int,int);
+ extern int ed_fulledit(Edit_t*);
+ extern void *ed_open(Shell_t*);
+#endif /* KSHELL */
+# if SHOPT_MULTIBYTE
+ extern int ed_internal(const char*, genchar*);
+ extern int ed_external(const genchar*, char*);
+ extern void ed_gencpy(genchar*,const genchar*);
+ extern void ed_genncpy(genchar*,const genchar*,int);
+ extern int ed_genlen(const genchar*);
+ extern int ed_setwidth(const char*);
+# endif /* SHOPT_MULTIBYTE */
+#if SHOPT_EDPREDICT
+ extern int ed_histgen(Edit_t*, const char*);
+ extern void ed_histlist(Edit_t*, int);
+#endif /* SHOPT_EDPREDICT */
+
+extern const char e_runvi[];
+#if !KSHELL
+ extern const char e_version[];
+#endif /* KSHELL */
+
+#if SHOPT_HISTEXPAND
+
+/* flags */
+
+#define HIST_EVENT 0x1 /* event designator seen */
+#define HIST_QUESTION 0x2 /* question mark event designator */
+#define HIST_HASH 0x4 /* hash event designator */
+#define HIST_WORDDSGN 0x8 /* word designator seen */
+#define HIST_QUICKSUBST 0x10 /* quick substition designator seen */
+#define HIST_SUBSTITUTE 0x20 /* for substition loop */
+#define HIST_NEWLINE 0x40 /* newline in squashed white space */
+
+/* modifier flags */
+
+#define HIST_PRINT 0x100 /* print new command */
+#define HIST_QUOTE 0x200 /* quote resulting history line */
+#define HIST_QUOTE_BR 0x400 /* quote every word on space break */
+#define HIST_GLOBALSUBST 0x800 /* apply substition globally */
+
+#define HIST_ERROR 0x1000 /* an error ocurred */
+
+/* flags to be returned */
+
+#define HIST_FLAG_RETURN_MASK (HIST_EVENT|HIST_PRINT|HIST_ERROR)
+
+extern int hist_expand(const char *, char **);
+#endif
+
+#endif
+#endif
diff --git a/src/cmd/ksh93/include/env.h b/src/cmd/ksh93/include/env.h
new file mode 100644
index 0000000..0224aa4
--- /dev/null
+++ b/src/cmd/ksh93/include/env.h
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _ENV_H
+#define _ENV_H 1
+
+#ifdef _BLD_env
+# ifdef __EXPORT__
+# define export __EXPORT__
+# endif
+#else
+ typedef void *Env_t;
+#endif
+
+/* for use with env_open */
+#define ENV_STABLE (-1)
+
+/* for third agument to env_add */
+#define ENV_MALLOCED 1
+#define ENV_STRDUP 2
+
+extern void env_close(Env_t*);
+extern int env_add(Env_t*, const char*, int);
+extern int env_delete(Env_t*, const char*);
+extern char **env_get(Env_t*);
+extern Env_t *env_open(char**,int);
+extern Env_t *env_scope(Env_t*,int);
+
+#undef extern
+
+#endif
+
+
diff --git a/src/cmd/ksh93/include/fault.h b/src/cmd/ksh93/include/fault.h
new file mode 100644
index 0000000..e327903
--- /dev/null
+++ b/src/cmd/ksh93/include/fault.h
@@ -0,0 +1,127 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SH_SIGBITS
+/*
+ * UNIX shell
+ * S. R. Bourne
+ * Rewritten by David Korn
+ *
+ */
+
+#include <sig.h>
+#include <setjmp.h>
+#include <error.h>
+#include <sfio.h>
+#include "FEATURE/setjmp"
+#include "FEATURE/sigfeatures"
+
+
+#ifndef SIGWINCH
+# ifdef SIGWIND
+# define SIGWINCH SIGWIND
+# else
+# ifdef SIGWINDOW
+# define SIGWINCH SIGWINDOW
+# endif
+# endif
+#endif
+
+typedef void (*SH_SIGTYPE)(int,void(*)(int));
+
+#define SH_FORKLIM 16 /* fork timeout interval */
+
+#define SH_TRAP 0200 /* bit for internal traps */
+#define SH_ERRTRAP 0 /* trap for non-zero exit status */
+#define SH_KEYTRAP 1 /* trap for keyboard event */
+#define SH_DEBUGTRAP 4 /* must be last internal trap */
+
+#define SH_SIGBITS 8
+#define SH_SIGFAULT 1 /* signal handler is sh_fault */
+#define SH_SIGOFF 2 /* signal handler is SIG_IGN */
+#define SH_SIGSET 4 /* pending signal */
+#define SH_SIGTRAP 010 /* pending trap */
+#define SH_SIGDONE 020 /* default is exit */
+#define SH_SIGIGNORE 040 /* default is ingore signal */
+#define SH_SIGINTERACTIVE 0100 /* handle interactive specially */
+#define SH_SIGTSTP 0200 /* tstp signal received */
+#define SH_SIGALRM 0200 /* timer alarm received */
+#define SH_SIGTERM SH_SIGOFF /* term signal received */
+#define SH_SIGRUNTIME 0400 /* runtime value */
+
+#define SH_SIGRTMIN 0 /* sh.sigruntime[] index */
+#define SH_SIGRTMAX 1 /* sh.sigruntime[] index */
+
+/*
+ * These are longjmp values
+ */
+
+#define SH_JMPDOT 2
+#define SH_JMPEVAL 3
+#define SH_JMPTRAP 4
+#define SH_JMPIO 5
+#define SH_JMPCMD 6
+#define SH_JMPFUN 7
+#define SH_JMPERRFN 8
+#define SH_JMPSUB 9
+#define SH_JMPERREXIT 10
+#define SH_JMPEXIT 11
+#define SH_JMPSCRIPT 12
+
+struct openlist
+{
+ Sfio_t *strm;
+ struct openlist *next;
+};
+
+struct checkpt
+{
+ sigjmp_buf buff;
+ sigjmp_buf *prev;
+ int topfd;
+ int mode;
+ struct openlist *olist;
+#if (ERROR_VERSION >= 20030214L)
+ Error_context_t err;
+#else
+ struct errorcontext err;
+#endif
+};
+
+#define sh_pushcontext(shp,bp,n)( (bp)->mode=(n) , (bp)->olist=0, \
+ (bp)->topfd=shp->topfd, (bp)->prev=shp->jmplist, \
+ (bp)->err = *ERROR_CONTEXT_BASE, \
+ shp->jmplist = (sigjmp_buf*)(&(bp)->buff) \
+ )
+#define sh_popcontext(shp,bp) (shp->jmplist=(bp)->prev, errorpop(&((bp)->err)))
+
+extern void sh_fault(int);
+extern void sh_done(void*,int);
+extern void sh_sigclear(int);
+extern void sh_sigdone(void);
+extern void sh_siginit(void*);
+extern void sh_sigtrap(int);
+extern void sh_sigreset(int);
+extern void *sh_timeradd(unsigned long,int ,void (*)(void*),void*);
+extern void timerdel(void*);
+
+extern const char e_alarm[];
+
+#endif /* !SH_SIGBITS */
diff --git a/src/cmd/ksh93/include/fcin.h b/src/cmd/ksh93/include/fcin.h
new file mode 100644
index 0000000..1459a3a
--- /dev/null
+++ b/src/cmd/ksh93/include/fcin.h
@@ -0,0 +1,71 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef fcgetc
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Fast character input with sfio text streams and strings
+ *
+ */
+
+#include <sfio.h>
+
+typedef struct _fcin
+{
+ Sfio_t *_fcfile; /* input file pointer */
+ unsigned char *fcbuff; /* pointer to input buffer */
+ unsigned char *fclast; /* pointer to end of input buffer */
+ unsigned char *fcptr; /* pointer to next input char */
+ unsigned char fcchar; /* saved character */
+ short fclen; /* last multibyte char len */
+ void (*fcfun)(Sfio_t*,const char*,int,void*); /* advance function */
+ void *context; /* context pointer */
+ int fcleft; /* for multibyte boundary */
+ Sfoff_t fcoff; /* offset for last read */
+} Fcin_t;
+
+#if SHOPT_MULTIBYTE
+# define fcmbget(x) (mbwide()?_fcmbget(x):fcget())
+#else
+# define fcmbget(x) (fcget())
+#endif
+#define fcfile() (_Fcin._fcfile)
+#define fcgetc(c) (((c=fcget()) || (c=fcfill())), c)
+#define fcget() ((int)(*_Fcin.fcptr++))
+#define fcpeek(n) ((int)_Fcin.fcptr[n])
+#define fcseek(n) ((char*)(_Fcin.fcptr+=(n)))
+#define fcfirst() ((char*)_Fcin.fcbuff)
+#define fclast() ((char*)_Fcin.fclast)
+#define fcleft() (_Fcin.fclast-_Fcin.fcptr)
+#define fcsopen(s) (_Fcin._fcfile=(Sfio_t*)0,_Fcin.fclen=1,_Fcin.fcbuff=_Fcin.fcptr=(unsigned char*)(s))
+#define fctell() (_Fcin.fcoff + (_Fcin.fcptr-_Fcin.fcbuff))
+#define fcsave(x) (*(x) = _Fcin)
+#define fcrestore(x) (_Fcin = *(x))
+extern int fcfill(void);
+extern int fcfopen(Sfio_t*);
+extern int fcclose(void);
+void fcnotify(void(*)(Sfio_t*,const char*,int,void*),void*);
+extern int _fcmbget(short*);
+
+extern Fcin_t _Fcin; /* used by macros */
+
+#endif /* fcgetc */
diff --git a/src/cmd/ksh93/include/history.h b/src/cmd/ksh93/include/history.h
new file mode 100644
index 0000000..034a3d3
--- /dev/null
+++ b/src/cmd/ksh93/include/history.h
@@ -0,0 +1,75 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef HIST_VERSION
+/*
+ * Interface for history mechanism
+ * written by David Korn
+ *
+ */
+
+#include <ast.h>
+
+#define HIST_CHAR '!'
+#define HIST_VERSION 1 /* history file format version no. */
+
+typedef struct
+{
+ Sfdisc_t histdisc; /* discipline for history */
+ Sfio_t *histfp; /* history file stream pointer */
+ char *histname; /* name of history file */
+ int32_t histind; /* current command number index */
+ int histsize; /* number of accessible history lines */
+#ifdef _HIST_PRIVATE
+ _HIST_PRIVATE
+#endif /* _HIST_PRIVATE */
+} History_t;
+
+typedef struct
+{
+ int hist_command;
+ int hist_line;
+ int hist_char;
+} Histloc_t;
+
+/* the following are readonly */
+extern const char hist_fname[];
+
+extern int _Hist;
+#define hist_min(hp) ((_Hist=((int)((hp)->histind-(hp)->histsize)))>=0?_Hist:0)
+#define hist_max(hp) ((int)((hp)->histind))
+/* these are the history interface routines */
+extern int sh_histinit(void *);
+extern void hist_cancel(History_t*);
+extern void hist_close(History_t*);
+extern int hist_copy(char*, int, int, int);
+extern void hist_eof(History_t*);
+extern Histloc_t hist_find(History_t*,char*,int, int, int);
+extern void hist_flush(History_t*);
+extern void hist_list(History_t*,Sfio_t*, off_t, int, char*);
+extern int hist_match(History_t*,off_t, char*, int*);
+extern off_t hist_tell(History_t*,int);
+extern off_t hist_seek(History_t*,int);
+extern char *hist_word(char*, int, int);
+#if SHOPT_ESH
+ extern Histloc_t hist_locate(History_t*,int, int, int);
+#endif /* SHOPT_ESH */
+
+#endif /* HIST_VERSION */
diff --git a/src/cmd/ksh93/include/io.h b/src/cmd/ksh93/include/io.h
new file mode 100644
index 0000000..c01dd12
--- /dev/null
+++ b/src/cmd/ksh93/include/io.h
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ * David Korn
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+
+#ifndef IOBSIZE
+# define IOBSIZE SF_BUFSIZE
+#endif /* IOBSIZE */
+#define IOMAXTRY 20
+
+#ifndef SF_CLOSING
+#define SF_CLOSING SF_CLOSE
+#endif
+#ifndef SF_APPENDWR
+#define SF_APPENDWR SF_APPEND
+#endif
+
+/* used for output of shell errors */
+#define ERRIO 2
+
+#define IOREAD 001
+#define IOWRITE 002
+#define IODUP 004
+#define IOSEEK 010
+#define IONOSEEK 020
+#define IOTTY 040
+#define IOCLEX 0100
+#define IOCLOSE (IOSEEK|IONOSEEK)
+
+#define IOSUBSHELL 0x8000 /* must be larger than any file descriptor */
+
+/*
+ * The remainder of this file is only used when compiled with shell
+ */
+
+#if KSHELL
+
+#ifndef ARG_RAW
+ struct ionod;
+#endif /* !ARG_RAW */
+
+extern int sh_iocheckfd(Shell_t*,int);
+extern void sh_ioinit(Shell_t*);
+extern int sh_iomovefd(int);
+extern int sh_iorenumber(Shell_t*,int,int);
+extern void sh_pclose(int[]);
+extern void sh_iorestore(Shell_t*,int,int);
+#if defined(__EXPORT__) && defined(_BLD_DLL) && defined(_BLD_shell)
+ __EXPORT__
+#endif
+extern Sfio_t *sh_iostream(Shell_t*,int);
+extern int sh_redirect(Shell_t*,struct ionod*,int);
+extern void sh_iosave(Shell_t *, int,int,char*);
+extern int sh_iovalidfd(Shell_t*, int);
+extern int sh_inuse(Shell_t*, int);
+extern void sh_iounsave(Shell_t*);
+extern int sh_chkopen(const char*);
+extern int sh_ioaccess(int,int);
+extern int sh_devtofd(const char*);
+extern int sh_isdevfd(const char*);
+extern int sh_source(Shell_t*, Sfio_t*, const char*);
+
+/* the following are readonly */
+extern const char e_pexists[];
+extern const char e_query[];
+extern const char e_history[];
+extern const char e_argtype[];
+extern const char e_create[];
+extern const char e_tmpcreate[];
+extern const char e_exists[];
+extern const char e_file[];
+extern const char e_redirect[];
+extern const char e_formspec[];
+extern const char e_badregexp[];
+extern const char e_open[];
+extern const char e_notseek[];
+extern const char e_noread[];
+extern const char e_badseek[];
+extern const char e_badwrite[];
+extern const char e_badpattern[];
+extern const char e_toomany[];
+extern const char e_pipe[];
+extern const char e_unknown[];
+extern const char e_devnull[];
+extern const char e_profile[];
+extern const char e_sysprofile[];
+#if SHOPT_SYSRC
+extern const char e_sysrc[];
+#endif
+#if SHOPT_BASH
+#if SHOPT_SYSRC
+extern const char e_bash_sysrc[];
+#endif
+extern const char e_bash_rc[];
+extern const char e_bash_login[];
+extern const char e_bash_logout[];
+extern const char e_bash_profile[];
+#endif
+extern const char e_stdprompt[];
+extern const char e_supprompt[];
+extern const char e_ambiguous[];
+#endif /* KSHELL */
diff --git a/src/cmd/ksh93/include/jobs.h b/src/cmd/ksh93/include/jobs.h
new file mode 100644
index 0000000..b67b097
--- /dev/null
+++ b/src/cmd/ksh93/include/jobs.h
@@ -0,0 +1,216 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef JOB_NFLAG
+/*
+ * Interface to job control for shell
+ * written by David Korn
+ *
+ */
+
+#define JOBTTY 2
+
+#include <ast.h>
+#include <sfio.h>
+#ifndef SIGINT
+# include <signal.h>
+#endif /* !SIGINT */
+#include "FEATURE/options"
+
+#if SHOPT_COSHELL
+# include <coshell.h>
+# define COPID_BIT (1L<<30)
+ struct cosh
+ {
+ struct cosh *next;
+ Coshell_t *coshell;
+ Cojob_t *cojob;
+ char *name;
+ short id;
+ };
+
+ extern pid_t sh_copid(struct cosh*);
+ extern char *sh_pid2str(Shell_t*,pid_t);
+#endif /* SHOPT_COSHELL */
+
+#undef JOBS
+#if defined(SIGCLD) && !defined(SIGCHLD)
+# define SIGCHLD SIGCLD
+#endif
+#ifdef SIGCHLD
+# define JOBS 1
+# include "terminal.h"
+# ifdef FIOLOOKLD
+ /* Ninth edition */
+ extern int tty_ld, ntty_ld;
+# define OTTYDISC tty_ld
+# define NTTYDISC ntty_ld
+# endif /* FIOLOOKLD */
+#else
+# undef SIGTSTP
+# undef SH_MONITOR
+# define SH_MONITOR 0
+# define job_set(x)
+# define job_reset(x)
+#endif
+
+struct process
+{
+ struct process *p_nxtjob; /* next job structure */
+ struct process *p_nxtproc; /* next process in current job */
+ Shell_t *p_shp; /* shell that posted the job */
+#if SHOPT_COSHELL
+ Cojob_t *p_cojob; /* coshell job */
+#endif /* SHOPT_COSHELL */
+ int *p_exitval; /* place to store the exitval */
+ pid_t p_pid; /* process id */
+ pid_t p_pgrp; /* process group */
+ pid_t p_fgrp; /* process group when stopped */
+ short p_job; /* job number of process */
+ unsigned short p_exit; /* exit value or signal number */
+ unsigned short p_exitmin; /* minimum exit value for xargs */
+ unsigned short p_flag; /* flags - see below */
+ int p_env; /* subshell environment number */
+#ifdef JOBS
+ off_t p_name; /* history file offset for command */
+ struct termios p_stty; /* terminal state for job */
+#endif /* JOBS */
+};
+
+struct jobs
+{
+ struct process *pwlist; /* head of process list */
+ int *exitval; /* pipe exit values */
+ pid_t curpgid; /* current process gid id */
+ pid_t parent; /* set by fork() */
+ pid_t mypid; /* process id of shell */
+ pid_t mypgid; /* process group id of shell */
+ pid_t mytgid; /* terminal group id of shell */
+ int curjobid;
+ unsigned int in_critical; /* >0 => in critical region */
+ int savesig; /* active signal */
+ int numpost; /* number of posted jobs */
+#ifdef SHOPT_BGX
+ int numbjob; /* number of background jobs */
+#endif /* SHOPT_BGX */
+ short fd; /* tty descriptor number */
+#ifdef JOBS
+ int suspend; /* suspend character */
+ int linedisc; /* line dicipline */
+#endif /* JOBS */
+ char jobcontrol; /* turned on for real job control */
+ char waitsafe; /* wait will not block */
+ char waitall; /* wait for all jobs in pipe */
+ char toclear; /* job table needs clearing */
+ unsigned char *freejobs; /* free jobs numbers */
+#if SHOPT_COSHELL
+ struct cosh *colist; /* coshell job list */
+#endif /* SHOPT_COSHELL */
+};
+
+/* flags for joblist */
+#define JOB_LFLAG 1
+#define JOB_NFLAG 2
+#define JOB_PFLAG 4
+#define JOB_NLFLAG 8
+
+extern struct jobs job;
+
+#ifdef JOBS
+
+#if !_std_malloc
+#include <vmalloc.h>
+#ifdef vmlocked
+#define vmbusy() vmlocked(Vmregion)
+#else
+#if VMALLOC_VERSION >= 20070911L
+#define vmbusy() (vmstat(0,0)!=0)
+#endif
+#endif
+#endif
+#ifndef vmbusy
+#define vmbusy() 0
+#endif
+
+#define job_lock() (job.in_critical++)
+#define job_unlock() \
+ do { \
+ int sig; \
+ if (!--job.in_critical && (sig = job.savesig)) \
+ { \
+ if (!job.in_critical++ && !vmbusy()) \
+ job_reap(sig); \
+ job.in_critical--; \
+ } \
+ } while(0)
+
+extern const char e_jobusage[];
+extern const char e_done[];
+extern const char e_running[];
+extern const char e_coredump[];
+extern const char e_no_proc[];
+extern const char e_no_job[];
+extern const char e_badpid[];
+extern const char e_jobsrunning[];
+extern const char e_nlspace[];
+extern const char e_access[];
+extern const char e_terminate[];
+extern const char e_no_jctl[];
+extern const char e_signo[];
+#ifdef SIGTSTP
+ extern const char e_no_start[];
+#endif /* SIGTSTP */
+#ifdef NTTYDISC
+ extern const char e_newtty[];
+ extern const char e_oldtty[];
+#endif /* NTTYDISC */
+#endif /* JOBS */
+
+/*
+ * The following are defined in jobs.c
+ */
+
+extern void job_clear(void);
+extern void job_bwait(char**);
+extern int job_walk(Sfio_t*,int(*)(struct process*,int),int,char*[]);
+extern int job_kill(struct process*,int);
+extern int job_wait(pid_t);
+extern int job_post(Shell_t*,pid_t,pid_t);
+extern void *job_subsave(void);
+extern void job_subrestore(void*);
+#ifdef SHOPT_BGX
+extern void job_chldtrap(Shell_t*, const char*,int);
+#endif /* SHOPT_BGX */
+#ifdef JOBS
+ extern void job_init(Shell_t*,int);
+ extern int job_close(Shell_t*);
+ extern int job_list(struct process*,int);
+ extern int job_terminate(struct process*,int);
+ extern int job_switch(struct process*,int);
+ extern void job_fork(pid_t);
+ extern int job_reap(int);
+#else
+# define job_init(s,flag)
+# define job_close(s) (0)
+# define job_fork(p)
+#endif /* JOBS */
+
+
+#endif /* !JOB_NFLAG */
diff --git a/src/cmd/ksh93/include/lexstates.h b/src/cmd/ksh93/include/lexstates.h
new file mode 100644
index 0000000..a078e35
--- /dev/null
+++ b/src/cmd/ksh93/include/lexstates.h
@@ -0,0 +1,157 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef S_BREAK
+#define S_BREAK 1 /* end of token */
+#define S_EOF 2 /* end of buffer */
+#define S_NL 3 /* new-line when not a token */
+#define S_RES 4 /* first character of reserved word */
+#define S_NAME 5 /* other identifier characters */
+#define S_REG 6 /* non-special characters */
+#define S_TILDE 7 /* first char is tilde */
+#define S_PUSH 8
+#define S_POP 9
+#define S_BRACT 10
+#define S_LIT 11 /* literal quote character */
+#define S_NLTOK 12 /* new-line token */
+#define S_OP 13 /* operator character */
+#define S_PAT 14 /* pattern characters * and ? */
+#define S_EPAT 15 /* pattern char when followed by ( */
+#define S_EQ 16 /* assignment character */
+#define S_COM 17 /* comment character */
+#define S_MOD1 18 /* ${...} modifier character - old quoting */
+#define S_MOD2 19 /* ${...} modifier character - new quoting */
+#define S_ERR 20 /* invalid character in ${...} */
+#define S_SPC1 21 /* special prefix characters after $ */
+#define S_SPC2 22 /* special characters after $ */
+#define S_DIG 23 /* digit character after $*/
+#define S_ALP 24 /* alpahbetic character after $ */
+#define S_LBRA 25 /* left brace after $ */
+#define S_RBRA 26 /* right brace after $ */
+#define S_PAR 27 /* set for $( */
+#define S_ENDCH 28 /* macro expansion terminator */
+#define S_SLASH 29 /* / character terminates ~ expansion */
+#define S_COLON 30 /* for character : */
+#define S_LABEL 31 /* for goto label */
+#define S_EDOL 32 /* ends $identifier */
+#define S_BRACE 33 /* left brace */
+#define S_DOT 34 /* . char */
+#define S_META 35 /* | & ; < > inside ${...} reserved for future use */
+#define S_SPACE S_BREAK /* IFS space characters */
+#define S_DELIM S_RES /* IFS delimter characters */
+#define S_MBYTE S_NAME /* IFS first byte of multi-byte char */
+#define S_BLNK 36 /* space or tab */
+/* The following must be the highest numbered states */
+#define S_QUOTE 37 /* double quote character */
+#define S_GRAVE 38 /* old comsub character */
+#define S_ESC 39 /* escape character */
+#define S_DOL 40 /* $ subsitution character */
+#define S_ESC2 41 /* escape character inside '...' */
+
+/* These are the lexical state table names */
+#define ST_BEGIN 0
+#define ST_NAME 1
+#define ST_NORM 2
+#define ST_LIT 3
+#define ST_QUOTE 4
+#define ST_NESTED 5
+#define ST_DOL 6
+#define ST_BRACE 7
+#define ST_DOLNAME 8
+#define ST_MACRO 9
+#define ST_QNEST 10
+#define ST_NONE 11
+
+#include "FEATURE/locale"
+
+#if _hdr_wchar
+# include <wchar.h>
+# if _hdr_wctype
+# include <wctype.h>
+# undef isalpha
+# define isalpha(x) iswalpha(x)
+# if defined(iswblank) || _lib_iswblank
+# undef isblank
+# define isblank(x) iswblank(x)
+# else
+# if _lib_wctype && _lib_iswctype
+# define _lib_iswblank -1
+# undef isblank
+# define isblank(x) local_iswblank(x)
+ extern int local_iswblank(wchar_t);
+# endif
+# endif
+# endif
+#endif
+#ifndef isblank
+# define isblank(x) ((x)==' '||(x)=='\t')
+#endif
+
+#undef LEN
+#if SHOPT_MULTIBYTE
+# define LEN _Fcin.fclen
+# define isaname(c) ((c)>0x7f?isalpha(c): sh_lexstates[ST_NAME][(c)]==0)
+# define isaletter(c) ((c)>0x7f?isalpha(c): sh_lexstates[ST_DOL][(c)]==S_ALP && (c)!='.')
+#else
+# undef mbwide
+# define mbwide() (0)
+# define LEN 1
+# define isaname(c) (sh_lexstates[ST_NAME][c]==0)
+# define isaletter(c) (sh_lexstates[ST_DOL][c]==S_ALP && (c)!='.')
+#endif
+#define STATE(s,c) (s[mbwide()?((c=fcmbget(&LEN)),LEN>1?'a':c):(c=fcget())])
+#define isadigit(c) (sh_lexstates[ST_DOL][c]==S_DIG)
+#define isastchar(c) ((c)=='@' || (c)=='*')
+#define isexp(c) (sh_lexstates[ST_MACRO][c]==S_PAT||(c)=='$'||(c)=='`')
+#define ismeta(c) (sh_lexstates[ST_NAME][c]==S_BREAK)
+
+extern char *sh_lexstates[ST_NONE];
+extern const char *sh_lexrstates[ST_NONE];
+extern const char e_lexversion[];
+extern const char e_lexspace[];
+extern const char e_lexslash[];
+extern const char e_lexlabignore[];
+extern const char e_lexlabunknown[];
+extern const char e_lexsyntax1[];
+extern const char e_lexsyntax2[];
+extern const char e_lexsyntax3[];
+extern const char e_lexsyntax4[];
+extern const char e_lexsyntax5[];
+extern const char e_lexwarnvar[];
+extern const char e_lexobsolete1[];
+extern const char e_lexobsolete2[];
+extern const char e_lexobsolete3[];
+extern const char e_lexobsolete4[];
+extern const char e_lexobsolete5[];
+extern const char e_lexobsolete6[];
+extern const char e_lexnonstandard[];
+extern const char e_lexusebrace[];
+extern const char e_lexusequote[];
+extern const char e_lexescape[];
+extern const char e_lexquote[];
+extern const char e_lexnested[];
+extern const char e_lexbadchar[];
+extern const char e_lexlongquote[];
+extern const char e_lexfuture[];
+extern const char e_lexzerobyte[];
+extern const char e_lexemptyfor[];
+extern const char e_lextypeset[];
+extern const char e_lexcharclass[];
+#endif
diff --git a/src/cmd/ksh93/include/name.h b/src/cmd/ksh93/include/name.h
new file mode 100644
index 0000000..9768c05
--- /dev/null
+++ b/src/cmd/ksh93/include/name.h
@@ -0,0 +1,268 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _NV_PRIVATE
+/*
+ * This is the implementation header file for name-value pairs
+ */
+
+#define _NV_PRIVATE \
+ Namfun_t *nvfun; /* pointer to trap functions */ \
+ union Value nvalue; /* value field */ \
+ char *nvenv; /* pointer to environment name */
+
+#include <ast.h>
+#include <cdt.h>
+
+typedef int (*Nambfp_f)(int, char**, void*);
+
+/* Nodes can have all kinds of values */
+union Value
+{
+ const char *cp;
+ int *ip;
+ char c;
+ int i;
+ unsigned int u;
+ int32_t *lp;
+ Sflong_t *llp; /* for long long arithmetic */
+ int16_t s;
+ int16_t *sp;
+ double *dp; /* for floating point arithmetic */
+ Sfdouble_t *ldp; /* for long floating point arithmetic */
+ struct Namarray *array; /* for array node */
+ struct Namval *np; /* for Namval_t node */
+ union Value *up; /* for indirect node */
+ struct Ufunction *rp; /* shell user defined functions */
+ struct Namfun *funp; /* discipline pointer */
+ struct Namref *nrp; /* name reference */
+ Nambfp_f bfp; /* builtin entry point function pointer */
+};
+
+#include "nval.h"
+
+/* used for arrays */
+
+#define ARRAY_MAX (1L<<ARRAY_BITS) /* maximum number of elements in an array */
+#define ARRAY_MASK (ARRAY_MAX-1) /* For index values */
+
+#define ARRAY_INCR 32 /* number of elements to grow when array
+ bound exceeded. Must be a power of 2 */
+#define ARRAY_FILL (8L<<ARRAY_BITS) /* used with nv_putsub() */
+#define ARRAY_NOCLONE (16L<<ARRAY_BITS) /* do not clone array disc */
+#define ARRAY_NOCHILD (32L<<ARRAY_BITS) /* skip compound arrays */
+#define ARRAY_SETSUB (64L<<ARRAY_BITS) /* set subscript */
+#define ARRAY_NOSCOPE (128L<<ARRAY_BITS) /* top level scope only */
+#define ARRAY_TREE (256L<<ARRAY_BITS) /* arrays of compound vars */
+#if SHOPT_FIXEDARRAY
+# define ARRAY_FIXED ARRAY_NOCLONE /* For index values */
+#endif /* SHOPT_FIXEDARRAY */
+#define NV_FARRAY 0x10000000 /* fixed sized arrays */
+#define NV_ASETSUB 8 /* set subscript */
+
+/* These flags are used as options to array_get() */
+#define ARRAY_ASSIGN 0
+#define ARRAY_LOOKUP 1
+#define ARRAY_DELETE 2
+
+
+struct Namref
+{
+ Namval_t *np;
+ Namval_t *table;
+ Dt_t *root;
+ char *sub;
+#if SHOPT_FIXEDARRAY
+ int curi;
+ char dim;
+#endif /* SHOPT_FIXEDARRAY */
+};
+
+/* This describes a user shell function node */
+struct Ufunction
+{
+ int *ptree; /* address of parse tree */
+ int lineno; /* line number of function start */
+ short argc; /* number of references */
+ char **argv; /* reference argument list */
+ off_t hoffset; /* offset into source or history file */
+ Namval_t *nspace; /* pointer to name space */
+ char *fname; /* file name where function defined */
+ char *help; /* help string */
+ Dt_t *sdict; /* dictionary for statics */
+ Dt_t *fdict; /* dictionary node belongs to */
+ Namval_t *np; /* function node pointer */
+};
+
+#ifndef ARG_RAW
+ struct argnod;
+#endif /* !ARG_RAW */
+
+/* attributes of Namval_t items */
+
+/* The following attributes are for internal use */
+#define NV_NOCHANGE (NV_EXPORT|NV_IMPORT|NV_RDONLY|NV_TAGGED|NV_NOFREE|NV_ARRAY)
+#define NV_ATTRIBUTES (~(NV_NOSCOPE|NV_ARRAY|NV_NOARRAY|NV_IDENT|NV_ASSIGN|NV_REF|NV_VARNAME|NV_STATIC))
+#define NV_PARAM NV_NODISC /* expansion use positional params */
+
+/* This following are for use with nodes which are not name-values */
+#define NV_TYPE 0x1000000
+#define NV_STATIC 0x2000000
+#define NV_COMVAR 0x4000000
+#define NV_UNJUST 0x8000000 /* clear justify attributes */
+#define NV_FUNCTION (NV_RJUST|NV_FUNCT) /* value is shell function */
+#define NV_FPOSIX NV_LJUST /* posix function semantics */
+#define NV_FTMP NV_ZFILL /* function source in tmpfile */
+#define NV_STATICF NV_INTEGER /* static class function */
+
+#define NV_NOPRINT (NV_LTOU|NV_UTOL) /* do not print */
+#define NV_NOALIAS (NV_NOPRINT|NV_IMPORT)
+#define NV_NOEXPAND NV_RJUST /* do not expand alias */
+#define NV_BLTIN (NV_NOPRINT|NV_EXPORT)
+#define BLT_ENV (NV_RDONLY) /* non-stoppable,
+ * can modify enviornment */
+#define BLT_SPC (NV_LJUST) /* special built-ins */
+#define BLT_EXIT (NV_RJUST) /* exit value can be > 255 */
+#define BLT_DCL (NV_TAGGED) /* declaration command */
+#define BLT_NOSFIO (NV_IMPORT) /* doesn't use sfio */
+#define NV_OPTGET (NV_BINARY) /* function calls getopts */
+#define nv_isref(n) (nv_isattr((n),NV_REF|NV_TAGGED|NV_FUNCT)==NV_REF)
+#define is_abuiltin(n) (nv_isattr(n,NV_BLTIN|NV_INTEGER)==NV_BLTIN)
+#define is_afunction(n) (nv_isattr(n,NV_FUNCTION|NV_REF)==NV_FUNCTION)
+#define nv_funtree(n) ((n)->nvalue.rp->ptree)
+#define funptr(n) ((n)->nvalue.bfp)
+
+#define NV_SUBQUOTE (NV_ADD<<1) /* used with nv_endsubscript */
+
+/* NAMNOD MACROS */
+/* ... for attributes */
+
+#define nv_setattr(n,f) ((n)->nvflag = (f))
+#define nv_context(n) ((void*)(n)->nvfun) /* for builtins */
+/* The following are for name references */
+#define nv_refnode(n) ((n)->nvalue.nrp->np)
+#define nv_reftree(n) ((n)->nvalue.nrp->root)
+#define nv_reftable(n) ((n)->nvalue.nrp->table)
+#define nv_refsub(n) ((n)->nvalue.nrp->sub)
+#if SHOPT_FIXEDARRAY
+# define nv_refindex(n) ((n)->nvalue.nrp->curi)
+# define nv_refdimen(n) ((n)->nvalue.nrp->dim)
+#endif /* SHOPT_FIXEDARRAY */
+
+/* ... etc */
+
+#define nv_setsize(n,s) ((n)->nvsize = (s))
+#undef nv_size
+#define nv_size(np) ((np)->nvsize)
+#define _nv_hasget(np) ((np)->nvfun && (np)->nvfun->disc && nv_hasget(np))
+#define nv_isnull(np) (!(np)->nvalue.cp && (nv_isattr(np,NV_SHORT|NV_INTEGER)!=(NV_SHORT|NV_INTEGER)) && !_nv_hasget(np))
+
+/* ... for arrays */
+
+#define array_elem(ap) ((ap)->nelem&ARRAY_MASK)
+#define array_assoc(ap) ((ap)->fun)
+
+extern int array_maxindex(Namval_t*);
+extern char *nv_endsubscript(Namval_t*, char*, int);
+extern Namfun_t *nv_cover(Namval_t*);
+extern Namarr_t *nv_arrayptr(Namval_t*);
+extern int nv_arrayisset(Namval_t*, Namarr_t*);
+extern int nv_arraysettype(Namval_t*, Namval_t*,const char*,int);
+extern int nv_aimax(Namval_t*);
+extern int nv_atypeindex(Namval_t*, const char*);
+extern int nv_setnotify(Namval_t*,char **);
+extern int nv_unsetnotify(Namval_t*,char **);
+extern void nv_setlist(struct argnod*, int, Namval_t*);
+extern struct argnod* nv_onlist(struct argnod*, const char*);
+extern void nv_optimize(Namval_t*);
+extern void nv_outname(Sfio_t*,char*, int);
+extern void nv_unref(Namval_t*);
+extern void _nv_unset(Namval_t*,int);
+extern int nv_hasget(Namval_t*);
+extern int nv_clone(Namval_t*, Namval_t*, int);
+void clone_all_disc(Namval_t*, Namval_t*, int);
+extern Namfun_t *nv_clone_disc(Namfun_t*, int);
+extern void *nv_diropen(Namval_t*, const char*);
+extern char *nv_dirnext(void*);
+extern void nv_dirclose(void*);
+extern char *nv_getvtree(Namval_t*, Namfun_t*);
+extern void nv_attribute(Namval_t*, Sfio_t*, char*, int);
+extern Namval_t *nv_bfsearch(const char*, Dt_t*, Namval_t**, char**);
+extern Namval_t *nv_mkclone(Namval_t*);
+extern Namval_t *nv_mktype(Namval_t**, int);
+extern Namval_t *nv_addnode(Namval_t*, int);
+extern Namval_t *nv_parent(Namval_t*);
+extern char *nv_getbuf(size_t);
+extern Namval_t *nv_mount(Namval_t*, const char *name, Dt_t*);
+extern Namval_t *nv_arraychild(Namval_t*, Namval_t*, int);
+extern int nv_compare(Dt_t*, Void_t*, Void_t*, Dtdisc_t*);
+extern void nv_outnode(Namval_t*,Sfio_t*, int, int);
+extern int nv_subsaved(Namval_t*);
+extern void nv_typename(Namval_t*, Sfio_t*);
+extern void nv_newtype(Namval_t*);
+extern int nv_istable(Namval_t*);
+extern size_t nv_datasize(Namval_t*, size_t*);
+extern Namfun_t *nv_mapchar(Namval_t*, const char*);
+#if SHOPT_FIXEDARRAY
+ extern int nv_arrfixed(Namval_t*, Sfio_t*, int, char*);
+#endif /* SHOPT_FIXEDARRAY */
+
+extern const Namdisc_t RESTRICTED_disc;
+extern const Namdisc_t ENUM_disc;
+extern char nv_local;
+extern Dtdisc_t _Nvdisc;
+extern const char *nv_discnames[];
+extern const char e_subscript[];
+extern const char e_nullset[];
+extern const char e_notset[];
+extern const char e_noparent[];
+extern const char e_notelem[];
+extern const char e_readonly[];
+extern const char e_badfield[];
+extern const char e_restricted[];
+extern const char e_ident[];
+extern const char e_varname[];
+extern const char e_noalias[];
+extern const char e_noarray[];
+extern const char e_notenum[];
+extern const char e_nounattr[];
+extern const char e_aliname[];
+extern const char e_badexport[];
+extern const char e_badref[];
+extern const char e_badsubscript[];
+extern const char e_noref[];
+extern const char e_selfref[];
+extern const char e_staticfun[];
+extern const char e_envmarker[];
+extern const char e_badlocale[];
+extern const char e_loop[];
+extern const char e_redef[];
+extern const char e_required[];
+extern const char e_badappend[];
+extern const char e_unknowntype[];
+extern const char e_unknownmap[];
+extern const char e_mapchararg[];
+extern const char e_subcomvar[];
+extern const char e_badtypedef[];
+extern const char e_typecompat[];
+extern const char e_globalref[];
+extern const char e_tolower[];
+extern const char e_toupper[];
+#endif /* _NV_PRIVATE */
diff --git a/src/cmd/ksh93/include/national.h b/src/cmd/ksh93/include/national.h
new file mode 100644
index 0000000..4c1888b
--- /dev/null
+++ b/src/cmd/ksh93/include/national.h
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * national.h - definitions for multibyte character sets
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#if SHOPT_MULTIBYTE
+
+# ifndef MARKER
+# define MARKER 0xdfff /* Must be invalid character */
+# endif
+
+ extern int sh_strchr(const char*,const char*);
+
+#endif /* SHOPT_MULTIBYTE */
diff --git a/src/cmd/ksh93/include/nval.h b/src/cmd/ksh93/include/nval.h
new file mode 100644
index 0000000..6d8a503
--- /dev/null
+++ b/src/cmd/ksh93/include/nval.h
@@ -0,0 +1,311 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef NV_DEFAULT
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Interface definitions of structures for name-value pairs
+ * These structures are used for named variables, functions and aliases
+ *
+ */
+
+
+#include <ast.h>
+#include <cdt.h>
+#include <option.h>
+
+/* for compatibility with old hash library */
+#define Hashtab_t Dt_t
+#define HASH_BUCKET 1
+#define HASH_NOSCOPE 2
+#define HASH_SCOPE 4
+#define hashscope(x) dtvnext(x)
+
+typedef struct Namval Namval_t;
+typedef struct Namfun Namfun_t;
+typedef struct Namdisc Namdisc_t;
+typedef struct Nambfun Nambfun_t;
+typedef struct Namarray Namarr_t;
+typedef struct Namdecl Namdecl_t;
+
+/*
+ * This defines the template for nodes that have their own assignment
+ * and or lookup functions
+ */
+struct Namdisc
+{
+ size_t dsize;
+ void (*putval)(Namval_t*, const char*, int, Namfun_t*);
+ char *(*getval)(Namval_t*, Namfun_t*);
+ Sfdouble_t (*getnum)(Namval_t*, Namfun_t*);
+ char *(*setdisc)(Namval_t*, const char*, Namval_t*, Namfun_t*);
+ Namval_t *(*createf)(Namval_t*, const char*, int, Namfun_t*);
+ Namfun_t *(*clonef)(Namval_t*, Namval_t*, int, Namfun_t*);
+ char *(*namef)(Namval_t*, Namfun_t*);
+ Namval_t *(*nextf)(Namval_t*, Dt_t*, Namfun_t*);
+ Namval_t *(*typef)(Namval_t*, Namfun_t*);
+ int (*readf)(Namval_t*, Sfio_t*, int, Namfun_t*);
+ int (*writef)(Namval_t*, Sfio_t*, int, Namfun_t*);
+};
+
+struct Namfun
+{
+ const Namdisc_t *disc;
+ char nofree;
+ unsigned char subshell;
+ unsigned short dsize;
+ Namfun_t *next;
+ char *last;
+ Namval_t *type;
+};
+
+struct Nambfun
+{
+ Namfun_t fun;
+ int num;
+ const char **bnames;
+ Namval_t *bltins[1];
+};
+
+/* This is an array template header */
+struct Namarray
+{
+ Namfun_t hdr;
+ long nelem; /* number of elements */
+ void *(*fun)(Namval_t*,const char*,int); /* associative arrays */
+ void *fixed; /* for fixed sized arrays */
+ Dt_t *table; /* for subscripts */
+ void *scope; /* non-zerp when scoped */
+};
+
+/* The context pointer for declaration command */
+struct Namdecl
+{
+ Namval_t *tp; /* point to type */
+ const char *optstring;
+ void *optinfof;
+};
+
+/* attributes of name-value node attribute flags */
+
+#define NV_DEFAULT 0
+/* This defines the attributes for an attributed name-value pair node */
+struct Namval
+{
+ Dtlink_t nvlink; /* space for cdt links */
+ char *nvname; /* pointer to name of the node */
+ unsigned short nvflag; /* attributes */
+ unsigned short nvsize; /* size or base */
+#ifdef _NV_PRIVATE
+ _NV_PRIVATE
+#else
+ Namfun_t *nvfun;
+ char *nvalue;
+ char *nvprivate;
+#endif /* _NV_PRIVATE */
+};
+
+#define NV_CLASS ".sh.type"
+#define NV_DATA "_" /* special class or instance variable */
+#define NV_MINSZ (sizeof(struct Namval)-sizeof(Dtlink_t)-sizeof(char*))
+#define nv_namptr(p,n) ((Namval_t*)((char*)(p)+(n)*NV_MINSZ-sizeof(Dtlink_t)))
+
+/* The following attributes are for internal use */
+#define NV_NOFREE 0x200 /* don't free the space when releasing value */
+#define NV_ARRAY 0x400 /* node is an array */
+#define NV_REF 0x4000 /* reference bit */
+#define NV_TABLE 0x800 /* node is a dictionary table */
+#define NV_IMPORT 0x1000 /* value imported from environment */
+#define NV_MINIMAL NV_IMPORT /* node does not contain all fields */
+
+#define NV_INTEGER 0x2 /* integer attribute */
+/* The following attributes are valid only when NV_INTEGER is off */
+#define NV_LTOU 0x4 /* convert to uppercase */
+#define NV_UTOL 0x8 /* convert to lowercase */
+#define NV_ZFILL 0x10 /* right justify and fill with leading zeros */
+#define NV_RJUST 0x20 /* right justify and blank fill */
+#define NV_LJUST 0x40 /* left justify and blank fill */
+#define NV_BINARY 0x100 /* fixed size data buffer */
+#define NV_RAW NV_LJUST /* used only with NV_BINARY */
+#define NV_HOST (NV_RJUST|NV_LJUST) /* map to host filename */
+
+/* The following attributes do not effect the value */
+#define NV_RDONLY 0x1 /* readonly bit */
+#define NV_EXPORT 0x2000 /* export bit */
+#define NV_TAGGED 0x8000 /* user define tag bit */
+
+/* The following are used with NV_INTEGER */
+#define NV_SHORT (NV_RJUST) /* when integers are not long */
+#define NV_LONG (NV_UTOL) /* for long long and long double */
+#define NV_UNSIGN (NV_LTOU) /* for unsigned quantities */
+#define NV_DOUBLE (NV_INTEGER|NV_ZFILL) /* for floating point */
+#define NV_EXPNOTE (NV_LJUST) /* for scientific notation */
+#define NV_HEXFLOAT (NV_LTOU) /* for C99 base16 float notation */
+
+/* options for nv_open */
+
+#define NV_APPEND 0x10000 /* append value */
+#define NV_MOVE 0x8000000 /* for use with nv_clone */
+#define NV_ADD 8
+ /* add node if not found */
+#define NV_ASSIGN NV_NOFREE /* assignment is possible */
+#define NV_NOASSIGN 0 /* backward compatibility */
+#define NV_NOARRAY 0x200000 /* array name not possible */
+#define NV_IARRAY 0x400000 /* for indexed array */
+#define NV_NOREF NV_REF /* don't follow reference */
+#define NV_IDENT 0x80 /* name must be identifier */
+#define NV_VARNAME 0x20000 /* name must be ?(.)id*(.id) */
+#define NV_NOADD 0x40000 /* do not add node */
+#define NV_NOSCOPE 0x80000 /* look only in current scope */
+#define NV_NOFAIL 0x100000 /* return 0 on failure, no msg */
+#define NV_NODISC NV_IDENT /* ignore disciplines */
+
+#define NV_FUNCT NV_IDENT /* option for nv_create */
+#define NV_BLTINOPT NV_ZFILL /* mark builtins in libcmd */
+
+#define NV_PUBLIC (~(NV_NOSCOPE|NV_ASSIGN|NV_IDENT|NV_VARNAME|NV_NOADD))
+
+/* numeric types */
+#define NV_INT16P (NV_LJUST|NV_SHORT|NV_INTEGER)
+#define NV_INT16 (NV_SHORT|NV_INTEGER)
+#define NV_UINT16 (NV_UNSIGN|NV_SHORT|NV_INTEGER)
+#define NV_UINT16P (NV_LJUSTNV_UNSIGN|NV_SHORT|NV_INTEGER)
+#define NV_INT32 (NV_INTEGER)
+#define NV_UNT32 (NV_UNSIGN|NV_INTEGER)
+#define NV_INT64 (NV_LONG|NV_INTEGER)
+#define NV_UINT64 (NV_UNSIGN|NV_LONG|NV_INTEGER)
+#define NV_FLOAT (NV_SHORT|NV_DOUBLE)
+#define NV_LDOUBLE (NV_LONG|NV_DOUBLE)
+
+/* name-value pair macros */
+#define nv_isattr(np,f) ((np)->nvflag & (f))
+#define nv_onattr(n,f) ((n)->nvflag |= (f))
+#define nv_offattr(n,f) ((n)->nvflag &= ~(f))
+#define nv_isarray(np) (nv_isattr((np),NV_ARRAY))
+
+/* The following are operations for associative arrays */
+#define NV_AINIT 1 /* initialize */
+#define NV_AFREE 2 /* free array */
+#define NV_ANEXT 3 /* advance to next subscript */
+#define NV_ANAME 4 /* return subscript name */
+#define NV_ADELETE 5 /* delete current subscript */
+#define NV_AADD 6 /* add subscript if not found */
+#define NV_ACURRENT 7 /* return current subscript Namval_t* */
+#define NV_ASETSUB 8 /* set current subscript */
+
+/* The following are for nv_disc */
+#define NV_FIRST 1
+#define NV_LAST 2
+#define NV_POP 3
+#define NV_CLONE 4
+
+/* The following are operations for nv_putsub() */
+#define ARRAY_BITS 22
+#define ARRAY_ADD (1L<<ARRAY_BITS) /* add subscript if not found */
+#define ARRAY_SCAN (2L<<ARRAY_BITS) /* For ${array[@]} */
+#define ARRAY_UNDEF (4L<<ARRAY_BITS) /* For ${array} */
+
+
+/* These are disciplines provided by the library for use with nv_discfun */
+#define NV_DCADD 0 /* used to add named disciplines */
+#define NV_DCRESTRICT 1 /* variable that are restricted in rsh */
+
+#if defined(__EXPORT__) && defined(_DLL)
+# ifdef _BLD_shell
+# define extern __EXPORT__
+# else
+# define extern __IMPORT__
+# endif /* _BLD_shell */
+#endif /* _DLL */
+/* prototype for array interface*/
+extern Namarr_t *nv_arrayptr(Namval_t*);
+extern Namarr_t *nv_setarray(Namval_t*,void*(*)(Namval_t*,const char*,int));
+extern int nv_arraynsub(Namarr_t*);
+extern void *nv_associative(Namval_t*,const char*,int);
+extern int nv_aindex(Namval_t*);
+extern int nv_nextsub(Namval_t*);
+extern char *nv_getsub(Namval_t*);
+extern Namval_t *nv_putsub(Namval_t*, char*, long);
+extern Namval_t *nv_opensub(Namval_t*);
+
+/* name-value pair function prototypes */
+extern int nv_adddisc(Namval_t*, const char**, Namval_t**);
+extern int nv_clone(Namval_t*, Namval_t*, int);
+extern void nv_close(Namval_t*);
+extern void *nv_context(Namval_t*);
+extern Namval_t *nv_create(const char*, Dt_t*, int,Namfun_t*);
+extern void nv_delete(Namval_t*, Dt_t*, int);
+extern Dt_t *nv_dict(Namval_t*);
+extern Sfdouble_t nv_getn(Namval_t*, Namfun_t*);
+extern Sfdouble_t nv_getnum(Namval_t*);
+extern char *nv_getv(Namval_t*, Namfun_t*);
+extern char *nv_getval(Namval_t*);
+extern Namfun_t *nv_hasdisc(Namval_t*, const Namdisc_t*);
+extern int nv_isnull(Namval_t*);
+extern Namfun_t *nv_isvtree(Namval_t*);
+extern Namval_t *nv_lastdict(void);
+extern Namval_t *nv_mkinttype(char*, size_t, int, const char*, Namdisc_t*);
+extern void nv_newattr(Namval_t*,unsigned,int);
+extern void nv_newtype(Namval_t*);
+extern Namval_t *nv_open(const char*,Dt_t*,int);
+extern void nv_putval(Namval_t*,const char*,int);
+extern void nv_putv(Namval_t*,const char*,int,Namfun_t*);
+extern int nv_rename(Namval_t*,int);
+extern int nv_scan(Dt_t*,void(*)(Namval_t*,void*),void*,int,int);
+extern char *nv_setdisc(Namval_t*,const char*,Namval_t*,Namfun_t*);
+extern void nv_setref(Namval_t*, Dt_t*,int);
+extern int nv_settype(Namval_t*, Namval_t*, int);
+extern void nv_setvec(Namval_t*,int,int,char*[]);
+extern void nv_setvtree(Namval_t*);
+extern int nv_setsize(Namval_t*,int);
+extern Namfun_t *nv_disc(Namval_t*,Namfun_t*,int);
+extern void nv_unset(Namval_t*); /*obsolete */
+extern void _nv_unset(Namval_t*,int);
+extern Namval_t *nv_search(const char *, Dt_t*, int);
+extern char *nv_name(Namval_t*);
+extern Namval_t *nv_type(Namval_t*);
+extern void nv_addtype(Namval_t*,const char*, Optdisc_t*, size_t);
+extern const Namdisc_t *nv_discfun(int);
+
+#ifdef _DLL
+# undef extern
+#endif /* _DLL */
+
+#define nv_unset(np) _nv_unset(np,0)
+#define nv_size(np) nv_setsize((np),-1)
+#define nv_stack(np,nf) nv_disc(np,nf,0)
+
+#if 0
+/*
+ * The names of many functions were changed in early '95
+ * Here is a mapping to the old names
+ */
+# define nv_istype(np) nv_isattr(np)
+# define nv_newtype(np) nv_newattr(np)
+# define nv_namset(np,a,b) nv_open(np,a,b)
+# define nv_free(np) nv_unset(np,0)
+# define nv_settype(np,a,b,c) nv_setdisc(np,a,b,c)
+# define nv_search(np,a,b) nv_open(np,a,((b)?0:NV_NOADD))
+# define settype setdisc
+#endif
+
+#endif /* NV_DEFAULT */
diff --git a/src/cmd/ksh93/include/path.h b/src/cmd/ksh93/include/path.h
new file mode 100644
index 0000000..f15dc4c
--- /dev/null
+++ b/src/cmd/ksh93/include/path.h
@@ -0,0 +1,147 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef PATH_OFFSET
+
+/*
+ * UNIX shell path handling interface
+ * Written by David Korn
+ * These are the definitions for the lexical analyzer
+ */
+
+#include "FEATURE/options"
+#include <nval.h>
+#include "defs.h"
+
+#if !defined(SHOPT_SPAWN)
+# if _UWIN || _use_spawnveg || !_lib_fork
+# define SHOPT_SPAWN 1
+# endif
+#endif /* !SHOPT_SPAWN */
+
+#define PATH_PATH 0001
+#define PATH_FPATH 0002
+#define PATH_CDPATH 0004
+#define PATH_BFPATH 0010
+#define PATH_SKIP 0020
+#define PATH_BUILTIN_LIB 0040
+#define PATH_STD_DIR 0100 /* directory is on $(getconf PATH) */
+
+#define PATH_OFFSET 2 /* path offset for path_join */
+#define MAXDEPTH (sizeof(char*)==2?64:1024) /* maximum recursion depth*/
+
+/*
+ * path component structure for path searching
+ */
+typedef struct pathcomp
+{
+ struct pathcomp *next;
+ int refcount;
+ dev_t dev;
+ ino_t ino;
+ time_t mtime;
+ char *name;
+ char *lib;
+ char *blib;
+ void *bltin_lib;
+ unsigned short len;
+ unsigned short flags;
+ Shell_t *shp;
+} Pathcomp_t;
+
+#ifndef ARG_RAW
+ struct argnod;
+#endif /* !ARG_RAW */
+
+/* pathname handling routines */
+extern void path_newdir(Shell_t*,Pathcomp_t*);
+extern Pathcomp_t *path_dirfind(Pathcomp_t*,const char*,int);
+extern Pathcomp_t *path_unsetfpath(Shell_t*);
+extern Pathcomp_t *path_addpath(Shell_t*,Pathcomp_t*,const char*,int);
+extern Pathcomp_t *path_dup(Pathcomp_t*);
+extern void path_delete(Pathcomp_t*);
+extern void path_alias(Namval_t*,Pathcomp_t*);
+extern Pathcomp_t *path_absolute(Shell_t*, const char*, Pathcomp_t*);
+extern char *path_basename(const char*);
+extern char *path_fullname(Shell_t*,const char*);
+extern int path_expand(Shell_t*,const char*, struct argnod**);
+extern void path_exec(Shell_t*,const char*,char*[],struct argnod*);
+extern pid_t path_spawn(Shell_t*,const char*,char*[],char*[],Pathcomp_t*,int);
+#if defined(__EXPORT__) && defined(_BLD_DLL) && defined(_BLD_shell)
+# define extern __EXPORT__
+#endif
+extern int path_open(Shell_t*,const char*,Pathcomp_t*);
+extern Pathcomp_t *path_get(Shell_t*,const char*);
+#undef extern
+extern char *path_pwd(Shell_t*,int);
+extern Pathcomp_t *path_nextcomp(Shell_t*,Pathcomp_t*,const char*,Pathcomp_t*);
+extern int path_search(Shell_t*,const char*,Pathcomp_t**,int);
+extern char *path_relative(Shell_t*,const char*);
+extern int path_complete(Shell_t*,const char*, const char*,struct argnod**);
+#if SHOPT_BRACEPAT
+ extern int path_generate(Shell_t*,struct argnod*,struct argnod**);
+#endif /* SHOPT_BRACEPAT */
+#if SHOPT_PFSH
+ extern int path_xattr(Shell_t*, const char*, char*);
+#endif /* SHOPT_PFSH */
+
+/* constant strings needed for whence */
+extern const char e_timeformat[];
+extern const char e_badtformat[];
+extern const char e_dot[];
+extern const char e_funload[];
+extern const char e_pfsh[];
+extern const char e_pwd[];
+extern const char e_logout[];
+extern const char e_alphanum[];
+extern const char e_mailmsg[];
+extern const char e_suidprofile[];
+extern const char e_sysprofile[];
+extern const char e_traceprompt[];
+extern const char e_crondir[];
+#if SHOPT_SUID_EXEC
+ extern const char e_suidexec[];
+#endif /* SHOPT_SUID_EXEC */
+extern const char is_alias[];
+extern const char is_builtin[];
+extern const char is_spcbuiltin[];
+extern const char is_builtver[];
+extern const char is_reserved[];
+extern const char is_talias[];
+extern const char is_xalias[];
+extern const char is_function[];
+extern const char is_ufunction[];
+#ifdef SHELLMAGIC
+ extern const char e_prohibited[];
+#endif /* SHELLMAGIC */
+
+#if SHOPT_ACCT
+# include "FEATURE/acct"
+# ifdef _sys_acct
+ extern void sh_accinit(void);
+ extern void sh_accbegin(const char*);
+ extern void sh_accend(void);
+ extern void sh_accsusp(void);
+# else
+# undef SHOPT_ACCT
+# endif /* _sys_acct */
+#endif /* SHOPT_ACCT */
+
+#endif /*! PATH_OFFSET */
diff --git a/src/cmd/ksh93/include/regress.h b/src/cmd/ksh93/include/regress.h
new file mode 100644
index 0000000..83c1824
--- /dev/null
+++ b/src/cmd/ksh93/include/regress.h
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Shell interface private definitions
+ *
+ */
+
+#ifndef _REGRESS_H
+#define _REGRESS_H 1
+
+#if SHOPT_REGRESS
+
+typedef struct Regress_s
+{
+ Shopt_t options;
+} Regress_t;
+
+#define sh_isregress(r) is_option(&sh.regress->options,r)
+#define sh_onregress(r) on_option(&sh.regress->options,r)
+#define sh_offregress(r) off_option(&sh.regress->options,r)
+
+#define REGRESS(r,i,f) do { if (sh_isregress(REGRESS_##r)) sh_regress(REGRESS_##r, i, sfprints f, __LINE__, __FILE__); } while (0)
+
+#define REGRESS_egid 1
+#define REGRESS_euid 2
+#define REGRESS_p_suid 3
+#define REGRESS_source 4
+#define REGRESS_etc 5
+
+#undef SHOPT_P_SUID
+#define SHOPT_P_SUID sh_regress_p_suid(__LINE__, __FILE__)
+
+extern int b___regress__(int, char**, Shbltin_t*);
+extern void sh_regress_init(Shell_t*);
+extern void sh_regress(unsigned int, const char*, const char*, unsigned int, const char*);
+extern uid_t sh_regress_p_suid(unsigned int, const char*);
+extern char* sh_regress_etc(const char*, unsigned int, const char*);
+
+#else
+
+#define REGRESS(r,i,f)
+
+#endif /* SHOPT_REGRESS */
+
+#endif /* _REGRESS_H */
diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h
new file mode 100644
index 0000000..ac80629
--- /dev/null
+++ b/src/cmd/ksh93/include/shell.h
@@ -0,0 +1,259 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SH_INTERACTIVE
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Interface definitions for shell command language
+ *
+ */
+
+#define SH_VERSION 20071012
+
+#include <ast.h>
+#include <cdt.h>
+#ifdef _SH_PRIVATE
+# include "name.h"
+#else
+# include <nval.h>
+#endif /* _SH_PRIVATE */
+
+#undef NOT_USED
+#define NOT_USED(x) (&x,1)
+
+/* options */
+typedef struct
+{
+ unsigned long v[4];
+}
+Shopt_t;
+
+typedef struct Shell_s Shell_t;
+
+#include <shcmd.h>
+
+typedef void (*Shinit_f)(Shell_t*, int);
+#ifndef SH_wait_f_defined
+ typedef int (*Shwait_f)(int, long, int);
+# define SH_wait_f_defined
+#endif
+
+union Shnode_u;
+typedef union Shnode_u Shnode_t;
+
+#define SH_CFLAG 0
+#define SH_HISTORY 1 /* used also as a state */
+#define SH_ERREXIT 2 /* used also as a state */
+#define SH_VERBOSE 3 /* used also as a state */
+#define SH_MONITOR 4 /* used also as a state */
+#define SH_INTERACTIVE 5 /* used also as a state */
+#define SH_RESTRICTED 6
+#define SH_XTRACE 7
+#define SH_KEYWORD 8
+#define SH_NOUNSET 9
+#define SH_NOGLOB 10
+#define SH_ALLEXPORT 11
+#define SH_PFSH 12
+#define SH_IGNOREEOF 13
+#define SH_NOCLOBBER 14
+#define SH_MARKDIRS 15
+#define SH_BGNICE 16
+#define SH_VI 17
+#define SH_VIRAW 18
+#define SH_TFLAG 19
+#define SH_TRACKALL 20
+#define SH_SFLAG 21
+#define SH_NOEXEC 22
+#define SH_GMACS 24
+#define SH_EMACS 25
+#define SH_PRIVILEGED 26
+#define SH_SUBSHARE 27 /* subshell shares state with parent */
+#define SH_NOLOG 28
+#define SH_NOTIFY 29
+#define SH_DICTIONARY 30
+#define SH_PIPEFAIL 32
+#define SH_GLOBSTARS 33
+#define SH_XARGS 34
+#define SH_RC 35
+#define SH_SHOWME 36
+#define SH_LETOCTAL 37
+
+/*
+ * passed as flags to builtins in Nambltin_t struct when BLT_OPTIM is on
+ */
+#define SH_BEGIN_OPTIM 0x1
+#define SH_END_OPTIM 0x2
+
+/* The following type is used for error messages */
+
+/* error messages */
+extern const char e_defpath[];
+extern const char e_found[];
+extern const char e_nospace[];
+extern const char e_format[];
+extern const char e_number[];
+extern const char e_restricted[];
+extern const char e_recursive[];
+extern char e_version[];
+
+typedef struct sh_scope
+{
+ struct sh_scope *par_scope;
+ int argc;
+ char **argv;
+ char *cmdname;
+ char *filename;
+ char *funname;
+ int lineno;
+ Dt_t *var_tree;
+ struct sh_scope *self;
+} Shscope_t;
+
+/*
+ * Saves the state of the shell
+ */
+
+struct Shell_s
+{
+ Shopt_t options; /* set -o options */
+ Dt_t *var_tree; /* for shell variables */
+ Dt_t *fun_tree; /* for shell functions */
+ Dt_t *alias_tree; /* for alias names */
+ Dt_t *bltin_tree; /* for builtin commands */
+ Shscope_t *topscope; /* pointer to top-level scope */
+ int inlineno; /* line number of current input file */
+ int exitval; /* most recent exit value */
+ unsigned char trapnote; /* set when trap/signal is pending */
+ char shcomp; /* set when runing shcomp */
+ short subshell; /* set for virtual subshell */
+#ifdef _SH_PRIVATE
+ _SH_PRIVATE
+#endif /* _SH_PRIVATE */
+};
+
+/* flags for sh_parse */
+#define SH_NL 1 /* Treat new-lines as ; */
+#define SH_EOF 2 /* EOF causes syntax error */
+
+/* symbolic values for sh_iogetiop */
+#define SH_IOCOPROCESS (-2)
+#define SH_IOHISTFILE (-3)
+
+#include <cmd.h>
+
+/* symbolic value for sh_fdnotify */
+#define SH_FDCLOSE (-1)
+
+#undef getenv /* -lshell provides its own */
+
+#if defined(__EXPORT__) && defined(_DLL)
+# ifdef _BLD_shell
+# define extern __EXPORT__
+# endif /* _BLD_shell */
+#endif /* _DLL */
+
+extern Dt_t *sh_bltin_tree(void);
+extern void sh_subfork(void);
+extern Shell_t *sh_init(int,char*[],Shinit_f);
+extern int sh_reinit(char*[]);
+extern int sh_eval(Sfio_t*,int);
+extern void sh_delay(double);
+extern void *sh_parse(Shell_t*, Sfio_t*,int);
+extern int sh_trap(const char*,int);
+extern int sh_fun(Namval_t*,Namval_t*, char*[]);
+extern int sh_funscope(int,char*[],int(*)(void*),void*,int);
+extern Sfio_t *sh_iogetiop(int,int);
+extern int sh_main(int, char*[], Shinit_f);
+extern int sh_run(int, char*[]);
+extern void sh_menu(Sfio_t*, int, char*[]);
+extern Namval_t *sh_addbuiltin(const char*, int(*)(int, char*[],Shbltin_t*), void*);
+extern char *sh_fmtq(const char*);
+extern char *sh_fmtqf(const char*, int, int);
+extern Sfdouble_t sh_strnum(const char*, char**, int);
+extern int sh_access(const char*,int);
+extern int sh_close(int);
+extern int sh_dup(int);
+extern void sh_exit(int);
+extern int sh_fcntl(int, int, ...);
+extern Sfio_t *sh_fd2sfio(int);
+extern int (*sh_fdnotify(int(*)(int,int)))(int,int);
+extern Shell_t *sh_getinterp(void);
+extern int sh_open(const char*, int, ...);
+extern int sh_openmax(void);
+extern Sfio_t *sh_pathopen(const char*);
+extern ssize_t sh_read(int, void*, size_t);
+extern ssize_t sh_write(int, const void*, size_t);
+extern off_t sh_seek(int, off_t, int);
+extern int sh_pipe(int[]);
+extern mode_t sh_umask(mode_t);
+extern void *sh_waitnotify(Shwait_f);
+extern Shscope_t *sh_getscope(int,int);
+extern Shscope_t *sh_setscope(Shscope_t*);
+extern void sh_sigcheck(void);
+extern unsigned long sh_isoption(int);
+extern unsigned long sh_onoption(int);
+extern unsigned long sh_offoption(int);
+extern int sh_waitsafe(void);
+extern int sh_exec(const Shnode_t*,int);
+
+#if SHOPT_DYNAMIC
+ extern void **sh_getliblist(void);
+#endif /* SHOPT_DYNAMIC */
+
+/*
+ * direct access to sh is obsolete, use sh_getinterp() instead
+ */
+#if !defined(_SH_PRIVATE) && defined(__IMPORT__) && !defined(_BLD_shell)
+ extern __IMPORT__ Shell_t sh;
+#else
+ extern Shell_t sh;
+#endif
+
+#ifdef _DLL
+# undef extern
+#endif /* _DLL */
+
+#ifndef _SH_PRIVATE
+# define access(a,b) sh_access(a,b)
+# define close(a) sh_close(a)
+# define exit(a) sh_exit(a)
+# define fcntl(a,b,c) sh_fcntl(a,b,c)
+# define pipe(a) sh_pipe(a)
+# define read(a,b,c) sh_read(a,b,c)
+# define write(a,b,c) sh_write(a,b,c)
+# define umask(a) sh_umask(a)
+# define dup sh_dup
+# if _lib_lseek64
+# define open64 sh_open
+# define lseek64 sh_seek
+# else
+# define open sh_open
+# define lseek sh_seek
+# endif
+#endif /* !_SH_PRIVATE */
+
+#define SH_SIGSET 4
+#define SH_EXITSIG 0400 /* signal exit bit */
+#define SH_EXITMASK (SH_EXITSIG-1) /* normal exit status bits */
+#define SH_RUNPROG -1022 /* needs to be negative and < 256 */
+
+#endif /* SH_INTERACTIVE */
diff --git a/src/cmd/ksh93/include/shlex.h b/src/cmd/ksh93/include/shlex.h
new file mode 100644
index 0000000..b8e5034
--- /dev/null
+++ b/src/cmd/ksh93/include/shlex.h
@@ -0,0 +1,171 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef NOTSYM
+/*
+ * UNIX shell
+ * Written by David Korn
+ * These are the definitions for the lexical analyzer
+ */
+
+#include <cdt.h>
+#include "FEATURE/options"
+#include "shnodes.h"
+#include "shtable.h"
+#include "lexstates.h"
+
+
+typedef struct _shlex_
+{
+ Shell_t *sh; /* pointer to the interpreter */
+ struct argnod *arg; /* current word */
+ struct ionod *heredoc; /* pending here document list */
+ int token; /* current token number */
+ int lastline; /* last line number */
+ int lasttok; /* previous token number */
+ int digits; /* numerical value with word token */
+ int nonstandard; /* nonstandard construct in profile */
+ char aliasok; /* on when alias is legal */
+ char assignok; /* on when name=value is legal */
+ char inexec; /* on when processing exec */
+ char intypeset; /* on when processing typeset */
+ char comp_assign; /* in compound assignment */
+ char comsub; /* parsing command substitution */
+ char noreserv; /* reserved works not legal */
+ int inlineno; /* saved value of sh.inlineno */
+ int firstline; /* saved value of sh.st.firstline */
+#if SHOPT_KIA
+ Sfio_t *kiafile; /* kia output file */
+ Sfio_t *kiatmp; /* kia reference file */
+ unsigned long script; /* script entity number */
+ unsigned long fscript; /* script file entity number */
+ unsigned long current; /* current entity number */
+ unsigned long unknown; /* <unknown> entity number */
+ off_t kiabegin; /* offset of first entry */
+ char *scriptname; /* name of script file */
+ Dt_t *entity_tree; /* for entity ids */
+#endif /* SHOPT_KIA */
+#ifdef _SHLEX_PRIVATE
+ _SHLEX_PRIVATE
+#endif
+} Lex_t;
+
+/* symbols for parsing */
+#define NL '\n'
+#define NOTSYM '!'
+#define SYMRES 0400 /* reserved word symbols */
+#define DOSYM (SYMRES|01)
+#define FISYM (SYMRES|02)
+#define ELIFSYM (SYMRES|03)
+#define ELSESYM (SYMRES|04)
+#define INSYM (SYMRES|05)
+#define THENSYM (SYMRES|06)
+#define DONESYM (SYMRES|07)
+#define ESACSYM (SYMRES|010)
+#define IFSYM (SYMRES|011)
+#define FORSYM (SYMRES|012)
+#define WHILESYM (SYMRES|013)
+#define UNTILSYM (SYMRES|014)
+#define CASESYM (SYMRES|015)
+#define FUNCTSYM (SYMRES|016)
+#define SELECTSYM (SYMRES|017)
+#define TIMESYM (SYMRES|020)
+#define NSPACESYM (SYMRES|021)
+
+#define SYMREP 01000 /* symbols for doubled characters */
+#define BREAKCASESYM (SYMREP|';')
+#define ANDFSYM (SYMREP|'&')
+#define ORFSYM (SYMREP|'|')
+#define IOAPPSYM (SYMREP|'>')
+#define IODOCSYM (SYMREP|'<')
+#define EXPRSYM (SYMREP|'(')
+#define BTESTSYM (SYMREP|'[')
+#define ETESTSYM (SYMREP|']')
+
+#define SYMMASK 0170000
+#define SYMPIPE 010000 /* trailing '|' */
+#define SYMLPAR 020000 /* trailing LPAREN */
+#define SYMAMP 040000 /* trailing '&' */
+#define SYMGT 0100000 /* trailing '>' */
+#define SYMSEMI 0110000 /* trailing ';' */
+#define SYMSHARP 0120000 /* trailing '#' */
+#define IOSEEKSYM (SYMSHARP|'<')
+#define IOMOV0SYM (SYMAMP|'<')
+#define IOMOV1SYM (SYMAMP|'>')
+#define FALLTHRUSYM (SYMAMP|';')
+#define COOPSYM (SYMAMP|'|')
+#define IORDWRSYM (SYMGT|'<')
+#define IORDWRSYMT (SYMSEMI|'<')
+#define IOCLOBSYM (SYMPIPE|'>')
+#define PIPESYM2 (SYMPIPE|'&')
+#define IPROCSYM (SYMLPAR|'<')
+#define OPROCSYM (SYMLPAR|'>')
+#define EOFSYM 04000 /* end-of-file */
+#define TESTUNOP 04001
+#define TESTBINOP 04002
+#define LABLSYM 04003
+#define IOVNAME 04004
+
+/* additional parser flag, others in <shell.h> */
+#define SH_EMPTY 04
+#define SH_NOIO 010
+#define SH_ASSIGN 020
+#define SH_FUNDEF 040
+#define SH_ARRAY 0100
+#define SH_SEMI 0200 /* semi-colon after NL ok */
+
+#define SH_COMPASSIGN 010 /* allow compound assignments only */
+
+#if 0
+typedef struct _shlex_
+{
+ struct shlex_t _shlex;
+#ifdef _SHLEX_PRIVATE
+ _SHLEX_PRIVATE
+#endif
+} Lex_t;
+
+#define shlex (((Lex_t*)(sh.lex_context))->_shlex)
+#endif
+extern const char e_unexpected[];
+extern const char e_unmatched[];
+extern const char e_endoffile[];
+extern const char e_newline[];
+
+/* odd chars */
+#define LBRACE '{'
+#define RBRACE '}'
+#define LPAREN '('
+#define RPAREN ')'
+#define LBRACT '['
+#define RBRACT ']'
+
+extern int sh_lex(Lex_t*);
+extern Shnode_t *sh_dolparen(Lex_t*);
+extern Lex_t *sh_lexopen(Lex_t*, Shell_t*, int);
+extern void sh_lexskip(Lex_t*,int,int,int);
+extern void sh_syntax(Lex_t*);
+#if SHOPT_KIA
+ extern int kiaclose(Lex_t *);
+ extern unsigned long kiaentity(Lex_t*, const char*,int,int,int,int,unsigned long,int,int,const char*);
+#endif /* SHOPT_KIA */
+
+
+#endif /* !NOTSYM */
diff --git a/src/cmd/ksh93/include/shnodes.h b/src/cmd/ksh93/include/shnodes.h
new file mode 100644
index 0000000..6e0eb55
--- /dev/null
+++ b/src/cmd/ksh93/include/shnodes.h
@@ -0,0 +1,221 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _SHNODES_H
+#define _SHNODES_H 1
+/*
+ * UNIX shell
+ * Written by David Korn
+ *
+ */
+
+
+#include <ast.h>
+#include "argnod.h"
+
+/* command tree for tretyp */
+#define FINT (02<<COMBITS) /* non-interruptable */
+#define FAMP (04<<COMBITS) /* background */
+#define FPIN (010<<COMBITS) /* input is a pipe */
+#define FPOU (040<<COMBITS) /* output is a pipe */
+#define FPCL (0100<<COMBITS) /* close the pipe */
+#define FCOOP (0200<<COMBITS) /* cooperating process */
+#define FSHOWME (0400<<COMBITS) /* set for showme commands */
+#define FALTPIPE (02000<<COMBITS) /* alternate pipes &| */
+#define FPOSIX (02<<COMBITS) /* posix semantics function */
+#define FLINENO (04<<COMBITS) /* for/case has line number */
+#define FOPTGET (010<<COMBITS) /* function calls getopts */
+
+#define TNEGATE (01<<COMBITS) /* ! inside [[...]] */
+#define TBINARY (02<<COMBITS) /* binary operator in [[...]] */
+#define TUNARY (04<<COMBITS) /* unary operator in [[...]] */
+#define TTEST (010<<COMBITS)
+#define TPAREN (TBINARY|TUNARY)
+#define TSHIFT (COMBITS+4)
+#define TNSPACE (TFUN|COMSCAN)
+
+#define TCOM 0
+#define TPAR 1
+#define TFIL 2
+#define TLST 3
+#define TIF 4
+#define TWH 5
+#define TUN (TWH|COMSCAN)
+#define TTST 6
+#define TSW 7
+#define TAND 8
+#define TORF 9
+#define TFORK 10
+#define TFOR 11
+#define TSELECT (TFOR|COMSCAN)
+#define TARITH 12
+#define TTIME 13
+#define TSETIO 14
+#define TFUN 15
+
+/* this node is a proforma for those that follow */
+
+struct trenod
+{
+ int tretyp;
+ struct ionod *treio;
+};
+
+
+struct forknod
+{
+ int forktyp;
+ struct ionod *forkio;
+ Shnode_t *forktre;
+ int forkline;
+};
+
+
+struct ifnod
+{
+ int iftyp;
+ Shnode_t *iftre;
+ Shnode_t *thtre;
+ Shnode_t *eltre;
+};
+
+struct whnod
+{
+ int whtyp;
+ Shnode_t *whtre;
+ Shnode_t *dotre;
+ struct arithnod *whinc;
+};
+
+struct fornod
+{
+ int fortyp;
+ char *fornam;
+ Shnode_t *fortre;
+ struct comnod *forlst;
+ int forline;
+};
+
+struct swnod
+{
+ int swtyp;
+ struct argnod *swarg;
+ struct regnod *swlst;
+ struct ionod *swio;
+ int swline;
+};
+
+struct regnod
+{
+ struct argnod *regptr;
+ Shnode_t *regcom;
+ struct regnod *regnxt;
+ char regflag;
+};
+
+struct parnod
+{
+ int partyp;
+ Shnode_t *partre;
+};
+
+struct lstnod
+{
+ int lsttyp;
+ Shnode_t *lstlef;
+ Shnode_t *lstrit;
+};
+
+/* tst is same as lst, but with extra field for line number */
+struct tstnod
+{
+ struct lstnod tstlst;
+ int tstline;
+};
+
+struct functnod
+{
+ int functtyp;
+ char *functnam;
+ Shnode_t *functtre;
+ int functline;
+ off_t functloc;
+ struct slnod *functstak;
+ struct comnod *functargs;
+};
+
+struct arithnod
+{
+ int artyp;
+ int arline;
+ struct argnod *arexpr;
+ void *arcomp;
+};
+
+
+/* types of ionodes stored in iofile */
+#define IOUFD 0x3f /* file descriptor number mask */
+#define IOPUT 0x40 /* > redirection operator */
+#define IOAPP 0x80 /* >> redirection operator */
+#define IODOC 0x100 /* << redirection operator */
+#define IOMOV 0x200 /* <& or >& operators */
+#define IOCLOB 0x400 /* noclobber bit */
+#define IORDW 0x800 /* <> redirection operator */
+#define IORAW 0x1000 /* no expansion needed for filename */
+#define IOSTRG 0x2000 /* here-document stored as incore string */
+#define IOSTRIP 0x4000 /* strip leading tabs for here-document */
+#define IOQUOTE 0x8000 /* here-document delimiter was quoted */
+#define IOVNM 0x10000 /* iovname field is non-zero */
+#define IOLSEEK 0x20000 /* seek operators <# or ># */
+#define IOARITH 0x40000 /* arithmetic seek <# ((expr)) */
+#define IOREWRITE 0x80000 /* arithmetic seek <# ((expr)) */
+#define IOCOPY IOCLOB /* copy skipped lines onto standard output */
+#define IOPROCSUB IOARITH /* process substitution redirection */
+
+union Shnode_u
+{
+ struct argnod arg;
+ struct ionod io;
+ struct whnod wh;
+ struct swnod sw;
+ struct ifnod if_;
+ struct dolnod dol;
+ struct comnod com;
+ struct trenod tre;
+ struct forknod fork;
+ struct fornod for_;
+ struct regnod reg;
+ struct parnod par;
+ struct lstnod lst;
+ struct tstnod tst;
+ struct functnod funct;
+ struct arithnod ar;
+};
+
+extern void sh_freeup(Shell_t*);
+extern void sh_funstaks(struct slnod*,int);
+extern Sfio_t *sh_subshell(Shell_t*,Shnode_t*, int, int);
+#if defined(__EXPORT__) && defined(_BLD_DLL) && defined(_BLD_shell)
+ __EXPORT__
+#endif
+extern int sh_tdump(Sfio_t*, const Shnode_t*);
+extern Shnode_t *sh_trestore(Shell_t*, Sfio_t*);
+
+#endif /* _SHNODES_H */
diff --git a/src/cmd/ksh93/include/shtable.h b/src/cmd/ksh93/include/shtable.h
new file mode 100644
index 0000000..e851ae5
--- /dev/null
+++ b/src/cmd/ksh93/include/shtable.h
@@ -0,0 +1,65 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _SHTABLE_H
+
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Interface definitions read-only data tables for shell
+ *
+ */
+
+#define _SHTABLE_H 1
+
+typedef struct shtable1
+{
+ const char *sh_name;
+ const unsigned sh_number;
+} Shtable_t;
+
+struct shtable2
+{
+ const char *sh_name;
+ const unsigned sh_number;
+ const char *sh_value;
+};
+
+struct shtable3
+{
+ const char *sh_name;
+ const unsigned sh_number;
+ int (*sh_value)(int, char*[], Shbltin_t*);
+};
+
+#define sh_lookup(name,value) (sh_locate(name,(Shtable_t*)(value),sizeof(*(value)))->sh_number)
+extern const Shtable_t shtab_testops[];
+extern const Shtable_t shtab_options[];
+extern const Shtable_t shtab_attributes[];
+extern const struct shtable2 shtab_variables[];
+extern const struct shtable2 shtab_aliases[];
+extern const struct shtable2 shtab_signals[];
+extern const struct shtable3 shtab_builtins[];
+extern const Shtable_t shtab_reserved[];
+extern const Shtable_t *sh_locate(const char*, const Shtable_t*, int);
+extern int sh_lookopt(const char*, int*);
+
+#endif /* SH_TABLE_H */
diff --git a/src/cmd/ksh93/include/streval.h b/src/cmd/ksh93/include/streval.h
new file mode 100644
index 0000000..30008b5
--- /dev/null
+++ b/src/cmd/ksh93/include/streval.h
@@ -0,0 +1,207 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SEQPOINT
+/*
+ * D. G. Korn
+ *
+ * arithmetic expression evaluator
+ */
+
+/* The following only is needed for const */
+#include <ast.h>
+#include <math.h>
+#include "defs.h"
+#if _AST_VERSION >= 20030127L
+# include <ast_float.h>
+#endif
+
+#if _ast_fltmax_double
+#define LDBL_LLONG_MAX DBL_LLONG_MAX
+#define LDBL_ULLONG_MAX DBL_ULLONG_MAX
+#define LDBL_LLONG_MIN DBL_LLONG_MIN
+#endif
+
+#ifndef LDBL_LLONG_MAX
+# ifdef LLONG_MAX
+# define LDBL_LLONG_MAX ((Sfdouble_t)LLONG_MAX)
+# else
+# ifdef LLONG_MAX
+# define LDBL_LLONG_MAX ((Sfdouble_t)LLONG_MAX)
+# else
+# define LDBL_LLONG_MAX ((Sfdouble_t)((((Sflong_t)1) << (8*sizeof(Sflong_t)-1)) -1 ))
+# endif
+# endif
+#endif
+#ifndef LDBL_ULLONG_MAX
+# ifdef ULLONG_MAX
+# define LDBL_ULLONG_MAX ((Sfdouble_t)ULLONG_MAX)
+# else
+# define LDBL_ULLONG_MAX (2.*((Sfdouble_t)LDBL_LLONG_MAX))
+# endif
+#endif
+#ifndef LDBL_LLONG_MIN
+# ifdef LLONG_MIN
+# define LDBL_LLONG_MIN ((Sfdouble_t)LLONG_MIN)
+# else
+# define LDBL_LLONG_MIN (-LDBL_LLONG_MAX)
+# endif
+#endif
+#ifndef LDBL_DIG
+# define LDBL_DIG DBL_DIG
+#endif
+
+struct lval
+{
+ Shell_t *shp;
+ char *value;
+ char *ovalue;
+ Sfdouble_t (*fun)(Sfdouble_t,...);
+ const char *expr;
+ const void *ptr;
+ int nosub;
+ short flag;
+ short nargs;
+ short emode;
+ short level;
+ short elen;
+ char eflag;
+ char isfloat;
+};
+
+struct mathtab
+{
+ char fname[16];
+ Sfdouble_t (*fnptr)(Sfdouble_t,...);
+};
+
+typedef struct _arith_
+{
+ Shell_t *shp;
+ unsigned char *code;
+ const char *expr;
+ Sfdouble_t (*fun)(const char**,struct lval*,int,Sfdouble_t);
+ short size;
+ short staksize;
+ short emode;
+ short elen;
+} Arith_t;
+#define ARITH_COMP 04 /* set when compile separate from execute */
+#define ARITH_ASSIGNOP 010 /* set during assignment operators */
+
+#define MAXPREC 15 /* maximum precision level */
+#define SEQPOINT 0200 /* sequence point */
+#define NOASSIGN 0100 /* assignment legal with this operator */
+#define RASSOC 040 /* right associative */
+#define NOFLOAT 020 /* illegal with floating point */
+#define PRECMASK 017 /* precision bit mask */
+
+#define A_EOF 1
+#define A_NEQ 2
+#define A_NOT 3
+#define A_MOD 4
+#define A_ANDAND 5
+#define A_AND 6
+#define A_LPAR 7
+#define A_RPAR 8
+#define A_POW 9
+#define A_TIMES 10
+#define A_PLUSPLUS 11
+#define A_PLUS 12
+#define A_COMMA 13
+#define A_MINUSMINUS 14
+#define A_MINUS 15
+#define A_DIV 16
+#define A_LSHIFT 17
+#define A_LE 18
+#define A_LT 19
+#define A_EQ 20
+#define A_ASSIGN 21
+#define A_COLON 22
+#define A_RSHIFT 23
+#define A_GE 24
+#define A_GT 25
+#define A_QCOLON 26
+#define A_QUEST 27
+#define A_XOR 28
+#define A_OROR 29
+#define A_OR 30
+#define A_TILDE 31
+#define A_REG 32
+#define A_DIG 33
+#define A_INCR 34
+#define A_DECR 35
+#define A_PUSHV 36
+#define A_PUSHL 37
+#define A_PUSHN 38
+#define A_PUSHF 39
+#define A_STORE 40
+#define A_POP 41
+#define A_SWAP 42
+#define A_UMINUS 43
+#define A_JMPZ 44
+#define A_JMPNZ 45
+#define A_JMP 46
+#define A_CALL1F 47
+#define A_CALL2F 48
+#define A_CALL3F 49
+#define A_CALL1I 50
+#define A_CALL2I 51
+#define A_DOT 52
+#define A_LIT 53
+#define A_NOTNOT 54
+#define A_ASSIGNOP 55
+#define A_ENUM 56
+#define A_ASSIGNOP1 57
+
+
+/* define error messages */
+extern const unsigned char strval_precedence[35];
+extern const char strval_states[64];
+extern const char e_moretokens[];
+extern const char e_argcount[];
+extern const char e_paren[];
+extern const char e_badnum[];
+extern const char e_badcolon[];
+extern const char e_recursive[];
+extern const char e_divzero[];
+extern const char e_synbad[];
+extern const char e_notlvalue[];
+extern const char e_function[];
+extern const char e_questcolon[];
+extern const char e_incompatible[];
+extern const char e_domain[];
+extern const char e_overflow[];
+extern const char e_singularity[];
+extern const char e_dict[];
+extern const char e_charconst[];
+extern const struct mathtab shtab_math[];
+
+/* function code for the convert function */
+
+#define LOOKUP 0
+#define ASSIGN 1
+#define VALUE 2
+#define MESSAGE 3
+
+extern Sfdouble_t strval(Shell_t*,const char*,char**,Sfdouble_t(*)(const char**,struct lval*,int,Sfdouble_t),int);
+extern Arith_t *arith_compile(Shell_t *,const char*,char**,Sfdouble_t(*)(const char**,struct lval*,int,Sfdouble_t),int);
+extern Sfdouble_t arith_exec(Arith_t*);
+#endif /* !SEQPOINT */
diff --git a/src/cmd/ksh93/include/terminal.h b/src/cmd/ksh93/include/terminal.h
new file mode 100644
index 0000000..4999ca3
--- /dev/null
+++ b/src/cmd/ksh93/include/terminal.h
@@ -0,0 +1,195 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _terminal_
+#define _terminal_ 1
+
+#include "FEATURE/ttys"
+/*
+ * terminal interface
+ * complicated by the fact that there are so many variations
+ * This will use POSIX <termios.h> interface where available
+ */
+
+#ifdef _hdr_termios
+# include <termios.h>
+# if __sgi__ || sgi /* special hack to eliminate ^M problem */
+# ifndef ECHOCTL
+# define ECHOCTL ECHOE
+# endif /* ECHOCTL */
+# ifndef CNSUSP
+# define CNSUSP CNSWTCH
+# endif /* CNSUSP */
+# endif /* sgi */
+# ifdef _NEXT_SOURCE
+# define _lib_tcgetattr 1
+# define _lib_tcgetpgrp 1
+# endif /* _NEXT_SOURCE */
+#else
+# if defined(_sys_termios) && defined(_lib_tcgetattr)
+# include <sys/termios.h>
+# define _hdr_termios
+# else
+# undef _sys_termios
+# endif /* _sys_termios */
+#endif /* _hdr_termios */
+
+#ifdef _hdr_termios
+# undef _hdr_sgtty
+# undef tcgetattr
+# undef tcsetattr
+# undef tcgetpgrp
+# undef tcsetpgrp
+# undef cfgetospeed
+# ifndef TCSANOW
+# define TCSANOW TCSETS
+# define TCSADRAIN TCSETSW
+# define TCSAFLUSH TCSETSF
+# endif /* TCSANOW */
+ /* The following corrects bugs in some implementations */
+# if defined(TCSADFLUSH) && !defined(TCSAFLUSH)
+# define TCSAFLUSH TCSADFLUSH
+# endif /* TCSADFLUSH */
+# ifndef _lib_tcgetattr
+# undef tcgetattr
+# define tcgetattr(fd,tty) ioctl(fd, TCGETS, tty)
+# undef tcsetattr
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+# undef cfgetospeed
+# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
+# endif /* _lib_tcgetattr */
+# undef TIOCGETC
+# if SHOPT_OLDTERMIO /* use both termios and termio */
+# ifdef _hdr_termio
+# include <termio.h>
+# else
+# ifdef _sys_termio
+# include <sys/termio.h>
+# define _hdr_termio 1
+# else
+# undef SHOPT_OLDTERMIO
+# endif /* _sys_termio */
+# endif /* _hdr_termio */
+# endif /* SHOPT_OLDTERMIO */
+#else
+# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
+# undef SHOPT_OLDTERMIO
+# ifdef _hdr_termio
+# include <termio.h>
+# else
+# ifdef _sys_termio
+# include <sys/termio.h>
+# define _hdr_termio 1
+# endif /* _sys_termio */
+# endif /* _hdr_termio */
+# ifdef _hdr_termio
+# define termios termio
+# undef TIOCGETC
+# define tcgetattr(fd,tty) ioctl(fd, TCGETA, tty)
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+
+# ifdef _sys_bsdtty
+# include <sys/bsdtty.h>
+# endif /* _sys_bsdtty */
+# else
+# ifdef _hdr_sgtty
+# include <sgtty.h>
+# ifndef LPENDIN
+# ifdef _sys_nttyio
+# include <sys/nttyio.h>
+# endif /* _sys_nttyio */
+# endif /* LPENDIN */
+# define termios sgttyb
+# ifdef TIOCSETN
+# undef TCSETAW
+# endif /* TIOCSETN */
+# ifdef TIOCGETP
+# define tcgetattr(fd,tty) ioctl(fd, TIOCGETP, tty)
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+# else
+# define tcgetattr(fd,tty) gtty(fd, tty)
+# define tcsetattr(fd,action,tty) stty(fd, tty)
+# endif /* TIOCGETP */
+# endif /* _hdr_sgtty */
+# endif /* hdr_termio */
+
+# ifndef TCSANOW
+# ifdef TCSETAW
+# define TCSANOW TCSETA
+# ifdef u370
+ /* delays are too long, don't wait for output to drain */
+# define TCSADRAIN TCSETA
+# else
+# define TCSADRAIN TCSETAW
+# endif /* u370 */
+# define TCSAFLUSH TCSETAF
+# else
+# ifdef TIOCSETN
+# define TCSANOW TIOCSETN
+# define TCSADRAIN TIOCSETN
+# define TCSAFLUSH TIOCSETP
+# endif /* TIOCSETN */
+# endif /* TCSETAW */
+# endif /* TCSANOW */
+#endif /* _hdr_termios */
+
+/* set ECHOCTL if driver can echo control charaters as ^c */
+#ifdef LCTLECH
+# ifndef ECHOCTL
+# define ECHOCTL LCTLECH
+# endif /* !ECHOCTL */
+#endif /* LCTLECH */
+#ifdef LNEW_CTLECH
+# ifndef ECHOCTL
+# define ECHOCTL LNEW_CTLECH
+# endif /* !ECHOCTL */
+#endif /* LNEW_CTLECH */
+#ifdef LNEW_PENDIN
+# ifndef PENDIN
+# define PENDIN LNEW_PENDIN
+# endif /* !PENDIN */
+#endif /* LNEW_PENDIN */
+#ifndef ECHOCTL
+# ifndef VEOL
+# define RAWONLY 1
+# endif /* !VEOL */
+#endif /* !ECHOCTL */
+
+#ifdef _sys_filio
+# ifndef FIONREAD
+# include <sys/filio.h>
+# endif /* FIONREAD */
+#endif /* _sys_filio */
+/* set FIORDCHK if you can check for characters in input queue */
+#ifdef FIONREAD
+# ifndef FIORDCHK
+# define FIORDCHK FIONREAD
+# endif /* !FIORDCHK */
+#endif /* FIONREAD */
+
+extern int tty_alt(int);
+extern void tty_cooked(int);
+extern int tty_get(int,struct termios*);
+extern int tty_raw(int,int);
+extern int tty_check(int);
+extern int tty_set(int, int, struct termios*);
+
+#endif /* _terminal_ */
diff --git a/src/cmd/ksh93/include/test.h b/src/cmd/ksh93/include/test.h
new file mode 100644
index 0000000..a9ed37b
--- /dev/null
+++ b/src/cmd/ksh93/include/test.h
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef TEST_ARITH
+/*
+ * UNIX shell
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "FEATURE/options"
+#include "defs.h"
+#include "shtable.h"
+/*
+ * These are the valid test operators
+ */
+
+#define TEST_ARITH 040 /* arithmetic operators */
+#define TEST_BINOP 0200 /* binary operator */
+#define TEST_PATTERN 0100 /* turn off bit for pattern compares */
+
+#define TEST_NE (TEST_ARITH|9)
+#define TEST_EQ (TEST_ARITH|4)
+#define TEST_GE (TEST_ARITH|5)
+#define TEST_GT (TEST_ARITH|6)
+#define TEST_LE (TEST_ARITH|7)
+#define TEST_LT (TEST_ARITH|8)
+#define TEST_OR (TEST_BINOP|1)
+#define TEST_AND (TEST_BINOP|2)
+#define TEST_SNE (TEST_PATTERN|1)
+#define TEST_SEQ (TEST_PATTERN|14)
+#define TEST_PNE 1
+#define TEST_PEQ 14
+#define TEST_EF 3
+#define TEST_NT 10
+#define TEST_OT 12
+#define TEST_SLT 16
+#define TEST_SGT 17
+#define TEST_END 8
+#define TEST_REP 20
+
+extern int test_unop(Shell_t*,int, const char*);
+extern int test_inode(const char*, const char*);
+extern int test_binop(Shell_t*,int, const char*, const char*);
+
+extern const char sh_opttest[];
+extern const char test_opchars[];
+extern const char e_argument[];
+extern const char e_missing[];
+extern const char e_badop[];
+extern const char e_tstbegin[];
+extern const char e_tstend[];
+
+#endif /* TEST_ARITH */
diff --git a/src/cmd/ksh93/include/timeout.h b/src/cmd/ksh93/include/timeout.h
new file mode 100644
index 0000000..a12c752
--- /dev/null
+++ b/src/cmd/ksh93/include/timeout.h
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * UNIX shell
+ *
+ * AT&T Labs
+ *
+ */
+
+#define TGRACE 60 /* grace period before termination */
+ /* The time_warn message contains this number */
+extern const char e_timeout[];
+extern const char e_timewarn[];
diff --git a/src/cmd/ksh93/include/ulimit.h b/src/cmd/ksh93/include/ulimit.h
new file mode 100644
index 0000000..a0e6330
--- /dev/null
+++ b/src/cmd/ksh93/include/ulimit.h
@@ -0,0 +1,174 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _ULIMIT_H
+#define _ULIMIT_H 1
+/*
+ * This is for the ulimit built-in command
+ */
+
+#include "FEATURE/time"
+#include "FEATURE/rlimits"
+#if defined(_sys_resource) && defined(_lib_getrlimit)
+# include <sys/resource.h>
+# if !defined(RLIMIT_FSIZE) && defined(_sys_vlimit)
+ /* This handles hp/ux problem */
+# include <sys/vlimit.h>
+# define RLIMIT_FSIZE (LIM_FSIZE-1)
+# define RLIMIT_DATA (LIM_DATA-1)
+# define RLIMIT_STACK (LIM_STACK-1)
+# define RLIMIT_CORE (LIM_CORE-1)
+# define RLIMIT_CPU (LIM_CPU-1)
+# ifdef LIM_MAXRSS
+# define RLIMIT_RSS (LIM_MAXRSS-1)
+# endif /* LIM_MAXRSS */
+# endif
+# undef _lib_ulimit
+#else
+# ifdef _sys_vlimit
+# include <sys/vlimit.h>
+# undef _lib_ulimit
+# define RLIMIT_FSIZE LIM_FSIZE
+# define RLIMIT_DATA LIM_DATA
+# define RLIMIT_STACK LIM_STACK
+# define RLIMIT_CORE LIM_CORE
+# define RLIMIT_CPU LIM_CPU
+# ifdef LIM_MAXRSS
+# define RLIMIT_RSS LIM_MAXRSS
+# endif /* LIM_MAXRSS */
+# else
+# ifdef _lib_ulimit
+# define vlimit ulimit
+# endif /* _lib_ulimit */
+# endif /* _lib_vlimit */
+#endif
+
+#ifdef RLIM_INFINITY
+# define INFINITY RLIM_INFINITY
+#else
+# ifndef INFINITY
+# define INFINITY ((rlim_t)-1L)
+# endif /* INFINITY */
+#endif /* RLIM_INFINITY */
+
+#if defined(_lib_getrlimit) || defined(_lib_vlimit) || defined(_lib_ulimit)
+# ifndef RLIMIT_VMEM
+# ifdef RLIMIT_AS
+# define RLIMIT_VMEM RLIMIT_AS
+# endif
+# endif /* !RLIMIT_VMEM */
+#else
+# define _no_ulimit
+#endif
+#ifndef _typ_rlim_t
+ typedef long rlim_t;
+#endif
+
+#if !defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE)
+#define RLIMIT_NOFILE RLIMIT_OFILE
+#endif
+
+#ifndef RLIMIT_UNKNOWN
+#define RLIMIT_UNKNOWN (-9999)
+#endif
+#ifndef RLIMIT_AS
+#define RLIMIT_AS RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_CORE
+#define RLIMIT_CORE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_CPU
+#define RLIMIT_CPU RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_DATA
+#define RLIMIT_DATA RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_FSIZE
+#define RLIMIT_FSIZE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_LOCKS
+#define RLIMIT_LOCKS RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_MEMLOCK
+#define RLIMIT_MEMLOCK RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_MSGQUEUE
+#define RLIMIT_MSGQUEUE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_NOFILE
+#define RLIMIT_NOFILE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_NICE
+#define RLIMIT_NICE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_NPROC
+#define RLIMIT_NPROC RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_PIPE
+#define RLIMIT_PIPE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_PTHREAD
+#define RLIMIT_PTHREAD RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_RSS
+#define RLIMIT_RSS RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_RTPRIO
+#define RLIMIT_RTPRIO RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_SBSIZE
+#define RLIMIT_SBSIZE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_SIGPENDING
+#define RLIMIT_SIGPENDING RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_STACK
+#define RLIMIT_STACK RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_SWAP
+#define RLIMIT_SWAP RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_VMEM
+#define RLIMIT_VMEM RLIMIT_UNKNOWN
+#endif
+
+#define LIM_COUNT 0
+#define LIM_BLOCK 1
+#define LIM_BYTE 2
+#define LIM_KBYTE 3
+#define LIM_SECOND 4
+
+typedef struct Limit_s
+{
+ const char name[16];
+ const char* description;
+ int index;
+ const char* conf;
+ unsigned char option;
+ unsigned char type;
+} Limit_t;
+
+extern const Limit_t shtab_limits[];
+extern const int shtab_units[];
+
+extern const char e_unlimited[];
+extern const char* e_units[];
+
+#endif /* _ULIMIT_H */
diff --git a/src/cmd/ksh93/include/variables.h b/src/cmd/ksh93/include/variables.h
new file mode 100644
index 0000000..edaa865
--- /dev/null
+++ b/src/cmd/ksh93/include/variables.h
@@ -0,0 +1,111 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef SH_VALNOD
+
+#include <option.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+
+/* The following defines are coordinated with data in data/variables.c */
+
+#define PATHNOD (shgd->bltin_nodes)
+#define PS1NOD (shgd->bltin_nodes+1)
+#define PS2NOD (shgd->bltin_nodes+2)
+#define IFSNOD (shgd->bltin_nodes+3)
+#define PWDNOD (shgd->bltin_nodes+4)
+#define HOME (shgd->bltin_nodes+5)
+#define MAILNOD (shgd->bltin_nodes+6)
+#define REPLYNOD (shgd->bltin_nodes+7)
+#define SHELLNOD (shgd->bltin_nodes+8)
+#define EDITNOD (shgd->bltin_nodes+9)
+#define MCHKNOD (shgd->bltin_nodes+10)
+#define RANDNOD (shgd->bltin_nodes+11)
+#define ENVNOD (shgd->bltin_nodes+12)
+#define HISTFILE (shgd->bltin_nodes+13)
+#define HISTSIZE (shgd->bltin_nodes+14)
+#define HISTEDIT (shgd->bltin_nodes+15)
+#define HISTCUR (shgd->bltin_nodes+16)
+#define FCEDNOD (shgd->bltin_nodes+17)
+#define CDPNOD (shgd->bltin_nodes+18)
+#define MAILPNOD (shgd->bltin_nodes+19)
+#define PS3NOD (shgd->bltin_nodes+20)
+#define OLDPWDNOD (shgd->bltin_nodes+21)
+#define VISINOD (shgd->bltin_nodes+22)
+#define COLUMNS (shgd->bltin_nodes+23)
+#define LINES (shgd->bltin_nodes+24)
+#define PPIDNOD (shgd->bltin_nodes+25)
+#define L_ARGNOD (shgd->bltin_nodes+26)
+#define TMOUTNOD (shgd->bltin_nodes+27)
+#define SECONDS (shgd->bltin_nodes+28)
+#define LINENO (shgd->bltin_nodes+29)
+#define OPTARGNOD (shgd->bltin_nodes+30)
+#define OPTINDNOD (shgd->bltin_nodes+31)
+#define PS4NOD (shgd->bltin_nodes+32)
+#define FPATHNOD (shgd->bltin_nodes+33)
+#define LANGNOD (shgd->bltin_nodes+34)
+#define LCALLNOD (shgd->bltin_nodes+35)
+#define LCCOLLNOD (shgd->bltin_nodes+36)
+#define LCTYPENOD (shgd->bltin_nodes+37)
+#define LCMSGNOD (shgd->bltin_nodes+38)
+#define LCNUMNOD (shgd->bltin_nodes+39)
+#define FIGNORENOD (shgd->bltin_nodes+40)
+#define VERSIONNOD (shgd->bltin_nodes+41)
+#define JOBMAXNOD (shgd->bltin_nodes+42)
+#define DOTSHNOD (shgd->bltin_nodes+43)
+#define ED_CHRNOD (shgd->bltin_nodes+44)
+#define ED_COLNOD (shgd->bltin_nodes+45)
+#define ED_TXTNOD (shgd->bltin_nodes+46)
+#define ED_MODENOD (shgd->bltin_nodes+47)
+#define SH_NAMENOD (shgd->bltin_nodes+48)
+#define SH_SUBSCRNOD (shgd->bltin_nodes+49)
+#define SH_VALNOD (shgd->bltin_nodes+50)
+#define SH_VERSIONNOD (shgd->bltin_nodes+51)
+#define SH_DOLLARNOD (shgd->bltin_nodes+52)
+#define SH_MATCHNOD (shgd->bltin_nodes+53)
+#define SH_COMMANDNOD (shgd->bltin_nodes+54)
+#define SH_PATHNAMENOD (shgd->bltin_nodes+55)
+#define SH_FUNNAMENOD (shgd->bltin_nodes+56)
+#define SH_SUBSHELLNOD (shgd->bltin_nodes+57)
+#define SH_LEVELNOD (shgd->bltin_nodes+58)
+#define SH_LINENO (shgd->bltin_nodes+59)
+#define SH_STATS (shgd->bltin_nodes+60)
+#define SH_MATHNOD (shgd->bltin_nodes+61)
+#define SH_JOBPOOL (shgd->bltin_nodes+62)
+#define SHLVL (shgd->bltin_nodes+63)
+#if SHOPT_FS_3D
+# define VPATHNOD (shgd->bltin_nodes+64)
+# define NFS_3D 1
+#else
+# define NFS_3D 0
+#endif /* SHOPT_FS_3D */
+#if SHOPT_VPIX
+# define DOSPATHNOD (shgd->bltin_nodes+64+NFS_3D)
+# define VPIXNOD (shgd->bltin_nodes+65+NFS_3D)
+# define NVPIX (NFS_3D+2)
+#else
+# define NVPIX NFS_3D
+#endif /* SHOPT_VPIX */
+#ifdef apollo
+# define SYSTYPENOD (shgd->bltin_nodes+63+NVPIX)
+#endif /* apollo */
+
+#endif /* SH_VALNOD */
diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h
new file mode 100644
index 0000000..5b2bc90
--- /dev/null
+++ b/src/cmd/ksh93/include/version.h
@@ -0,0 +1,20 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#define SH_RELEASE "93u+ 2012-02-29"
diff --git a/src/cmd/ksh93/ksh-regress.rt b/src/cmd/ksh93/ksh-regress.rt
new file mode 100644
index 0000000..d3d71a1
--- /dev/null
+++ b/src/cmd/ksh93/ksh-regress.rt
@@ -0,0 +1,71 @@
+NOTE regression tests for --regress enabled ksh
+
+UNIT ksh-regress
+
+EXPORT HOME=. ENV=.env.sh LC_ALL=C HISTFILE=
+
+TEST mode suid/sgid combinations
+
+# these tests are the product { all modes combinations } X { tests }
+
+defaults=(
+ "etc=$HOME"
+ "source"
+)
+modes=(
+ interactive
+ login
+ privileged
+ rc
+ restricted
+)
+tests=(
+ ""
+ "euid=0"
+ "euid=0 p_suid=0"
+ "euid=0 p_suid=99999"
+ "euid=1"
+ "euid=1 p_suid=0"
+ "euid=1 p_suid=99999"
+ "egid=1"
+ "egid=1 p_suid=0"
+ "egid=1 p_suid=99999"
+)
+
+integer n=1 m=${#modes[@]}
+d=
+for o in ${defaults[@]}
+do d="$d --regress=$o"
+done
+for ((b=0; b<m; b++))
+do (( n *= 3 ))
+done
+for (( b=0; b<n; b++ ))
+do k=
+ z=$(printf "%0$m..3u" $b)
+ for (( i=0; i<m; i++ ))
+ do case $z in
+ 1*) k="$k --no${modes[i]}" ;;
+ 2*) k="$k --${modes[i]}" ;;
+ esac
+ z=${z#?}
+ done
+ for t in "${tests[@]}"
+ do o=$d
+ for r in $t
+ do o="$o --regress=$r"
+ done
+ o="$o $k"
+
+EXEC $o <<!
+set --state
+!
+
+ done
+done
+
+TEST privileged/noprivileged sequence
+
+EXEC --regress=etc=. --regress=euid=1 --privileged <<!
+set --state; set --noprivileged; set --state; set --privileged; set --state; set --noprivileged; set --state
+!
diff --git a/src/cmd/ksh93/ksh-regress.tst b/src/cmd/ksh93/ksh-regress.tst
new file mode 100644
index 0000000..4565028
--- /dev/null
+++ b/src/cmd/ksh93/ksh-regress.tst
@@ -0,0 +1,22544 @@
+# : : generated from ksh-regress.rt by mktest : : #
+
+# regression tests for --regress enabled ksh
+
+UNIT ksh-regress
+
+EXPORT HOME=. ENV=.env.sh LC_ALL=C HISTFILE=''
+
+TEST 01 'mode suid/sgid combinations'
+
+ EXEC --regress=etc=. --regress=source
+ INPUT - 'set --state'
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+TEST 02 'privileged/noprivileged sequence'
+
+ EXEC --regress=etc=. --regress=euid=1 --privileged
+ INPUT - 'set --state; set --noprivileged; set --state; set --privileged; set --state;'\
+' set --noprivileged; set --state'
+ OUTPUT - $'set --default --braceexpand --privileged --trackall --vi --viraw
+set --default --braceexpand --trackall --vi --viraw
+set --default --braceexpand --privileged --trackall --vi --viraw
+set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:euid:setuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
diff --git a/src/cmd/ksh93/mamexec b/src/cmd/ksh93/mamexec
new file mode 100755
index 0000000..e36a846
--- /dev/null
+++ b/src/cmd/ksh93/mamexec
@@ -0,0 +1,307 @@
+:
+#
+# Glenn Fowler
+# AT&T Bell Laboratories
+#
+# make abstract machine executor with state
+#
+# @(#)mamexec (gsf@research.att.com) 07/17/94
+#
+# mamexec [ -dfins ] [ target ... ] < mam-file
+#
+# NOTE: variables defined in this script may conflict with
+# mam-file variables
+#
+
+_command_=mamexec
+_debug_=:
+_diff_=.
+_error_='exit 1'
+_exec_=eval
+_force_=
+_list_=
+_same_=.
+_set_=
+_silent_=
+_state_list_=MAMlist
+_state_time_=MAMtime
+_tmp_=/tmp/mam.$$.mam
+
+trap 'rm -f $_tmp_' 0
+trap 'exit 2' 1 2
+while :
+do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ -*) case $1 in
+ -*[abceghjklmopqrtuvwxyz_A-Z0-9]*) # [!...] not portable
+ echo "Usage: $_command_ [ -dfins ] [ target ... ] < mam-file" >&2; exit 2
+ ;;
+ *) case $1 in
+ *d*) _debug_="eval echo $_command_: debug: >&2" ;;
+ esac
+ case $1 in
+ *f*) _force_=1 ;;
+ esac
+ case $1 in
+ *i*) _error_=: ;;
+ esac
+ case $1 in
+ *n*) _exec_=echo ;;
+ esac
+ case $1 in
+ *s*) _silent_=1 ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+done
+_select_=
+while :
+do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *=*) eval $1
+ ;;
+ *) case $_select_ in
+ "") _select_=$1 ;;
+ *) _select_="$_select_|$1" ;;
+ esac
+ ;;
+ esac
+ shift
+done
+case $_select_ in
+"") _select_="*" ;;
+esac
+(set -e; false || true) && _set_=e || echo $_command_: command errors ignored because of shell botch >&2
+case $_silent_ in
+"") _set_=x$_set_
+ ;;
+*) case $_exec_ in
+ "echo") _exec_=: ;;
+ esac
+ ;;
+esac
+case $_exec_ in
+"eval") _begin_="("
+ _end_=") </dev/null"
+ case $_set_ in
+ ?*) _set_="set -$_set_;" ;;
+ esac
+ ;;
+*) _set_=
+ ;;
+esac
+
+if test -f $_state_list_ -a -f $_state_time_
+then mamstate $_state_list_ < $_state_list_ | sort > $_tmp_
+ for _i_ in `comm -12 $_state_time_ $_tmp_ | sed 's/ .*//'`
+ do case $_same_ in
+ .) _same_=$_i_ ;;
+ *) _same_="$_same_|$_i_" ;;
+ esac
+ done
+fi
+
+_index_=_
+_match_=
+case `(echo ok | (read -r a; echo $a) 2>/dev/null)` in
+ok) _read_='read -r'
+ ;;
+*) # read strips \ -- thanks a lot
+ # tmp file avoids char at a time read
+ _read_=read
+ sed 's/\\/\\\\/g' > $_tmp_
+ exec < $_tmp_
+ rm -f $_tmp_
+ ;;
+esac
+_old_=1
+_ifs_=$IFS
+while IFS=' '; $_read_ _op_ _arg_ _val_
+do IFS=$_ifs_
+ case $_op_ in
+ "note") continue
+ ;;
+ "info") case $_arg_ in
+ "mam") _old_= ;;
+ esac
+ continue
+ ;;
+ "setv") eval _data_='$'$_arg_
+ case $_index_:$_data_ in
+ __*:*|*:)
+ case $_exec_ in
+ "eval") ;;
+ *) echo "$_arg_=$_val_" ;;
+ esac
+ eval $_arg_="$_val_" "</dev/null"
+ ;;
+ esac
+ case $_arg_:$mam_cc_L in
+ "CC:") (
+ set -
+ mkdir /tmp/mam$$
+ cd /tmp/mam$$
+ echo 'main(){return 0;}' > main.c
+ code=1
+ if $CC -c main.c 2>/dev/null
+ then if $CC -L. main.o -lc 2>/dev/null
+ then $CC -L. main.o -lc > libc.a 2>/dev/null || code=0
+ fi
+ fi
+ cd /tmp
+ rm -rf /tmp/mam$$
+ exit $code
+ ) </dev/null && mam_cc_L=' '
+ ;;
+ esac
+ continue
+ ;;
+ "make") eval _name_$_index_=$_name_
+ eval _prev_$_index_=$_prev_
+ eval _cmds_$_index_='"$_cmds_"'
+ eval _attr_$_index_=$_attr_
+ eval _name_=$_arg_
+ _prev_=$_index_
+ case " $_val_ " in
+ *" metarule "*) _attr_=m$_attr_ ;;
+ esac
+ _cmds_=
+ eval " case \"$_name_\" in
+ $_select_)
+ case \"$_select_\" in
+ \"*\") _select_=$_name_ ;;
+ esac
+ _match_=1
+ _attr_=x$_attr_
+ ;;
+ esac"
+ case $_force_ in
+ "") eval " case \"$_name_\" in
+ $_diff_)_attr_=u$_attr_ ;;
+ $_same_);;
+ *) _attr_=u$_attr_ ;;
+ esac"
+ ;;
+ *) _attr_=u$_attr_
+ ;;
+ esac
+ case $_attr_ in
+ *u*) case $_diff_ in
+ .) _diff_=$_name_ ;;
+ *) _diff_="$_diff_|$_name_" ;;
+ esac
+ ;;
+ esac
+ _index_=_$_index_
+ eval _name_$_index_=$_name_
+ eval _prev_$_index_=$_prev_
+ eval _cmds_$_index_=$_cmds_
+ eval _attr_$_index_=$_attr_
+ eval _list_='"'"$_list_"'
+'$_name_'"'
+ continue
+ ;;
+ "prev") case $_force_ in
+ "") eval " case \"$_arg_\" in
+ $_diff_)_attr_=u$_attr_ ;;
+ $_same_) ;;
+ *) _attr_=u$_attr_ ;;
+ esac"
+ ;;
+ *) _attr_=u$_attr_
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ case $_index_ in
+ _) echo $_op_: missing make op >&2; continue ;;
+ esac
+ case $_op_ in
+ "attr") case $_val_ in
+ "meta"|"suff") _attr_=m$_attr_ ;;
+ esac
+ ;;
+ "exec"|"....")
+ case $_old_ in
+ "") _arg_=$_val_
+ ;;
+ *) case $_val_ in
+ ?*) _arg_="$_arg_ $_val_" ;;
+ esac
+ ;;
+ esac
+ case $_cmds_ in
+ "") _cmds_=$_arg_
+ ;;
+ *) _cmds_="$_cmds_
+$_arg_"
+ ;;
+ esac
+ ;;
+ "done") eval _arg_=$_arg_
+ _prop_=
+ case $_arg_ in
+ $_name_)case $_attr_ in
+ *m*) ;;
+ *x*u*|*u*x*)
+ case $_cmds_ in
+ "") case $_attr_ in
+ *u*) _prop_=u ;;
+ esac
+ ;;
+ *) $_exec_ "$_begin_$_set_$_cmds_$_end_" ||
+ {
+ _code_=$?
+ case $_set_ in
+ *-*e*) ;;
+ *) case $_cmds_ in
+ *if*then*fi*|"||") _code_=0 ;;
+ esac
+ ;;
+ esac
+ case $_code_ in
+ 0) ;;
+ *) echo "*** exit code $_code_ making $_name_" >&2
+ $_error_
+ ;;
+ esac
+ }
+ _prop_=u
+ ;;
+ esac
+ ;;
+ esac
+ _index_=$_prev_
+ eval _name_='$'_name_$_index_
+ eval _prev_='$'_prev_$_index_
+ eval _cmds_='$'_cmds_$_index_
+ eval _attr_=$_prop_'$'_attr_$_index_
+ ;;
+ *) echo $_val_: $_op_ $_name_ expected >&2
+ ;;
+ esac
+ ;;
+ esac
+done
+IFS=$_ifs_
+case $_match_ in
+"") echo "$_command_: don't know how to make $_select_" >&2; $_error_ ;;
+esac
+case $_exec_ in
+"eval") echo "$_list_" > $_state_list_
+ mamstate $_state_list_ < $_state_list_ | sort > $_state_time_
+ ;;
+esac
diff --git a/src/cmd/ksh93/mamstate.c b/src/cmd/ksh93/mamstate.c
new file mode 100644
index 0000000..7a0e459
--- /dev/null
+++ b/src/cmd/ksh93/mamstate.c
@@ -0,0 +1,73 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * AT&T Bell Laboratories
+ * make abstract machine file state support
+ *
+ * mamstate reference [ file ... | <files ]
+ *
+ * stdout is list of <file,delta> pairs where delta
+ * is diff between reference and file times
+ * non-existent files are not listed
+ */
+
+#if !lint
+static char id[] = "\n@(#)$Id: mamstate (AT&T Bell Laboratories) 1989-06-26 $\0\n";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+main(argc, argv)
+int argc;
+register char** argv;
+{
+ register char* s;
+ register int c;
+ long ref;
+ struct stat st;
+ char buf[1024];
+
+ if (!(s = *++argv) || stat(s, &st))
+ {
+ fprintf(stderr, "Usage: mamstate reference [ file ... | <files ]\n");
+ exit(1);
+ }
+ ref = (long)st.st_mtime;
+ if (s = *++argv) do
+ {
+ if (!stat(s, &st))
+ printf("%s %ld\n", s, (long)st.st_mtime - ref);
+ } while (s = *++argv);
+ else do
+ {
+ s = buf;
+ while ((c = getchar()) != EOF && c != ' ' && c != '\n')
+ if (s < buf + sizeof(buf) - 1) *s++ = c;
+ if (s > buf)
+ {
+ *s = 0;
+ if (!stat(buf, &st))
+ printf("%s %ld\n", buf, (long)st.st_mtime - ref);
+ }
+ } while (c != EOF);
+ exit(0);
+}
diff --git a/src/cmd/ksh93/nval.3 b/src/cmd/ksh93/nval.3
new file mode 100644
index 0000000..9dc09a5
--- /dev/null
+++ b/src/cmd/ksh93/nval.3
@@ -0,0 +1,688 @@
+.fp 5 CW
+.TH NVAL 3 "12 Feb 2003"
+.SH NAME
+\fBnval\fR \- the \f5ksh\fP name/value library
+.SH SYNOPSIS
+.ta .8i 1.6i 2.4i 3.2i 4.0i
+.SS "HEADERS/LIBRARIES"
+.nf
+.ft 5
+#include <nval.h>
+libshell.a -lshell
+.ft R
+.fi
+.SS "DATA TYPES"
+.nf
+.ft 5
+Namval_t;
+Namfun_t;
+Namarr_t;
+Namdisc_t;
+.ft R
+.fi
+.SS "OPENING/CLOSING"
+.nf
+.ft 5
+Namval_t *nv_open(const char *\fIname\fP, Dt_t *\fIdict\fP, int \fIflags\fP);
+Namval_t *nv_create(const char *\fIname\fP, Dt_t *\fIdict\fP, int \fIflags\fP, Namfun_t *\fIfp\fP);
+Namval_t *nv_namptr(void *\fIptr\fP, int \fIindx\fP);
+void nv_close(Namval_t *\fInp\fP);
+void nv_delete(Namval_t *\fInp\fP, Dt_t *\fIdict\fP, int \fInofree\fP);
+.ft R
+.fi
+.SS "GETTING AND SETTING VALUES"
+.nf
+.ft 5
+char *nv_getval(Namval_t *\fInp\fP);
+Sfdouble_t nv_getnum(Namval_t *\fInp\fP);
+char *nv_name(Namval_t *\fInp\fP);
+void nv_putval(Namval_t *\fInp\fP, const char *\fIval\fP, int \fIflags\fP);
+void nv_unset(Namval_t *\fInp\fP, int \fIflags\fP);
+int nv_clone(Namval_t *\fIsrc\fP, Namval_t *\fIdest\fP, int \fIflags\fP);
+.ft R
+.fi
+.SS "ATTRIBUTES AND SIZE"
+.nf
+.ft 5
+int nv_isnull(Namval_t *\fInp\fP);
+int nv_setsize(Namval_t *\fInp\fP, int \fIsize\fP);
+int nv_size(Namval_t *\fInp\fP);
+unsigned nv_isattr(Namval_t *\fInp\fP, unsigned \fIflags\fP);
+Namfun_t *nv_isvtree(Namval_t *\fInp\fP);
+unsigned nv_onattr(Namval_t *\fInp\fP, unsigned \fIflags\fP);
+unsigned nv_offattr(Namval_t *\fInp\fP, unsigned \fIflags\fP);
+void nv_newattr(Namval_t *\fInp\fP, unsigned \fIflags\fP, int \fIsize\fP);
+.ft R
+.fi
+
+.SS "ARRAY HANDLING"
+.nf
+.ft 5
+unsigned nv_isarray(Namval_t *\fInp\fP);
+Namarr_t *nv_setarray(Namval_t *\fInp\fP,void*(*\fIfun\fP)(Namval_t*,const char*,int));
+Namarr_t *nv_arrayptr(Namval_t *\fInp\fP);
+Namval_t *nv_putsub(Namval_t *\fInp\fP, char *\fIname\fP, long \fImode\fP);
+Namval_t *nv_opensub(Namval_t *\fInp\fP);
+void nv_setvec(Namval_t *\fInp\fP, int \fIappend\fP, int \fIargc\fP, char *\fIargv\fP[]);
+char *nv_getsub(Namval_t *\fInp\fP);
+int nv_nextsub(Namval_t *\fInp\fP);
+int nv_aindex(Namval_t *\fInp\fP);
+.ft R
+.fi
+.SS "DISCIPLINES"
+.nf
+.ft 5
+Namfun_t *nv_disc(Namval_t *\fInp\fP, Namfun_t *\fIfp\fP, int \fIflags\fP);
+Namfun_t *nv_hasdisc(Namval_t *\fInp\fP, const Namdisc_t *\fIdp\fP);
+char *nv_getv(Namval_t *\fInp\fP, Namfun_t *\fIfp\fP);
+Sfdouble_t nv_getn(Namval_t *\fInp\fP, Namfun_t *\fIfp\fP);
+void nv_putv(Namval_t *\fInp\fP, const char *\fIval\fP, int \fIflags\fP, Namfun_t *\fIfp\fP);
+char *nv_setdisc(Namval_t *\fInp\fP, const char *\fIa\fP, Namval_t *\fIf\fP, Namfun_t *\fIfp\fP);
+char *nv_adddisc(Namval_t *\fInp\fP, const char **\fInames\fP);
+const Namdisc_t *nv_discfun(int \fIwhich\fP);
+.ft R
+.fi
+.SS "TYPES"
+.nf
+.ft 5
+Namval_t *nv_type(Namval_t *\fInp\fP);
+int *nv_settype(Namval_t *\fInp\fP, Namval_t *\fItp\fP, int \fIflags\fP);
+Namval_t *nv_mkinttype(char *\fIname\fP, size_t \fIsz\fP, int \fIus\fP, const char *\fIstr\fP, Namdisc_t *\fIdp\fP);
+void nv_addtype(Namval_t *\fInp\fP, const char *\fIstr\fP, Optdisc_t* *\fIop\fP, size_t \fIsz\fP);
+.ft R
+.fi
+.SS "MISCELLANEOUS FUNCTIONS"
+.nf
+.ft 5
+int nv_scan(Dt_t *\fIdict\fP, void(*\fIfn\fP)(Namval_t*,void*), void *\fIdata\fP, int \fImask\fP, int \fIflags\fP);
+Dt_t *nv_dict(Namval_t *\fInp\fP);
+void nv_setvtree(Namval_t *\fInp\fP);
+void nv_setref(Namval_t *\fInp\fP, Dt_t *\fIdp\fP, int \fIflags\fP);
+Namval_t *nv_lastdict(void);
+.ft R
+.fi
+.SH DESCRIPTION
+\fINval\fP is a library of functions for interacting with name-value
+pairs as used in \f5ksh\fP.
+It is built on top the container dictionary type library facility
+in \f5libcdt\fP. (See cdt(3)).
+Each name-value pair is represented by a
+type named \f5Namval_t\fP.
+A \f5Namval_t\fP contains the name, value and
+attributes of a variable.
+Some attributes can have an associated number that
+represents the field width, arithmetic base, or precision.
+Additionally, each name-value pair can be associated with
+one or more processing disciplines that affect
+its behavior.
+.PP
+The function \f5nv_open()\fP returns a pointer to a name-value
+pair corresponding to the given \fIname\fP.
+It can also assign a value and give attributes to a name-value pair.
+The argument \fIdict\fP defines the dictionary to search.
+A \f5NULL\fP value causes the shell global variable dictionary to be searched.
+.PP
+The \fIflags\fP argument consists of the bitwise-or of zero or more
+of the attributes listed later and zero or more of the following:
+.IP
+\f5NV_VARNAME\fP:
+An invalid variable name causes an error.
+.IP
+\f5NV_IDENTIFIER\fP:
+A variable name that is not an identifier causes an error.
+.IP
+\f5NV_ASSIGN\fP:
+The \fIname\fP argument can contain an assignment.
+.IP
+\f5NV_NOARRAY\fP:
+The \fIname\fP argument cannot contain a subscript.
+.IP
+\f5NV_NOREF\fP:
+Do not follow references when finding the name-value pair.
+.IP
+\f5NV_NOADD\fP:
+The name-value pair will not be added if it doesn't exist.
+Instead, a \f5NULL\fP pointer will be returned.
+.IP
+\f5NV_NOSCOPE\fP:
+Only the top level scope is used.
+.IP
+\f5NV_NOFAIL\fP:
+Just return \f5NULL\fP when an error occurs.
+By default an error message is displayed and the current command
+is aborted.
+.IP
+.PP
+If a name-value pair by this name does not already exist, it is
+created unless \fIflags\fP contains the \f5NV_NOADD\fP flag.
+If \f5NV_VARNAME\fP, \f5NV_IDENTIFIER\fP and \f5NV_ASSIGN\fP are
+all not specified, then no validity check is performed on the \fIname\fP
+argument and no further processing is performed.
+Otherwise, if \f5NV_ASSIGN\fP is specified, then the characters up
+to the first \f5=\fP or \f5+=\fP are used to find the name-value pair,
+and the characters after the \f5=\fP are used to define
+the value that will be assigned to this name-value pair.
+If \fIname\fP does not contain an \f5=\fP, than no assignment
+will be made.
+If the first identifier in \fIname\fP is a reference and is not
+preceded by a \fB.\fP,
+it will be replaced by the value of the reference
+to find the name of a variable.
+Unless \fIflags\fP contains the \f5NV_NOREF\fP flag,
+if the name-value pair give by \fIname\fP has the \f5NV_REF\fP
+attribute, it will be replaced by the variable whose name
+is the value of this name-value pair.
+If \f5NV_ASSIGN\fP is set in the \fIflags\fP argument,
+the \fIname\fP variable can contain an \f5=\fP
+and a value that will be assigned to the name-value pair.
+Any attributes appearing in the \fIflags\fP argument
+will be applied to the name-value pair after any value is assigned.
+.PP
+It is possible for an application to create additional dictionaries
+with the cdt library and associate them with name-value pairs.
+The \f5nv_dict()\fP function returns the dictionary associated with
+the specified name-value pair, or if no dictionary was specified,
+\f5NULL\fP is returned.
+The \f5nv_lastdict()\fP function returns a pointer the the
+name-value pair that contains
+the last dictionary searched on the previous \f5nv_open()\fP.
+.PP
+Name-value pairs can also be allocated without belonging to
+a dictionary. They will typically be looked up by a \fIcreate\fP
+discipline associated with a parent node. In this case the
+node size will be \f5NV_MINSZ\fP and \fIn\fP nodes can be allocated
+vial \f5calloc(5NV_MINSZ,\fIn\fP)\fP(3).
+The \f5nv_namptr\fP function can be used on the pointer returned by
+\f5calloc\fP along with the element number to return the
+corresponding node.
+Each of these nodes must be given the \f5NV_MINIMAL\fP attributes.
+.PP
+The \f5nv_close()\fP indicates that the pointer returned by
+\f5nv_open()\fP or \f5nv_opensub()\fP will not be referenced again. If the
+name-value pair is unset, and not referenced elsewhere,
+the name-value pair may be freed.
+.PP
+The \f5nv_delete()\fP function will remove the node \fInp\fP from
+the dictionary \fIdict\fP. Unless \fInofree\fP is non-zero, the
+node \fInp\fP will also be freed.
+.PP
+The \f5nv_name()\fP function returns the name of the given name-value
+pair \fInp\fP.
+The \f5nv_setsize()\fP function returns the size of the field for
+justified variables, the arithmetic base for integer variables,
+and the precision or number of places after the decimal point
+for floating point variables. If \fIsize\fP is greater than or
+equal to zero, the current size is changed to this value.
+The \f5nv_size()\fP function is equivalent to \f5nv_setsize()\fP
+with the second argument negative.
+.PP
+The \f5nv_getval()\fP function returns the value of the given
+name-value pair as a string. A \f5NULL\fP return value indicates
+that the name-value pair is unset.
+The \f5nv_getnum()\fP function returns the value of the given
+name-value pair as a double precision number using the \f5Sfio\fP
+library (See Sfio(3)) type \f5Sfdouble_t\fP.
+For name-value pairs without the \f5NV_INTEGER\fP attribute,
+the string value is evaluated as an arithmetic expression to
+arrive at a numerical value.
+.PP
+The \f5nv_putval()\fP function is used to assign a \fIvalue\fP to
+the name-value pair \fInp\fP.
+The \fIflags\fP argument consists zero or more of the bitwise-or
+of \f5NV_LONG\fP, \f5NV_SHORT\fP, \f5NV_DOUBLE\fP, \f5NV_INTEGER\fP,
+\f5NV_RDONLY\fP, \f5NV_REF\fP, \f5NV_BINARY\fP, and \f5NV_NOFREE\fP.
+The presence of \f5NV_RDONLY\fP allows the assignment to occur
+even if the name-value pair has the \f5NV_RDONLY\fP attribute.
+The presence of \f5NV_INTEGER\fP indicates that the \fIvalue\fP
+argument is actually a pointer to a numerical type.
+By default this type is \f5long\fP, but can be modified with
+\f5NV_LONG\fP, \f5NV_SHORT\fP, and \f5NV_DOUBLE\fP
+to represent \f5long long\fP, \f5short\fP, \f5double\fP, \f5long double\fP,
+and \f5float\fP.
+The presence of \f5NV_REF\fP indicates that the \fIvalue\fP
+argument is actually a pointer to a name-value pair
+and \f5np\fP should become a reference to this name-value pair.
+If \f5NV_NOFREE\fP is specified, \fIvalue\fP itself becomes
+the value of the name-value pair \fInp\fP.
+Otherwise, a copy of the value is stored
+as the value for \fInp\fP.
+.PP
+The \f5nv_unset()\fP function clears out the value and attributes
+of the given name-value function but does not free the name-value
+pair.
+If called from the \f5putval\fP discipline function, use the \fIflags\fP
+argument as the \fIflags\fP to \f5nv_unset()\fP. Otherwise, use 0.
+.PP
+The following attributes can be associated with a name-value pair:
+.IP
+\f5NV_EXPORT\fP:
+The export attribute.
+.IP
+\f5NV_RDONLY\fP:
+The readonly attribute.
+.IP
+\f5NV_LTOU\fP:
+Lower case characters are converted to upper case characters.
+.IP
+\f5NV_UTOL\fP:
+Upper case characters are converted to lower case characters.
+.IP
+\f5NV_RJUST\fP:
+Right justify and blank fill.
+This attribute has an associated size that defines the
+string length of the value.
+.IP
+\f5NV_LJUST\fP:
+Left justify and blank fill.
+This attribute has an associated size that defines the
+string length of the value.
+.IP
+\f5NV_ZFILL\fP:
+Without \f5NV_LJUST\fP, right justifies and fills with leading zeros.
+With \f5NV_LJUST\fP, left justify and strip leading zeros.
+Left justify and blank fill.
+This attribute has an associated size that defines the
+string length of the value.
+.IP
+\f5NV_TAGGED\fP:
+Indicates the tagged attribute.
+.IP
+\f5NV_INTEGER\fP:
+Causes value to be represented by a number.
+This attribute has an associated number that defines the
+arithmetic base to be used when the value is expanded as a string.
+.IP
+\f5NV_DOUBLE\fP:
+Used in conjunction with \f5NV_INTEGER\fP to cause value
+to be stored as a double precision floating point number.
+This attribute has an associated number that defines the
+number of places after the decimal point to be used when
+the value is expanded as a string.
+.IP
+\f5NV_EXPNOTE\fP:
+Used in conjunction with \f5NV_INTEGER\fP and \f5NV_DOUBLE\fP to
+cause the value to be represented in scientific notation when
+expanded as a string.
+This attribute has an associated number that defines the
+the precision of the mantissa.
+.IP
+\f5NV_HEXFLOAT\fP:
+Used in conjunction with \f5NV_INTEGER\fP and \f5NV_DOUBLE\fP to
+cause the value to be represented in C99 %a format when expanded as
+a string.
+.IP
+\f5NV_BINARY\fP:
+The name-value pair contains a buffer of binary data and \f5nv_size()\fP
+is the number of bytes for this data. By default the value
+will be represented by the base64 encoding of the buffer.
+The \f5NV_LJUST\fP flag may also be specified and causes the buffer
+size to be fixed and data either truncated or filled with \f50\fP bytes.
+.IP
+\f5NV_REF\fP:
+The name-value pair is a name reference variable.
+.IP
+\f5NV_MINIMAL\fP:
+The name-value pair node is not embedded in a dictionary
+and is minimal size, \f5NV_MINSZ\fP.
+.IP
+\f5NV_NODISC\fP:
+All discipline functions are ignored when performing assignments
+and lookups.
+.PP
+The \f5nv_isattr()\fP function can test whether or not any of
+the attributes given by \fIflags\fP is set.
+The \f5nv_onattr()\fP and \f5nv_offattr()\fP functions turn attributes
+on or off respectively. Only attributes that do not affect the
+value can be set in this way.
+The \f5nv_newattr()\fP function can be used to change the
+attributes and size of the given name-value pair which may result
+in the value being changed to conform to the new attributes and size.
+The \fIsize\fP argument is needed for attributes that require
+an additional argument such as justifies variables.
+Changing the attribute may require changing the value
+to agree with the new attributes.
+For an array variable, the values for each of the
+subscripts will be changed.
+.PP
+The \f5nv_isvtree()\fP function returns a pointer to the compound
+variable discipline if the node \fInp\fP is a compound variable
+or \f5NULL\fP otherwise.
+.PP
+The \f5nv_isarray()\fP function returns a non-zero value if the specified
+name-value pair is an array.
+.PP
+The \f5nv_scan()\fP function is used to walk through
+all name-value pairs in the dictionary given by \fIdict\fP.
+If the \f5flags\fP variable contains the \f5NV_NOSCOPE\fP
+flag, then only the top scope will be examined.
+The remaining flags will be used in conjunction with \fImask\fP
+to further restrict the walk.
+If \fImask\fP is non-zero, only the nodes for which
+\f5nv_isattr(\fP\fInode\fP\f5,\fP\fImask\fP\f5)\fP
+is equal to \fIflags\fP will be visited.
+If \fIfn\fP is non-zero, then this function will be executed
+for each name-value pair in the walk.
+The arguments to \fIfn\fP will be a pointer to the name-value pair
+and the \fIdata\fP pointer passed to \f5nv_scan()\fP.
+The number of elements visited will be returned.
+.PP
+The \f5nv_clone()\fP function is used make a copy of the contents of
+name-value pair \fIsrc\fP to another name-value pair \fIdest\fP.
+.PP
+Disciplines provide a way to
+intercept the lookup and assignment operations,
+to manage the creation of sub-variables,
+and to extend the operations permitted on a name-value pair.
+A discipline consists of a set of one or more functions and related
+data that are used to override and extend the operations
+on a name-value pair.
+A discipline is defined by the types
+\f5Namfun_t\fP and \f5Namdisc_t\fP.
+The \f5Namdisc_t\fP is not modified by any of these functions and
+can therefore be shared by several name-value pairs.
+It contains following public fields in the order listed:
+.nf
+ \f5size_t dsize;\fP
+ \f5void (*putval)(Namval_t*,const char*,int,Namfun_t*);\fP
+ \f5char *(*getval)(Namval_t*,Namfun_t*);\fP
+ \f5double (*getnum)(Namval_t*,Namfun_t*);\fP
+ \f5char *(*setdisc)(Namval_t*,const char*,Namval_t*,Namfun_t*);\fP
+ \f5Namval_t *(*createf)(Namval_t*,const char*,Namfun_t*);\fP
+ \f5Namfun_t *(*clonef)(Namval_t*,Namval_t*,int,Namfun_t*);\fP
+ \f5char *(*namef)(Namval_t*,Namfun_t*);\fP
+ \f5Namval_t *(*nextf)(Namval_t*,Dt_t*,Namfun_t*);\fP
+ \f5Namval_t *(*typef)(Namval_t*,Namfun_t*);\fP
+.fi
+The \f5Namfun_t\fP type contains a member named
+\f5disc\fP which points to a \f5Namdisc_t\fP structure.
+To create a discipline with additional user data,
+define a structure with an instance of \f5Namfun_t\fP
+as the first element.
+An application must initialize the \f5Namfun_t\fP portion of
+the structure to zero and then set the \fIdisc\fP field to point
+to the \f5Namdisc_t\fP structure.
+The \f5dsize\fP field of the \f5Namdisc_t\fP structure must be
+the size of this structure. A value of 0,
+indicates that there are no additional fields and is equivalent
+to \f5sizeof(Namfun_t)\fP.
+If different instances of this structure uses different sizes, then
+the \f5size\fP field in the \f5Namfun_t\fP can must be set to
+this size and overrides the value in the \f5Namdisc_t\fP structure.
+.PP
+When a variable is referenced by calling the \f5nv_getval()\fP function,
+and the \f5NV_NODISC\fP attribute is not set,
+the \f5getval()\fP discipline function is called with a pointer
+to the name-value pair, \fInp\fP, and a pointer to the discipline,
+\fIfp\fP.
+Inside the \f5getval()\fP function, the \f5nv_getv()\fP function
+can be called to get the value of the name-value pair that
+would have resulted if the discipline were not used.
+The \f5getnum()\fP discipline is called whenever a numerical
+value is needed for the name-value pair \fInp\fP
+and the \f5NV_NODISC\fP attribute is not set,
+The \f5nv_getn()\fP function can be called from within
+the \f5getnum()\fP discipline to get the value that would
+have resulted if there were no \f5getnum()\fP discipline.
+.PP
+The \f5putval\fP\f5()\fP discipline function is used to
+override the assignment of values
+to a name-value pair.
+It is called whenever a value is assigned with \f5nv_putval()\fP
+and the \f5NV_NODISC\fP attribute is not set,
+or when a name-value pair is unset with \f5nv_unset()\fP.
+When a name-value pair is unset, \f5putval\fP\f5()\fP
+is called with \fIvalue\fP set to \f5NULL\fP.
+The \f5nv_putv()\fP function is used within the \f5putval()\fP
+to perform the assignment or unset that would have occurred
+if the discipline had not been installed.
+.PP
+The \f5createf()\fP discipline function is called from
+\f5nv_open()\fP or \f5nv_create()\fP when the name-value pair preceding a
+.B \s+2.\s-2
+is found.
+This function is passed the name-value pointer plus the remaining string and
+the current \fIflags\fP argument.
+The \f5createf()\fP discipline function
+must return the created name-value pair, otherwise the default action
+will be taken.
+If the name-value pair that is returned is the same as the
+one given, then the the behavior will be the same as if
+an invalid name had been given to \f5nv_open()\fP.
+The \f5nv_create()\fP function may be called within
+the \f5createf()\fP discipline function
+to perform the action that would have occurred
+by an earlier \f5nv_open()\fP function.
+.PP
+The \f5setdisc()\fP discipline function is used
+to extend the set of available shell level discipline functions
+associated with a name-value pair by allowing
+builtins or functions whose name is of the
+form \fIvarname\fP\f5.\fP\fIaction\fP to be defined.
+By default, each name-value pair can have a \f5get\fP,
+\f5set\fP, and \f5unset\fP discipline associated with it.
+Whenever a builtin or function whose name is of the
+form \fIvarname\fP\f5.\fP\fIaction\fP is defined or is unset,
+and \fIaction\fP is not \f5get\fP,
+\f5set\fP, or \f5unset\fP, the \fIsetdisc\fP\f5()\fP function is invoked
+with the same argument format as \f5nv_setdisc\fP\f5()\fP.
+The argument \fIf\fP points to the name-value pair associated
+with the function being defined, or \f5NULL\fP if the function is
+being unset.
+If the given action \fIa\fP is not known by this discipline,
+it should return the value returned by calling
+\f5nv_setdisc(\fP\fInp\fP\f5,\fP\fIa\fP\f5,\fP\fIf\fP\f5,\fP\fIfp\fP\f5)\fP
+so that it can be searched for in previously stacked disciplines.
+Otherwise, the \fIsetdisc\fP\f5()\fP function should save the function
+name-value pair pointer, and return a non-\f5NULL\fP value.
+The name-value pointer to the function can be used to invoke
+the function at an application defined point.
+If the action \fIa\fP is \f5NULL\fP, then \fIf\fP points to
+an action name instead of a name-value pair pointer.
+The \fIsetdisc\fP\f5()\fP must return the
+name of the action that follows the action name given by
+\fIf\fP. If \fIf\fP is also \f5NULL\fP, the name of the first action
+must be returned.
+This allows an application to get the list of valid discipline
+action names allowed by a given name-value pair.
+.PP
+The \f5nv_adddisc()\fP function is a higher level function that
+adds a \fIsetdisc\fP discipline to the name-value pair that allows
+shell level disciplines to be created for each of the name specified
+in \f5names\fP.
+.PP
+The \f5nv_discfun()\fP function can be used to get a pointer to
+discipline functions that are provided by the library.
+Currently, the only one that is provided is the ones used to
+implement \f5nv_adddisc()\fP which can be returned with an
+argument of \f5NV_DCADD\fP.
+.PP
+The \f5clonef()\fP discipline function is called by \f5nv_clone()\fP
+when making a copy of the \f5Namfun_t\fP discipline to the new node.
+The first argument is the original node, the second argument is
+the new node, and the third argument is the flags that were passed
+down to \f5nv_clone()\fP.
+It must return a new instance of the \f5Namfun_t*\fP \f5fp\fP.
+If omitted, then memory whose size is determinated by the \f5size\fP
+field of \f5fp\fP, if non-zero, or \f5fp->disc\fP, will be allocated
+and copied from \f5fp\fP.
+.PP
+The \f5namef()\fP discipline function returns the name for this name-value pair.
+.PP
+The \f5nextf()\fP is used for walking through the list of sub-variables
+associated with this name-value pair. If the dictionary argument is
+\f5NULL\fP, it must return the first sub-variable. Otherwise,
+it must return the next sub-variable, or \f5NULL\fP if there are
+no more variables.
+.PP
+A discipline is installed or removed with the
+\f5nv_disc()\fP function.
+The following flags can be specified:
+.IP
+\f5NV_FIRST\fP:
+If \fIfp\fP is non-\f5NULL\fP, the discipline is moved to the top
+of the stack or pushed onto the top of the stack of disciplines
+associated with the given name-value
+pair \fInp\fP if not already present.
+Otherwise, the top of the discipline stack is returned.
+.IP
+\f5NV_LAST\fP:
+If \fIfp\fP is non-\f5NULL\fP, the discipline is moved to the bottom
+of the stack or pushed onto the bottom of the stack of disciplines
+associated with the given name-value
+pair \fInp\fP if not already present.
+Otherwise, the bottom of the discipline stack is returned.
+.IP
+\f5NV_POP\fP:
+If \fIfp\fP is non-\f5NULL\fP and it is on the stack,
+it is removed and \fIfp\fP is returned. If \fIfp\fP is non-\f5NULL\fP
+and is not on the stack, \f5NULL\fP is returned.
+Otherwise, the the top discipline is popped
+and returned.
+.IP
+\f5NV_CLONE\fP:
+If \fIfp\fP is non-\f5NULL\fP and it is on the stack,
+it is replace by a copy created by \f5malloc\fP(3).
+The \f5nofree\fP field is set to \f50\fP.
+The new discipline is returned.
+Otherwise, \f5NULL\fP is returned.
+.IP
+\f50\fP:
+If \fIfp\fP is non-\f5NULL\fP then it is equivalent to \f5NV_FIRST\fP.
+Otherwise, it is equivalent to \f5NV_POP\fP.
+.PP
+The
+\f5nv_hasdisc()\fP function can be used to tell whether a discipline
+whose discipline functions are those defined in \fIdp\fP.
+A pointer to this discipline is returned.
+.PP
+The \f5nv_aindex()\fP function returns
+the current index for
+the indexed array given by the name-value pair pointer \fInp\fP.
+The return value is negative if \fInp\fP refers to
+an associative array.
+.PP
+The \f5nv_setarray()\fP function is used to create an associative array
+from a name-value pair node.
+The function \fIfun\fP defines the semantics of the associative
+array.
+Using \fIfun\fP equal to \f5nv_associative()\fP implements the default
+associative array semantics
+that are used with \f5typeset\ -A\fP.
+The function \fIfun\fP will be called with third argument as follows:
+.IP
+\f5NV_AINIT\fP:
+This will be called at initialization.
+The function you supply must return a pointer to a structure
+that contains the type \f5Namarr_t\fP as the first element.
+All other calls receive this value as an argument.
+.IP
+\f5NV_AFREE\fP:
+This will be called after all elements of the name-value pair have been
+deleted and the array is to be freed.
+.IP
+\f5NV_ADELETE\fP:
+The current element should be deleted.
+.IP
+\f5NV_ANEXT\fP:
+This means that the array subscript should be advanced to the
+next subscript. A \f5NULL\fP return indicates that there are
+no more subscripts.
+.IP
+\f5NV_ANAME\fP:
+The name of the current subscript must be returned.
+.IP
+\f5NV_ACURRENT\fP:
+Returns a pointer to a name-value pair corresponding to the
+current subscript, or \f5NULL\fP if this array type doesn't
+create represent each element as a name-value pair.
+.IP
+\f5NV_ASETSUB\fP:
+Set the current subscript to the name-value pair passed in
+as the second argument.
+.PP
+If \fInp\fP refers to an array,
+\f5nv_arrayptr()\fP returns a pointer to
+the array discipline structure \f5Namarr_t\fP.
+Otherwise \f5nv_arrayptr()\fP returns \f5NULL\fP.
+.PP
+If \fInp\fP refers to an array,
+the \f5nv_getsub()\fP returns a pointer to
+the name of the current subscript.
+Otherwise, \f5nv_getsub()\fP
+returns \f5NULL\fP.
+.PP
+The \f5nv_opensub()\fP function returns
+a pointer to the name-value pair corresponding
+to the current subscript in an associative array.
+Note that the \f5nv_close()\fP function should be called
+when the pointer is no longer needed.
+.PP
+The \f5nv_putsub()\fP function is used to
+set the subscript for the next reference to \f5np\fP.
+If the \f5name\fP argument is not \f5NULL\fP,
+it defines the value of the next subscript.
+The \f5mode\fP argument can contain one or more of the following flags:
+.IP
+\f5ARRAY_ADD\fP:
+Add the subscript if not found.
+Otherwise, \f5nv_putsub()\fP returns \f5NULL\fP if the
+given subscript is not found.
+.IP
+\f5ARRAY_SCAN\fP:
+Begin a walk through the subscripts starting at the subscript
+given by \f5name\fP. If \f5name\fP is \f5NULL\fP
+the walk is started from the beginning.
+.IP
+\f5ARRAY_UNDEF\fP:
+This causes any current scan to terminate and leaves the
+subscript in an undefined state.
+.PP
+If \f5ARRAY_ADD\fP is not given and the subscript
+does not exist, a \f5NULL\fP value is returned.
+.PP
+The \f5nv_nextsub()\fP function is used to advance to the
+next subscript.
+It returns 0 if there are no more subscripts or if called
+when not in a scan.
+.PP
+The \f5nv_setref()\fP function makes the name-value pair \f5np\fP
+into a reference to the variable whose name is given by
+the value of \f5np\fP. The \f5nv_open()\fP open function is
+called with this name, the dictionary given by \f5dp\fP,
+and the \f5flags\fP argument.
+A \f5NULL\fP value causes the shell global variable dictionary to be searched.
+.PP
+The \f5nv_setvtree()\fP function makes the name-value pair \f5np\fP
+into a tree structured variable so that \f5nv_getval()\fP
+will return a string containing all the names and values of
+children nodes in a format that can be used in
+a shell compound assignment.
+.PP
+The \f5nv_type()\fP function returns a name_value pair pointer
+that contains the type definition for the specified name-value pair.
+The \fInvname\fP field contains the name for the type.
+.PP
+The \f5nv_settype()\fP function converts the name-value pair
+given by \fInp\fP into the type given by \fItp\fP.
+.PP
+The \f5nv_addtype()\fP function adds the name of the type given by
+\fInp\fP to the list of declaration built-ins. The \fIstr\fP
+argument contains the string used by \f5optget\fP(3) to generate
+the man page and process the options. The \fIop\fP argument
+specifies the callback discipline used by \f5optget\fP(3) and
+\fIsz\fP specifies the size of the callback information so
+that the discipline \fBoptget\fP(3) can be extended with private
+data used by the callback function.
+.P
+The \f5nv_mkinttype()\fP function creates named integer types
+of the specified \fIname\fP. The \fIsize\fP parameter is the size
+in bytes of the integer variable and \fIus\fP is non-zero
+for unsigned integer types. If \fIdp\fP is specified then integer
+variables of this type will all use this discipline.
+.SH SEE ALSO
+calloc(3)
+cdt(3)
+shell(3)
+optget(3)
+.SH AUTHOR
+David G. Korn (dgk@research.att.com).
diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1
new file mode 100644
index 0000000..27d8a9e
--- /dev/null
+++ b/src/cmd/ksh93/sh.1
@@ -0,0 +1,8142 @@
+.\"
+.\" David Korn
+.\" AT&T Bell Laboratories
+.\"
+.\" @(#)sh.1 (dgk@research.att.com) 12/28/93
+.\"
+.nr Z 1 \" set to 1 when command name is ksh, 2 for ksh93
+.ds OK [\|
+.ds CK \|]
+.ds ' \s+4\v@.3m@\'\v@-.3m@\s-4
+.ds ` \s+4\v@.3m@\`\v@-.3m@\s-4
+.if \nZ=0 \{\
+.TH SH 1
+.\}
+.if \nZ=1 \{\
+.TH KSH 1
+.\}
+.if \nZ=2 \{\
+.TH KSH93 1
+.\}
+.SH NAME
+.if \nZ=0 \{\
+sh, rsh, pfsh \- shell, the standard/restricted command and programming language
+.\}
+.if \nZ=1 \{\
+ksh, rksh, pfksh \- KornShell, a standard/restricted command and programming language
+.\}
+.if \nZ=2 \{\
+ksh93, rksh93, pfksh93 \- KornShell, a standard/restricted command and programming language
+.\}
+.SH SYNOPSIS
+.if \nZ=0 \{\
+.B sh
+.\}
+.if \nZ=1 \{\
+.B ksh
+.\}
+.if \nZ=2 \{\
+.B ksh93
+.\}
+[
+.B \(+-abcefhikmnoprstuvxBCDP
+] [
+.B \-R
+file ] [
+.B \(+-o
+option ] .\|.\|. [
+.B \-
+] [ arg .\|.\|. ]
+.br
+.if \nZ=0 \{\
+.B rsh
+.\}
+.if \nZ=1 \{\
+.B rksh
+.\}
+.if \nZ=2 \{\
+.B rksh93
+.\}
+[
+.B \(+-abcefhikmnoprstuvxBCD
+] [
+.B \-R
+file ] [
+.B \(+-o
+option ] .\|.\|. [
+.B \-
+] [ arg .\|.\|. ]
+.SH DESCRIPTION
+.if \nZ=0 .I Sh\^
+.if \nZ=1 .I Ksh\^
+.if \nZ=2 .I Ksh93\^
+is a command and programming language
+that executes commands read from a terminal
+or a file.
+.if \nZ=0 .I Rsh\^
+.if \nZ=1 .I Rksh\^
+.if \nZ=2 .I Rksh93\^
+is a restricted version of the
+.if \nZ=0 standard
+command interpreter
+.if \nZ=0 .IR sh ;
+.if \nZ=1 .IR ksh ;
+.if \nZ=2 .IR ksh93 ;
+it is used to set up login names and execution environments whose
+capabilities are more controlled than those of the standard shell.
+.if \nZ=0 .I Rpfsh\^
+.if \nZ=1 .I Rpfksh\^
+.if \nZ=2 .I Rpfksh93\^
+is a profile shell version of the
+.if \nZ=0 standard
+command interpreter
+.if \nZ=0 .IR sh ;
+.if \nZ=1 .IR ksh ;
+.if \nZ=2 .IR ksh93 ;
+it is used to to execute commands with the attributes specified by
+the user's profiles (see
+.IR pfexec (1)).
+See
+.I Invocation\^
+below
+for the meaning of arguments to the shell.
+.SS Definitions.
+A
+.I metacharacter\^
+is one of the following characters:
+.PP
+.RS
+\f3; & ( ) \(bv < > new-line space tab\fP
+.RE
+.PP
+A
+.I blank\^
+is a
+.B tab
+or a
+.BR space .
+An
+.I identifier\^
+is a sequence of letters, digits, or underscores
+starting with a letter or underscore.
+Identifiers are used as components of
+.I variable\^
+names.
+A
+.I vname\^
+is a sequence of one or more identifiers
+separated by a \fB\s+2.\s-2\fP and optionally preceded
+by a \fB\s+2.\s-2\fP.
+Vnames are used as function and variable names.
+A
+.I word\^
+is a sequence of
+.I characters\^
+from the character set defined by the current locale,
+excluding non-quoted
+.IR metacharacters .
+.PP
+A
+.I command\^
+is a sequence of characters in the syntax
+of the shell language.
+The shell reads each command and
+carries out the desired action either directly or by invoking
+separate utilities.
+A built-in command is a command that is carried out by the
+shell itself without creating a separate process.
+Some commands are built-in purely for convenience
+and are not documented here.
+Built-ins that cause
+side effects in the shell environment and
+built-ins that are found before performing a
+path search (see
+.I Execution\^
+below)
+are documented here.
+For historical reasons, some of
+these built-ins behave differently than
+other built-ins and are called
+.IR "special built-ins" .
+.SS Commands.
+A
+.I simple-command\^
+is a list of variable assignments
+(see
+.I Variable Assignments\^
+below)
+or a sequence of
+.I blank\^
+separated words
+which may be preceded by a list of variable assignments
+(see
+.I Environment\^
+below).
+The first word specifies the name of the command to
+be executed.
+Except as specified below,
+the remaining words are passed as arguments
+to the invoked command.
+The command name is passed as argument 0
+(see
+.IR exec (2)).
+The
+.I value\^
+of a simple-command is its exit status; 0-255
+if it terminates normally; 256+\f2signum\^\fP if
+it terminates abnormally (the name of the signal corresponding
+to the exit status can be
+obtained via the
+.B \-l
+option of the
+.B kill\^
+built-in utility).
+.PP
+A
+.I pipeline\^
+is a sequence of one or more
+.I commands\^
+separated by
+.BR \(bv .
+The standard output of each command but the last
+is connected by a
+.IR pipe (2)
+to the standard input of the next command.
+Each command,
+except possibly the last,
+is run as a separate process;
+the shell waits for the last command to terminate.
+The exit status of a pipeline is the exit
+status of the last command unless the
+.B pipefail
+option is enabled.
+Each pipeline can be preceded by the
+.I "reserved word"
+.B !
+which causes the exit status of the pipeline to become
+0 if the exit status of the last command is non-zero, and
+1 if the exit status of the last command is 0.
+.PP
+A
+.I list\^
+is a sequence of one or more
+pipelines
+separated by
+.BR ; ,
+.BR & ,
+.BR \(bv& ,
+.BR && ,
+or
+.BR \(bv\|\(bv ,
+and optionally terminated by
+.BR ; ,
+.BR & ,
+or
+.BR \(bv& .
+Of these five symbols,
+.BR ; ,
+.BR & ,
+and
+.B \(bv&
+have equal precedence,
+which is lower than that of
+.B &&
+and
+.BR \(bv\|\(bv .
+The symbols
+.B &&
+and
+.B \(bv\|\(bv
+also have equal precedence.
+A semicolon
+.RB ( ; )
+causes sequential execution of the preceding pipeline; an ampersand
+.RB ( & )
+causes asynchronous execution of the preceding pipeline (i.e., the shell does
+.I not\^
+wait for that pipeline to finish).
+The symbol
+.B \(bv&
+causes asynchronous execution of the preceding pipeline
+with a two-way pipe established to the parent shell;
+the standard input and output of the spawned pipeline
+can be written to and read from by the parent shell
+by applying
+the redirection operators
+.B <&
+and
+.B >&
+with arg
+.B p
+to commands and by using
+.B \-p
+option of
+the built-in commands
+.B read
+and
+.B print
+described later.
+The symbol
+.B &&
+.RB (\| \(bv\|\(bv \^)
+causes the
+.I list\^
+following it to be executed only if the preceding
+pipeline
+returns a zero (non-zero) value.
+One or more new-lines may appear in a
+.I list\^
+instead of a semicolon,
+to delimit a command.
+The first
+.I item \^
+of the first
+.I pipeline\^
+of a
+.I list\^
+that is a simple command not beginning
+with a redirection, and not occurring within a
+.BR while ,
+.BR until ,
+or
+.B if
+.IR list ,
+can be preceded by a semicolon.
+This semicolon
+is ignored unless the
+.B showme
+option is enabled as described with
+the
+.B set
+built-in below.
+.PP
+A
+.I command\^
+is either a simple-command
+or one of the following.
+Unless otherwise stated,
+the value returned by a command is that of the
+last simple-command executed in the command.
+.TP
+\f3for\fP \f2vname\^\fP \*(OK \f3in\fP \f2word\^\fP .\|.\|. \*(CK \f3;do\fP \f2list\^\fP \f3;done\fP
+Each time a
+.B for
+command is executed,
+.I vname\^
+is set to the next
+.I word\^
+taken from the
+.B in
+.I word\^
+list.
+If
+.BI in " word\^"
+\&.\|.\|.
+is omitted, then
+the
+.B for
+command executes the \f3do\fP \f2list\^\fP once for each positional parameter
+that is set starting from
+.B 1
+(see
+.I "Parameter Expansion\^"
+below).
+Execution ends when there are no more words in the list.
+.TP
+\f3for ((\fP \*(OK\f2expr1\^\fP\*(CK \f3;\fP \*(OK\f2expr2\^\fP\*(CK \f3;\fP \*(OK\f2expr3\^\fP\*(CK \f3))\fP \f3;do\fP \f2list\^\fP \f3;done\fP
+The arithmetic expression
+.I expr1
+is evaluated first
+(see
+.I "Arithmetic evaluation"
+below).
+The arithmetic expression
+.I expr2
+is repeatedly evaluated until it evaluates to zero and when non-zero,
+.I list
+is executed and the arithmetic expression
+.I expr3
+evaluated.
+If any expression
+is omitted, then it behaves as if it evaluated to 1.
+.TP
+\f3select\fP \f2vname\^\fP \*(OK \f3in\fP \f2word\^\fP .\|.\|. \*(CK \f3;do\fP \f2list\^\fP \f3;done\fP
+A
+.B select
+command prints on standard error (file descriptor 2) the set of
+.IR word s,
+each preceded by a number.
+If
+.BI in " word\^"
+\&.\|.\|.
+is omitted, then
+the
+positional parameters starting from
+.B 1
+are used instead
+(see
+.I "Parameter Expansion\^"
+below).
+The
+.SM
+.B PS3
+prompt is printed
+and a line is read from the standard input.
+If this line consists of the number
+of one of the listed
+.IR word s,
+then the value of the variable
+.I vname\^
+is set to the
+.I word\^
+corresponding to this number.
+If this line is empty, the selection list is
+printed again.
+Otherwise the value of the variable
+.I vname\^
+is set to
+.IR null .
+The contents of the line read from standard input is
+saved in
+the variable
+.SM
+.BR REPLY .
+The
+.I list\^
+is executed for each selection until a
+.B break\^
+or
+.I end-of-file\^
+is encountered.
+If the
+.SM
+.B REPLY
+variable is set to
+.I null\^
+by the execution of
+.IR list ,
+then the selection list is printed before
+displaying the
+.SM
+.B PS3
+prompt for the next selection.
+.TP
+\f3case\fP \f2word\^\fP \f3in\fP \*(OK \*(OK\f3(\fP\*(CK\f2pattern\^\fP \*(OK \(bv \f2pattern\^\fP \*(CK .\|.\|. \f3)\fP \f2list\^\fP \f3;;\fP \*(CK .\|.\|. \f3esac\fP
+A
+.B case
+command executes the
+.I list\^
+associated with the first
+.I pattern\^
+that matches
+.IR word .
+The form of the patterns is
+the same as that used for
+file-name generation (see
+.I "File Name Generation\^"
+below).
+The
+.B ;;
+operator causes execution of
+.B case
+to terminate.
+If
+.B ;&
+is used in place of
+.B ;;
+the next subsequent list, if any, is executed.
+.TP
+\f3if\fP \f2list\^\fP \f3;then\fP \f2list\^\fP \*(OK \
+\f3;elif\fP \f2list\^\fP \f3;then\fP \f2list\^\fP \*(CK .\|.\|. \
+\*(OK \f3;else\fP \f2list\^\fP \*(CK \f3;f\&i\fP
+The
+.I list\^
+following \f3if\fP is executed and,
+if it
+returns a zero exit status, the
+.I list\^
+following
+the first
+.B then
+is executed.
+Otherwise, the
+.I list\^
+following \f3elif\fP
+is executed and, if its value is zero,
+the
+.I list\^
+following
+the next
+.B then
+is executed.
+Failing each successive
+.B elif
+.IR list\^ ,
+the
+.B else
+.I list\^
+is executed.
+If the
+.B if
+.I list\^
+has non-zero exit status
+and there is no
+.B else
+.IR list ,
+then the
+.B if
+command returns a zero exit status.
+.TP
+.PD 0
+\f3while\fP \f2list\^\fP \f3;do\fP \f2list\^\fP \f3;done\fP
+.TP
+\f3until\fP \f2list\^\fP \f3;do\fP \f2list\^\fP \f3;done\fP
+.PD
+A
+.B while
+command repeatedly executes the
+.B while
+.I list\^
+and, if the exit status of the last command in the list is zero, executes
+the
+.B do
+.IR list ;
+otherwise the loop terminates.
+If no commands in the
+.B do
+.I list\^
+are executed, then the
+.B while
+command returns a zero exit status;
+.B until
+may be used in place of
+.B while
+to negate
+the loop termination test.
+.TP
+\f3((\fP\f2expression\^\fP\f3))\fP
+.br
+The
+.I expression\^
+is evaluated using the rules for arithmetic evaluation described below.
+If the value of the arithmetic expression is non-zero, the exit
+status is 0, otherwise the exit status is 1.
+.TP
+\f3(\fP\f2list\^\fP\f3)\fP
+.br
+Execute
+.I list\^
+in a separate environment.
+Note, that if two adjacent open parentheses are
+needed for nesting, a space must be inserted to avoid
+evaluation as an arithmetic command as described above.
+.TP
+\f3{ \fP\f2list\^\fP\f3;}\fP
+.br
+.I list\^
+is simply executed.
+Note that unlike the metacharacters
+.B (
+and
+.BR ) ,
+.B {
+and
+.B }
+are
+.IR "reserved word" s
+and must occur
+at the beginning of a line or after a
+.B ;
+in order to be recognized.
+.TP
+\f3[[\fP\f2 expression \^\fP\f3]]\fP
+.br
+Evaluates
+.I expression\^
+and returns a zero exit status when
+.I expression\^
+is true.
+See
+.I "Conditional Expressions\^"
+below, for a description of
+.IR expression .
+.TP
+.PD 0
+\f3function\fP \f2varname\^\fP \f3{\fP \f2list\^\fP \f3;}\fP
+.TP
+\f2varname\^\fP \f3() {\fP \f2list\^\fP \f3;}\fP
+.PD
+Define a function which is referenced by
+.IR varname .
+A function whose
+.I varname\^
+contains a
+.B \s+2.\s-2
+is called a discipline function and the portion
+of the
+.I varname\^
+preceding the last
+.B \s+2.\s-2
+must refer to an existing variable.
+The body of the function is the
+.I list\^
+of commands between
+.B {
+and
+.BR } .
+A function defined with the \f3function\fP \f2varname\^\fP
+syntax can also be used as an argument to the \f3.\fP
+special built-in command to get the equivalent behavior
+as if the \f2varname\^\fP\f3()\fP syntax were used to define it.
+(See
+.I Functions\^
+below.)
+.TP
+\f3namespace\fP \f2identifier\^\fP \f3{\fP \f2list\^\fP \f3;}\fP
+.br
+Defines or uses the name space
+.I identifier\^
+and runs the commands in
+.I list\^
+in this name space.
+(See
+.I Name Spaces\^
+below.)
+.TP
+\f3&\fP \*(OK \f2name\^\fP \*(OK \f2arg...\^\fP \*(CK \*(CK
+Causes subsequent
+.I list\^
+commands terminated by
+.B &
+to be placed in the background job pool
+.IR name .
+If
+.I name\^
+is omitted a default unnamed pool is used.
+Commands in a named background pool may be executed remotely.
+.TP
+\f3time\fP \*(OK \f2pipeline\^\fP \*(CK
+.br
+If \f2pipeline\^\fP is omitted the user and system time for
+the current shell and completed child processes is printed
+on standard error.
+Otherwise,
+.I pipeline\^
+is executed and the elapsed time as well as
+the user and system time are printed on standard error.
+The
+.SM
+.B TIMEFORMAT
+variable may be set to a format string that specifies how the timing
+information should be displayed.
+See
+.B "Shell Variables"
+below
+for a description of the
+.SM
+.B TIMEFORMAT
+variable.
+.PP
+The following reserved words
+are recognized as reserved only when they are the first word of a command
+and are not quoted:
+.PP
+.if t .RS
+.B
+.if n if then else elif fi case esac for while until do done { } function select time [[ ]] !
+.if t if then else elif fi case esac for while until do done { } function select time [[ ]] !
+.if t .RE
+.SS Variable Assignments.
+One or more variable assignments can start a simple command
+or can be arguments to the
+.BR typeset ,
+.BR enum ,
+.BR export ,
+or
+.B readonly
+special built-in commands as well as
+to other declaration commands created as types.
+The syntax for an \f2assignment\^\fP is of the form:
+.TP
+.PD 0
+\f2varname\^\fP\f3=\fP\f2word\^\fP
+.TP
+\f2varname\^\fP\f3[\fP\f2word\^\fP\f3]\fP=\fP\f2word\^\fP
+.PD
+No space is permitted between \f2varname\^\fP and the \f3=\fP or
+between \f3=\fP and \fIword\^\fP.
+.TP
+\f2varname\^\fP\f3=(\fP\f2assign_list\^\fP\f3)\fP
+No space is permitted between \f2varname\^\fP and the \f3=\fP.
+The variable
+.I varname
+is unset before the assignment.
+An \f2assign_list\^\fP can be one of the following:
+.RS 15
+.PD 0
+.TP
+\f2word\^\fP ...
+Indexed array assignment.
+.TP
+\f3[\fP\f2word\^\fP\f3]=\fP\f2word\^\fP .\|.\|.
+Associative array assignment.
+If preceded by
+.B typeset \-a
+this will create an indexed array instead.
+.TP
+\f2assignment\^\fP .\|.\|.
+Compound variable assignment.
+This creates a compound variable \f2varname\^\fP with
+sub-variables of the form \f2varname\^\fP\f3.\fP\f2name\^\fP,
+where \f2name\^\fP is the name portion of \f2assignment\^\fP.
+The value of \f2varname\^\fP will contain all the assignment elements.
+Additional assignments made to sub-variables of \f2varname\^\fP
+will also be displayed as part of the value of \f2varname\^\fP.
+If no \f2assignment\fPs are specified, \f2varname\^\fP will be
+a compound variable allowing subsequence child elements to be defined.
+.TP
+\f3typeset\fP \*(OK\f2options\fP\*(CK \f2assignment\^\fP .\|.\|.
+Nested variable assignment. Multiple assignments
+can be specified by separating each of them with a \f3;\fP.
+The previous value is unset before the assignment.
+Other declaration commands such as
+.BR readonly,
+.BR enum ,
+and
+other declaration commands can be used in place of
+.BR typeset .
+.TP
+\f3\|.\fP \f2filename\^\fP
+Include the assignment commands contained in
+.IR filename .
+.PD
+.RE
+.PP
+In addition, a \f3+=\fP can be used in place of the \f3=\fP
+to signify adding to or appending to the previous value.
+When \f3+=\fP is applied to an arithmetic type, \f2word\^\fP
+is evaluated as an arithmetic expression and added to the current value.
+When applied to a string variable, the value defined by \f2word\^\fP
+is appended to the value. For compound assignments, the previous
+value is not unset and the new values are appended to the
+current ones provided that the types are compatible.
+.PP
+The right hand side of a variable assignment undergoes all the expansion
+listed below except word splitting, brace expansion, and file name generation.
+When the left hand side is an assignment is a compound variable and
+the right hand is the name of a compound variable, the compound variable
+on the right will be copied or appended to the compound variable on the left.
+.SS Comments.
+.PD 0
+A word beginning with
+.B #
+causes that word and all the following characters up to a new-line
+to be ignored.
+.SS Aliasing.
+The first word of each command is replaced by the text of an
+.B alias
+if an
+.B alias
+for this word has been defined.
+An
+.B alias
+name consists of any number of characters excluding metacharacters,
+quoting characters,
+file expansion characters,
+parameter expansion and command substitution
+characters,
+the characters
+.B /
+and
+.BR = .
+The replacement string can contain any
+valid shell script
+including the metacharacters listed above.
+The first word of each command in the
+replaced text,
+other than
+any that are in the process of being replaced,
+will be tested for aliases.
+If the last character of the alias value is a
+.I blank\^
+then the word following the alias will also be checked for alias
+substitution.
+Aliases can be used to redefine
+built-in commands but cannot be used to redefine
+the reserved words listed above.
+Aliases can be created and listed with the
+.B alias
+command and can be removed with the
+.B unalias
+command.
+.PP
+.I Aliasing\^
+is performed when
+scripts are read,
+not while they are executed.
+Therefore,
+for an alias to take effect,
+the
+.B
+alias
+definition command has to be executed before
+the command which references the alias is read.
+.PP
+The following aliases
+are compiled into the shell
+but can be unset or redefined:
+.RS 20
+.PD 0
+.TP
+.B "autoload=\(fmtypeset \-fu\(fm"
+.TP
+.B "command=\(fmcommand \(fm"
+.TP
+.B "compound=\(fmtypeset \-C\(fm"
+.TP
+.B "fc=hist"
+.TP
+.B "float=\(fmtypeset \-lE\(fm"
+.TP
+.B "functions=\(fmtypeset \-f\(fm"
+.TP
+.B "hash=\(fmalias \-t \-\^\-\(fm"
+.TP
+.B "history=\(fmhist \-l\(fm"
+.TP
+.B "integer=\(fmtypeset \-li\(fm"
+.TP
+.B "nameref=\(fmtypeset \-n\(fm"
+.TP
+.B "nohup=\(fmnohup \(fm"
+.TP
+.B "r=\(fmhist \-s\(fm"
+.TP
+.B "redirect=\(fmcommand exec\(fm"
+.TP
+.B "source=\(fmcommand \s+2.\s-2\(fm"
+.TP
+.B "stop=\(fmkill \-s \s-1STOP\s+1\(fm"
+.TP
+.B "suspend=\(fmkill \-s \s-1STOP\s+1 $$\(fm"
+.TP
+.B "times=\(fm{ { time;} 2>&1;}\(fm"
+.TP
+.B "type=\(fmwhence \-v\(fm"
+.PD
+.RE
+.SS Tilde Substitution.
+After alias substitution is performed, each word
+is checked to see if it begins with an unquoted
+.BR \(ap .
+For tilde substitution,
+.I word\^
+also refers to the
+.I word\^
+portion of parameter expansion
+(see
+.I "Parameter Expansion\^"
+below).
+If it does, then the word up to a
+.B /
+is checked to see if it matches a user name in the
+password database (See
+.IR getpwname (3).)
+If a match is found, the
+.B \(ap
+and the matched login name are replaced by the
+login directory of the matched user.
+If no match is found, the original text is left unchanged.
+A
+.B \(ap
+by itself, or in front of a
+.BR / ,
+is replaced by
+.SM
+.BR $HOME .
+A
+.B \(ap
+followed by a
+.B +
+or
+.B \-
+is replaced by the value of
+.B
+.SM $PWD
+and
+.B
+.SM $OLDPWD
+respectively.
+.PP
+In addition,
+when expanding a
+.IR "variable assignment" ,
+.I tilde
+substitution is attempted when
+the value of the assignment
+begins with a
+.BR \(ap ,
+and when a
+.B \(ap
+appears after a
+.BR : .
+The
+.B :
+also terminates a
+.B \(ap
+login name.
+.SS Command Substitution.
+The standard output from a command list enclosed in
+parentheses preceded by a dollar sign (
+\f3$(\fP\f2list\^\fP\f3)\fP
+),
+or in a brace group preceded by a dollar sign (
+\f3${ \fP\f2list\^\fP\f3;}\fP
+), or in a pair of grave accents (\^\f3\*`\^\*`\fP\^)
+may be used as part or all
+of a word;
+trailing new-lines are removed.
+In the second case, the \f3{\fP and \f3}\fP are treated as a reserved words
+so that \f3{\fP must be followed by a \f2blank\^\fP and \f3}\fP must
+appear at the beginning of the line or follow a \f3;\fP.
+In the third (obsolete) form, the string between the quotes is processed
+for special quoting characters before the command is executed (see
+.I Quoting\^
+below).
+The command substitution
+\^\f3$(\^cat file\^)\fP\^
+can be replaced by the equivalent but faster
+\^\f3$(\^<file\^)\fP\^.
+The command substitution
+\^\f3$(\^\fP\f2n\^\fP\f3<#\^)\fP
+will expand to the current byte offset for file descriptor
+.IR n .
+Except for the second form, the command list is run in a subshell so that no
+side effects are possible.
+For the second form, the final
+.B }
+will be recognized as a reserved word after any token.
+.SS Arithmetic Substitution.
+An arithmetic expression enclosed in double
+parentheses preceded by a dollar sign (
+.B $((\|))
+)
+is replaced by the value of the arithmetic expression
+within the double parentheses.
+.SS Process Substitution.
+Each command argument of the form
+\f3<(\fP\f2list\^\fP\f3)\fP
+or
+\f3>(\fP\f2list\^\fP\f3)\fP
+will run process
+.I list
+asynchronously connected to some file in
+.B /dev/fd
+if this directory exists, or else a fifo a temporary directory.
+The name of this file will become the argument to the command.
+If the form with
+.B >
+is selected then writing on this file will provide input for
+.IR list .
+If
+.B <
+is used,
+then the file passed as an argument will contain the output of the
+.I list
+process.
+For example,
+.PP
+.RS
+\f3paste <(cut \-f1\fP \f2file1\fP\f3) <(cut \-f3\fP \f2file2\f3) | tee >(\fP\f2process1\fP\f3) >(\fP\f2process2\fP\f3)\fP
+.RE
+.PP
+.I cuts
+fields 1 and 3 from
+the files
+.I file1
+and
+.I file2
+respectively,
+.I pastes
+the results together, and
+sends it
+to the processes
+.I process1
+and
+.IR process2 ,
+as well as putting it onto the standard output.
+Note that the file, which is passed as an argument to the command,
+is a UNIX
+.IR pipe (2)
+so programs that expect to
+.IR lseek (2)
+on the file will not work.
+.PP
+Process substitution of the form
+\f3<(\fP\f2list\^\fP\f3)\fP
+can also be used with the
+.B <
+redirection operator which causes the output of
+.I list\^
+to be standard input or the input for whatever file descriptor is specified.
+.SS Parameter Expansion.
+A
+.I parameter\^
+is a
+.IR variable ,
+one or more digits,
+or any of the characters
+.BR \(** ,
+.BR @ ,
+.BR # ,
+.BR ? ,
+.BR \- ,
+.BR $ ,
+and
+.BR !\\^ .
+A
+.I variable\^
+is denoted by a \f2vname\fP.
+To create a variable whose
+.I vname\^
+contains a \f3\s+2.\s-2\fP,
+a variable whose
+.I vname\^
+consists of everything before the last \f3\s+2.\s-2\fP must already exist.
+A
+.I variable\^
+has a
+.I value\^
+and zero or more
+.IR attributes .
+.I Variables\^
+can be assigned
+.I values\^
+and
+.I attributes
+by using the
+.B typeset\^
+special built-in command.
+The attributes supported by the shell are described
+later with the
+.B typeset\^
+special built-in command.
+Exported variables pass values and attributes to
+the environment.
+.PP
+The shell supports both indexed and associative arrays.
+An element of an array variable is referenced by a
+.IR subscript .
+A
+.I subscript\^
+for an indexed array is denoted by
+an
+.I arithmetic expression\^
+(see
+.I "Arithmetic evaluation"
+below)
+between a
+.B [
+and a
+.BR ] .
+To assign values to an indexed array, use
+\f2vname\fP\f3=(\fP\f2value\fP .\|.\|.\f3)\fP or
+\f3set \-A\fP \f2vname\fP \f2value\fP .\|.\|. .
+The value of all non-negative
+subscripts must be in the
+range of
+0 through 4,194,303.
+A negative subscript is treated as an offset from the maximum
+current index +1 so that \-1 refers to the last element.
+Indexed arrays can be declared with the
+.B \-a
+option to
+.BR typeset.
+Indexed arrays need not be declared.
+Any reference to a variable
+with a valid subscript is
+legal and an array will be created if necessary.
+.PP
+An associative array is created with the
+.B \-A
+option to
+.BR typeset.
+A
+.I subscript\^
+for an associative array is denoted by
+a string enclosed between
+.B [
+and
+.BR ] .
+.PP
+Referencing any array without a subscript
+is equivalent to referencing the array with subscript 0.
+.PP
+The
+.I value\^
+of a
+.I variable\^
+may be assigned by writing:
+.PP
+.RS
+.IB vname = value\^\|
+\*(OK
+.IB vname = value\^
+\*(CK .\|.\|.
+.RE
+.PP
+.PD 0
+or
+.PP
+.RS
+.IB vname [ subscript ]= value\^\|
+\*(OK
+.IB vname [ subscript ]= value\^
+\*(CK .\|.\|.
+.sp .5
+.RE
+Note that no space is allowed before or after the
+.BR = .
+.sp .5
+.PP
+.PD 0
+Attributes assigned by the
+.I typeset\^
+special built-in command apply to all elements of the array.
+An array element can be a simple variable, a compound variable or an
+array variable. An element of an indexed array can be either an indexed
+array or an associative array. An element of an associative array can also
+be either. To refer to an array element that is part of an array
+element, concatenate the subscript in brackets. For example, to refer
+to the
+.I foobar\^
+element of an associative array that is defined as the
+third element of the indexed array, use
+.BI ${ vname [ 3 ][ foobar ]}
+.sp .5
+.PP
+.PD 0
+A
+.I nameref\^
+is a variable that is a reference to another variable.
+A nameref is created with the
+.B \-n
+attribute of
+.BR typeset .
+The value of the variable at the time of the
+.B typeset
+command becomes the variable that will be referenced whenever
+the nameref variable is used.
+The name of a nameref cannot contain a \fB\s+2.\s-2\fP.
+When a variable or function name contains a \fB\s+2.\s-2\fP, and the portion
+of the name up to the first \fB\s+2.\s-2\fP matches the
+name of a nameref, the variable referred to is obtained by
+replacing the nameref portion with the name of the variable
+referenced by the nameref.
+If a nameref is used as the index of a \fBfor\fP loop,
+a name reference is established for each item in the list.
+A nameref provides a convenient way to refer to the variable
+inside a function whose name is passed as an argument to a function.
+For example, if the name of a variable is passed as the first
+argument to a function, the command
+.PP
+.RS
+\fBtypeset \-n var=$1\fR
+.RE
+.PP
+inside the function causes references and assignments to
+.B var
+to be references and assignments to the variable whose
+name has been passed to the function.
+.sp .5
+.PP
+If any of the floating point attributes,
+.BR \-E ,
+.BR \-F ,
+or
+.BR \-X ,
+or the integer attribute,
+.BR \-i ,
+is set for
+.IR vname ,
+then the
+.I value\^
+is subject to arithmetic evaluation as described below.
+.sp .5
+.PP
+Positional parameters,
+parameters denoted by a number,
+may be assigned values with the
+.B set\^
+special built-in command.
+Parameter
+.B $0
+is set from argument zero when the shell
+is invoked.
+.sp .5
+.PP
+The character
+.B $
+is used to introduce substitutable
+.IR parameters .
+.TP
+\f3${\fP\f2parameter\^\fP\f3}\fP
+The shell
+reads all the characters from
+.B ${
+to the matching
+.B }
+as part of the same word even if it contains
+braces or metacharacters.
+The value, if any, of the parameter is substituted.
+The braces are required when
+.I parameter\^
+is followed by a letter, digit, or underscore
+that is not to be interpreted as part of its name,
+when the variable name contains a \fB\s+2.\s-2\fP.
+The braces are also required when a variable is subscripted
+unless it is part of an Arithmetic Expression
+or a Conditional Expression.
+If
+.I parameter\^
+is one or more digits then it is a positional parameter.
+A positional parameter of more than one digit must be
+enclosed in braces.
+If
+.I parameter\^
+is
+.B \(**
+or
+.BR @ ,
+then all the positional
+parameters, starting with
+.BR $1 ,
+are substituted
+(separated by a field separator character).
+If an array
+.I vname\^
+with last subscript
+.B \(**
+.BR @ ,
+or for index arrays of the form
+.I sub1\^
+.B ..
+.IR sub2 .
+is used,
+then the value
+for each of the
+elements between
+.I sub1\^
+and
+.I sub2\^
+inclusive (or all elements for
+.B \(**
+and
+.BR @ )
+is substituted,
+separated by
+the first character of
+the value of
+.SM
+.BR IFS .
+.TP
+\f3${#\fP\f2parameter\^\fP\f3}\fP
+If
+.I parameter\^
+is
+.B \(**
+or
+.BR @ ,
+the number of positional parameters is substituted.
+Otherwise, the length of the value of the
+.I parameter\^
+is substituted.
+.TP
+.PD 0
+\f3${#\fP\f2vname\fP\f3[*]}\fP
+.TP
+.PD
+\f3${#\fP\f2vname\fP\f3[@]}\fP
+The number of elements in the array
+.I vname\^
+is substituted.
+.TP
+.PD 0
+\f3${@\fP\f2vname\^\fP\f3}\fP
+Expands to the type name (See
+.I "Type Variables"\^
+below) or attributes of the variable referred to by
+.IR vname .
+.TP
+\f3${!\fP\f2vname\^\fP\f3}\fP
+Expands to the name of the variable referred to by
+.IR vname .
+This will be
+.I vname\^
+except when
+.I vname\^
+is a name reference.
+.TP
+\f3${!\fP\f2vname\^\fP\f3[\f2subscript\^\f3]}\fP
+Expands to name of the subscript unless
+.I subscript\^
+is
+.BR * ,
+.BR @ .
+or of the form
+.I sub1\^
+.B ..
+.IR sub2 .
+When
+.I subscript\^
+is
+.BR * ,
+the list of array subscripts for \f2vname\^\fP
+is generated.
+For a variable that is not an array, the value is 0 if the variable
+is set. Otherwise it is null.
+When
+.I subscript\^
+is
+.BR @ ,
+same as above, except that when used in double quotes,
+each array subscript yields a separate
+argument.
+When
+.I subscript\^
+is of the form
+.I sub1\^
+.B ..
+.I sub2\^
+it expands
+to the list of subscripts between
+.I sub1\^
+and
+.I sub2\^
+inclusive using the same quoting rules as
+.BR @ .
+.TP
+\f3${!\fP\f2prefix\^\fP\f3*}\fP
+Expands to the names of the variables whose names begin with
+.IR prefix .
+.TP
+\f3${\fP\f2parameter\^\fP\f3:\-\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is set and is non-null then substitute its value;
+otherwise substitute
+.IR word .
+.TP
+\f3${\fP\f2parameter\^\fP\f3:=\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is not set or is null then set it to
+.IR word ;
+the value of the parameter is then substituted.
+Positional parameters may not be assigned to
+in this way.
+.TP
+\f3${\fP\f2parameter\^\fP\f3:?\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is set and is non-null then substitute its value;
+otherwise, print
+.I word\^
+and exit from the shell (if not interactive).
+If
+.I word\^
+is omitted then a standard message is printed.
+.TP
+\f3${\fP\f2parameter\^\fP\f3:+\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is set and is non-null then substitute
+.IR word ;
+otherwise substitute nothing.
+.PP
+In the above,
+.I word\^
+is not evaluated unless it is
+to be used as the substituted string,
+so that, in the following example,
+.B pwd
+is executed only if
+.B d
+is not set or is null:
+.PP
+.RS
+print \|${d:\-\^$(\^pwd\^)\^}
+.RE
+.PP
+If the colon (
+.B : )
+is omitted from the above expressions,
+then the shell only checks whether
+.I parameter\^
+is set or not.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3:\fP\f2offset\^\fP\f3:\fP\f2length\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3:\fP\f2offset\^\fP\f3}\fP
+Expands to the portion of the value of
+.I parameter\^
+starting at the character (counting from
+.BR 0\^ )
+determined by expanding
+.I offset\^
+as an arithmetic expression and consisting of the
+number of characters determined by the arithmetic expression
+defined by
+.IR length.
+In the second form, the remainder of the value is used.
+If
+A negative
+.I offset\^
+counts backwards from the end of
+.IR parameter .
+Note that one or more
+.IR blank s
+is required in front of a minus sign
+to prevent the shell from interpreting the operator as
+.BR :\- .
+If
+.I parameter\^
+is
+.B \(**
+or
+.BR @ ,
+or is an array name indexed by
+.B \(**
+or
+.BR @ ,
+then
+.I offset\^
+and
+.I length\^
+refer to the array index and number
+of elements respectively.
+A negative
+.I offset\^
+is taken relative to one greater than the highest subscript
+for indexed arrays.
+The order for associate arrays is unspecified.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3#\fP\f2pattern\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3##\fP\f2pattern\^\fP\f3}\fP
+.PD
+If
+the shell
+.I pattern\^
+matches the beginning of the value of
+.IR parameter ,
+then the value of
+this expansion is the value of the
+.I parameter\^
+with the matched portion deleted;
+otherwise the value of this
+.I parameter\^
+is substituted.
+In the first form the smallest matching pattern is deleted and in the
+second form the largest matching pattern is deleted.
+When
+.I parameter\^
+is
+.BR @ ,
+.BR * ,
+or an array variable with subscript
+.B @
+or
+.BR * ,
+the substring operation is applied to each element in turn.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3%\fP\f2pattern\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3%%\fP\f2pattern\^\fP\f3}\fP
+.PD
+If
+the shell
+.I pattern\^
+matches the end of the value of
+.IR parameter ,
+then the value of
+this expansion is the value of the
+.I parameter\^
+with the matched part deleted;
+otherwise substitute the value of
+.IR parameter .
+In the first form the smallest matching pattern is deleted and in the
+second form the largest matching pattern is deleted.
+When
+.I parameter\^
+is
+.BR @ ,
+.BR * ,
+or an array variable with subscript
+.B @
+or
+.BR * ,
+the substring operation is applied to each element in turn.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3/\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3//\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3/#\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3/%\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.PD
+Expands
+.I parameter\^
+and replaces the longest match of
+.I pattern\^
+with the given
+.IR string.
+Each occurrence of \f3\e\fP\f2n\^\fP in
+.I string
+is replaced by the portion of \f2parameter\^\fP
+that matches the \f2n\^\fP-th sub-pattern.
+In the first form,
+only the first occurrence of
+.I pattern\^
+is replaced.
+In the second form,
+each match for
+.I pattern\^
+is replaced by the given
+.IR string.
+The third form restricts the pattern match to the beginning of the string
+while the fourth form restricts the pattern match to the end of
+the string.
+When
+.I string\^
+is null, the
+.I pattern\^
+will be deleted and the
+.B /
+in front of
+.I string\^
+may be omitted.
+When
+.I parameter\^
+is
+.BR @ ,
+.BR * ,
+or an array variable with subscript
+.B @
+or
+.BR * ,
+the substitution operation is applied to each element in turn.
+In this case, the
+.I string\^
+portion of
+.I word\^
+will be re-evaluated for each element.
+.PP
+The following
+parameters
+are automatically set by the shell:
+.RS
+.PD 0
+.TP
+.B #
+The number of positional parameters in decimal.
+.TP
+.B \-
+Options supplied to the shell on invocation or by
+the
+.B set
+command.
+.TP
+.B ?
+The decimal value returned by the last executed command.
+.TP
+.B $
+The process number of this shell.
+.TP
+.B _
+Initially, the value of
+.B _
+is an absolute pathname of the shell or script being executed
+as passed in the
+.IR environment .
+Subsequently it is assigned the last argument of the previous command.
+This parameter is not set for commands which are asynchronous.
+This parameter is also used to hold the name of the matching
+.B
+.SM MAIL
+file when checking for mail.
+While defining a compound variable or a type,
+.B _
+is initialized as a reference to the compound variable or type.
+When a discipline function is invoked,
+.B _
+is initialized as a reference to the variable associated with
+the call to this function.
+Finally when
+.B _
+is used as the name of the first variable of a type definition,
+the new type is derived from the type of the first variable (See
+.I "Type Variables"\^
+below.).
+.TP
+.B !
+The process id or the pool name and job number of the last background command
+invoked or the most recent job put in the background with the
+.B bg
+built-in command.
+Background jobs started in a named pool will be in the form
+.IB pool . number
+where
+.I pool\^
+is the pool name and
+.I number\^
+is the job number within that pool.
+.TP
+.B .sh.command
+When processing a
+.SM
+.B DEBUG
+trap, this variable contains the current command line
+that is about to run.
+.TP
+.B .sh.edchar
+This variable contains the value of the keyboard character
+(or sequence of characters if the first character is an ESC, ascii
+.BR 033\^ )
+that has
+been entered when processing a
+.B
+.SM KEYBD
+trap
+(see
+.I "Key Bindings\^"
+below).
+If the value is changed as part of the trap action, then the new
+value replaces the key (or key sequence) that caused the trap.
+.TP
+.B .sh.edcol
+The character position of the cursor at the time of the most recent
+.B
+.SM KEYBD
+trap.
+.TP
+.B .sh.edmode
+The value is set to ESC when processing a
+.B
+.SM KEYBD
+trap while in
+.B vi
+insert mode. (See
+.I "Vi Editing Mode"\^
+below.)
+Otherwise,
+.B .sh.edmode
+is null when processing a
+.B
+.SM KEYBD
+trap.
+.TP
+.B .sh.edtext
+The characters in the input buffer at the time of the most recent
+.B
+.SM KEYBD
+trap.
+The value is null when not processing a
+.B
+.SM KEYBD
+trap.
+.TP
+.B .sh.file
+The pathname of the file than contains the current command.
+.TP
+.B .sh.fun
+The name of the current function that is being executed.
+.TP
+.B .sh.level
+Set to the current function depth. This can be changed
+inside a DEBUG trap and will set the context to the specified
+level.
+.TP
+.B .sh.lineno
+Set during a DEBUG trap to the line number for the caller of
+each function.
+.TP
+.B .sh.match
+An indexed array which stores the most recent match and sub-pattern
+matches after conditional pattern matches that match and after
+variables expansions using the operators
+.BR # ,
+.BR % ,
+or
+.BR / .
+The
+.BR 0 -th
+element stores the complete match and the
+.IR i\^ -th.
+element stores the
+.IR i\^ -th
+submatch.
+The
+.B .sh.match
+variable
+becomes unset when the variable that has expanded
+is assigned a new value.
+.TP
+.B .sh.math
+Used for defining arithmetic functions
+(see
+.I "Arithmetic evaluation"
+below).
+and stores the list of user defined arithmetic functions.
+.TP
+.B .sh.name
+Set to the name of the variable at the time that a
+discipline function is invoked.
+.TP
+.B .sh.subscript
+Set to the name subscript of the variable at the time that a
+discipline function is invoked.
+.TP
+.B .sh.subshell
+The current depth for subshells and command substitution.
+.TP
+.B .sh.value
+Set to the value of the variable at the time that the
+.B set
+or
+.B append
+discipline function is invoked.
+When a user defined arithmetic function is invoked, the value
+of
+.B .sh.value
+is saved and
+.B .sh.value
+is set to long double precision floating point.
+.B .sh.value
+is restored when the function returns.
+.TP
+.B .sh.version
+Set to a value that identifies the version of this shell.
+.TP
+.B
+.SM KSH_VERSION
+A name reference to
+.BR .sh.version .
+.TP
+.B
+.SM LINENO
+The current line number within the script or
+function being executed.
+.TP
+.B
+.SM OLDPWD
+The previous working directory set by the
+.B cd
+command.
+.TP
+.B
+.SM OPTARG
+The value of the last option argument processed by the
+.B getopts
+built-in command.
+.TP
+.B
+.SM OPTIND
+The index of the last option argument processed by the
+.B getopts
+built-in command.
+.TP
+.B
+.SM PPID
+The process number of the parent of the shell.
+.TP
+.B
+.SM PWD
+The present working directory set by the
+.B cd
+command.
+.TP
+.B
+.SM RANDOM
+Each time this variable is referenced, a random integer,
+uniformly distributed between 0 and 32767, is generated.
+The sequence of random numbers can be initialized by assigning
+a numeric value to
+.SM
+.BR RANDOM .
+.TP
+.B
+.SM REPLY
+This variable is set by the
+.B select
+statement and by
+the
+.B read
+built-in command when no arguments are supplied.
+.TP
+.B
+.SM SECONDS
+Each time this variable is referenced, the number of
+seconds since shell invocation is returned.
+If this variable is
+assigned a value, then the value returned upon reference will
+be the value that was assigned plus the number of seconds since the assignment.
+.TP
+.SM
+.B SHLVL
+An integer variable the is incremented each time the shell
+is invoked and is exported.
+If
+.SM
+.B SHLVL
+is not in the environment when the shell is invoked, it is set
+to 1.
+.PD
+.RE
+.PP
+The following
+variables
+are used by the shell:
+.RS
+.PD 0
+.TP
+.B
+.SM CDPATH
+The search path for the
+.B cd
+command.
+.TP
+.B
+.SM COLUMNS
+If this variable is set,
+the value is used to define the width of the edit window
+for the shell edit modes and for printing
+.B select
+lists.
+.TP
+.B
+.SM EDITOR
+If the
+.B
+.SM VISUAL
+variable is not set,
+the value of this variable will be checked for the patterns
+as described with
+.B
+.SM VISUAL
+below and the corresponding editing option
+(see Special Command
+.B set
+below)
+will be turned on.
+.TP
+.SM
+.B ENV
+If this variable is set, then
+parameter expansion, command substitution, and arithmetic substitution
+are performed on
+the value to generate
+the pathname of the script that will be
+executed when the shell
+is invoked interactively
+(see
+.I Invocation\^
+below).
+This file is typically used for
+.B alias
+and
+.B function
+definitions.
+The default value is \fB$HOME/.kshrc\fP.
+On systems that support a system wide \fB/etc/ksh.kshrc\fP initialization file,
+if the filename generated by the expansion of
+.SM
+.B ENV
+begins with
+.B /./
+or
+.B .\^/.\^/
+the system wide initialization file will not be executed.
+.TP
+.B
+.SM FCEDIT
+Obsolete name for
+the default editor name for the
+.B hist
+command.
+.B
+.SM FCEDIT
+is not used when
+.B
+.SM HISTEDIT
+is set.
+.TP
+.SM
+.B FIGNORE
+A pattern that defines the set of filenames that will be
+ignored when performing filename matching.
+.TP
+.SM
+.B FPATH
+The search path for function definitions.
+The directories in this path are searched for a file with the same name
+as the function or command when a function with the
+.B \-u
+attribute is referenced and when a command is not found.
+If an executable file with the name of that command is found,
+then it is read and executed
+in the current environment.
+Unlike
+.SM
+.BR PATH ,
+the current directory must be represented
+explicitly by
+.B .
+rather than by adjacent
+.B :
+characters or a beginning or ending
+.BR : .
+.TP
+.B
+.SM HISTCMD
+Number of the current command in the history file.
+.TP
+.B
+.SM HISTEDIT
+Name for
+the default editor name for the
+.B hist
+command.
+.TP
+.SM
+.B HISTFILE
+If this variable is set when the shell is invoked, then
+the value is the pathname of the file that will be
+used to store the command history (see
+.I "Command Re-entry\^"
+below).
+.TP
+.SM
+.B HISTSIZE
+If this variable is set when the shell is invoked, then
+the number of previously entered commands that
+are accessible by this shell
+will be greater than or equal to this number.
+The default is 512.
+.TP
+.B
+.SM HOME
+The default argument (home directory) for the
+.B cd
+command.
+.TP
+.SM
+.B IFS
+Internal field separators,
+normally
+.BR space ,
+.BR tab ,
+and
+.B new-line
+that are used to separate the results of
+command substitution or parameter expansion
+and to separate fields with the built-in command
+.BR read .
+The first character of the
+.SM
+.B IFS
+variable is used to separate arguments for the
+.B
+"$\(**"
+substitution (see
+.I Quoting
+below).
+Each single occurrence of
+an
+.SM
+.B IFS
+character in the string to be split,
+that is not in the \f2isspace\^\fP character class, and any
+adjacent characters in
+.SM
+.B IFS
+that are in the \f2isspace\^\fP character class, delimit a field.
+One or more
+characters in
+.SM
+.B IFS
+that belong to the \f2isspace\^\fP character class,
+delimit a field.
+In addition, if the same \f2isspace\^\fP character appears
+consecutively inside
+.SM
+.BR IFS ,
+this character is treated as if it were not in the \f2isspace\^\fP
+class, so that if
+.SM
+.BR IFS
+consists of two
+.B tab
+characters,
+then two adjacent
+.B tab
+characters delimit a null field.
+.TP
+.B
+.SM JOBMAX
+This variable defines the maximum number running background jobs
+that can run at a time. When this limit is reached, the
+shell will wait for a job to complete before staring a new job.
+.TP
+.B
+.SM LANG
+This variable determines the locale category for any
+category not specifically selected with a variable
+starting with
+.B
+.SM LC_
+or
+.SM
+.BR LANG .
+.TP
+.B
+.SM LC_ALL
+This variable overrides the value of the
+.B
+.SM LANG
+variable and any other
+.B
+.SM LC_
+variable.
+.TP
+.B
+.SM LC_COLLATE
+This variable determines the locale category for character
+collation information.
+.TP
+.B
+.SM LC_CTYPE
+This variable determines the locale category for character
+handling functions.
+It determines the character classes for pattern matching (see
+.I "File Name Generation\^"
+below).
+.TP
+.B
+.SM LC_NUMERIC
+This variable determines the locale category for the
+decimal point character.
+.TP
+.B
+.SM LINES
+If this variable is set,
+the value is used to determine the column length for printing
+.B select
+lists.
+Select lists will print vertically until about two-thirds of
+.B
+.SM LINES
+lines are filled.
+.TP
+.B
+.SM MAIL
+If this variable is set to the name of a mail file
+.I and\^
+the
+.B
+.SM MAILPATH
+variable is not set,
+then the shell informs the user of arrival of mail
+in the specified file.
+.TP
+.B
+.SM MAILCHECK
+This variable specifies how often (in seconds) the
+shell will check for changes in the modification time
+of any of the files specified by the
+.B
+.SM MAILPATH
+or
+.B
+.SM MAIL
+variables.
+The default value is 600 seconds.
+When the time has elapsed
+the shell will check before issuing the next prompt.
+.TP
+.B
+.SM MAILPATH
+A colon (
+.B :
+)
+separated list of file names.
+If this variable is set,
+then the shell informs the user of
+any modifications to the specified files
+that have occurred within the last
+.B
+.SM MAILCHECK
+seconds.
+Each file name can be followed by a
+.B ?
+and a message that will be printed.
+The message will undergo parameter expansion, command substitution,
+and arithmetic substitution
+with the variable
+.B $_
+defined as the name of the file that has changed.
+The default message is
+.I you have mail in $_\^.
+.TP
+.B
+.SM PATH
+The search path for commands (see
+.I Execution\^
+below).
+The user may not change
+.B \s-1PATH\s+1
+if executing under
+.if \nZ=0 .B rsh
+.if \nZ=1 .B rksh
+.if \nZ=2 .B rksh93
+(except in
+.BR .profile\^).
+.TP
+.SM
+.B PS1
+The value of this variable is expanded for parameter
+expansion, command substitution, and arithmetic substitution to define the
+primary prompt string which by default is
+.RB `` "$\|\|\|" ''.
+The character
+.B !
+in the primary prompt string is replaced by the
+.I command\^
+number (see
+.I "Command Re-entry\^"
+below).
+Two successive occurrences of
+.B !
+will produce a single
+.B !
+when the prompt string is printed.
+.TP
+.SM
+.B PS2
+Secondary prompt string, by default
+.RB `` "> \|" ''.
+.TP
+.SM
+.B PS3
+Selection prompt string
+used within a
+.B select
+loop, by default
+.RB `` "#? \|" ''.
+.TP
+.SM
+.B PS4
+The value of this variable is expanded for parameter evaluation,
+command substitution, and arithmetic substitution
+and precedes each line of an execution trace.
+By default,
+.SM
+.B PS4
+is
+.RB `` "+ \|" ''.
+In addition
+when
+.SM
+.B PS4
+is unset,
+the execution trace prompt is also
+.RB `` "+ \|" ''.
+.TP
+.SM
+.B SHELL
+The pathname of the
+.I shell\^
+is kept in the environment.
+At invocation, if the basename of this variable is
+.BR rsh ,
+.BR rksh ,
+or
+.BR krsh ,
+then the shell becomes restricted.
+If it is
+.BR pfsh
+or
+.BR pfksh ,
+then the shell becomes a profile shell (see
+.IR pfexec (1)).
+.TP
+.SM
+.B TIMEFORMAT
+The value of this parameter is used as a format string specifying
+how the timing information for pipelines prefixed with the
+.B time
+reserved word should be displayed.
+The \fB%\fP character introduces a format sequence that is
+expanded to a time value or other information.
+The format sequences and their meanings are as follows.
+.sp .5
+.RS
+.PD 0
+.TP 10
+.B %%
+A literal \fB%\fP.
+.TP
+.B %[\fIp\fP][l]R
+The elapsed time in seconds.
+.TP
+.B %[\fIp\fP][l]U
+The number of CPU seconds spent in user mode.
+.TP
+.B %[\fIp\fP][l]S
+The number of CPU seconds spent in system mode.
+.TP
+.B %P
+The CPU percentage, computed as (U + S) / R.
+.PD
+.RE
+.IP
+The brackets denote optional portions.
+The optional \fIp\fP is a digit specifying the \fIprecision\fP,
+the number of fractional digits after a decimal point.
+A value of 0 causes no decimal point or fraction to be output.
+At most three places after the decimal point can be displayed;
+values of \fIp\fP greater than 3 are treated as 3.
+If \fIp\fP is not specified, the value 3 is used.
+.IP
+The optional \fBl\fP specifies a longer format, including
+hours if greater than zero,
+minutes, and seconds of the form \fIHH\fPh\fIMM\fPm\fISS\fP.\fIFF\fPs.
+The value of \fIp\fP determines whether or not the fraction is
+included.
+.IP
+All other characters are output without change and a trailing
+newline is added.
+If unset, the default value, \fB$'\enreal\et%2lR\enuser\et%2lU\ensys\t%2lS'\fP,
+is used. If the value is null, no timing information is displayed.
+.TP
+.B
+.SM TMOUT
+If set to a value greater than zero,
+.B
+.SM TMOUT
+will be the default timeout value for the
+.B read
+built-in command.
+The
+.B select
+compound command terminates after
+.B
+.SM TMOUT
+seconds when input is from a terminal.
+Otherwise,
+the shell will terminate if a line is not entered within
+the prescribed number of seconds while reading from a terminal.
+(Note that the shell can be compiled with a maximum bound
+for this value which cannot be exceeded.)
+.TP
+.B
+.SM VISUAL
+If the value of this variable matches the pattern
+.IR *[Vv][Ii]* ,
+then the
+.B vi
+option
+(see Special Command
+.B set
+below)
+is turned on.
+If the value matches the pattern
+.I *gmacs* ,
+the
+.B gmacs
+option is turned on.
+If the value matches the pattern
+.IR *macs* ,
+then the
+.B emacs
+option
+will be turned on.
+The value of
+.B
+.SM VISUAL
+overrides the value of
+.B
+.SM EDITOR.
+.PD
+.RE
+.PP
+The shell gives default values to
+\f3\s-1PATH\s+1\fP, \f3\s-1PS1\s+1\fP, \f3\s-1PS2\s+1\fP,
+\f3\s-1PS3\s+1\fP, \f3\s-1PS4\s+1\fP, \f3\s-1MAILCHECK\s+1\fP, \f3\s-1FCEDIT\s+1\fP,
+\f3\s-1TMOUT\s+1\fP and \f3\s-1IFS\s+1\fP,
+while
+.SM
+.BR HOME ,
+.SM
+.BR SHELL ,
+.SM
+.BR ENV ,
+and
+.SM
+.B MAIL
+are
+not set at all by the shell (although
+.SM
+.B HOME
+.I is\^
+set by
+.IR login (1)).
+On some systems
+.SM
+.B MAIL
+and
+.SM
+.B SHELL
+are also
+set by
+.IR login (1).
+.SS Field Splitting.
+After parameter expansion and command substitution,
+the results of substitutions are scanned for the field separator
+characters (those found in
+.SM
+.B IFS\^\c
+)
+and split into distinct fields where such characters are found.
+Explicit null fields (\^\f3"\^"\fP or \f3\(fm\^\(fm\fP\^) are retained.
+Implicit null fields
+(those resulting from
+.I parameters\^
+that have no values or command substitutions with no output) are removed.
+.PP
+If the
+.B braceexpand
+.RB ( \-B )
+option is set then each of the fields resulting from
+.SM
+.B IFS
+are checked to see if they contain one or more of the brace patterns
+.BR {*,*} ,
+.BI { l1 .. l2 }
+,
+.BI { n1 .. n2 }
+,
+.BI { n1 .. n2 %
+.IB fmt }
+,
+.BI { n1 .. n2
+.BI .. n3 }
+, or
+.BI { n1 .. n2
+.BI .. n3 % fmt }
+, where
+.B *
+represents any character,
+.IR l1\^ , l2\^
+are letters and
+.IR n1\^ , n2\^ , n3\^
+are signed numbers and
+.I fmt\^
+is a format specified as used by
+.BR printf .
+In each case, fields are created
+by prepending the characters before the
+.B {
+and appending the characters after the
+.B }
+to each of the strings generated by the characters between
+the
+.B {
+and
+.BR } .
+The resulting fields are checked to see if they have any
+brace patterns.
+.PP
+In the first form, a field is created for each string between
+.BR {
+and
+.BR , ,
+between
+.BR ,
+and
+.BR , ,
+and between
+.BR ,
+and
+.BR } .
+The string represented by
+.B *
+can contain embedded matching
+.B {
+and
+.B }
+without quoting.
+Otherwise, each
+.B {
+and
+.B }
+with
+.B *
+must be quoted.
+.PP
+In the seconds form,
+.I l1\^
+and
+.I l2\^
+must both be either upper case or both be lower case characters
+in the C locale. In this case a field is created for each character
+from
+.I l1\^
+thru
+.IR l2\^ .
+.PP
+In the remaining forms, a field is created for each number starting at
+.I n1\^
+and continuing until it reaches
+.I n2\^
+incrementing
+.I n1\^
+by
+.IR n3\^ .
+The cases where
+.I n3\^
+is not specified behave as if
+.I n3\^
+where
+.B 1
+if
+.IB n1 <= n2
+and
+.B \-1
+otherwise.
+If forms which specify
+.BI % fmt\^
+any format flags, widths and precisions can be specified
+and
+.I fmt\^
+can end in any of the specifiers
+.BR cdiouxX .
+For example,
+.B {a,z}{1..5..3%02d}{b..c}x
+expands to the 8 fields,
+.BR a01bx ,
+.BR a01cx ,
+.BR a04bx ,
+.BR a04cx ,
+.BR z01bx ,
+.BR z01cx ,
+.B z04bx
+and
+.BR z4cx .
+.SS File Name Generation.
+Following splitting, each field is scanned for the characters
+.BR \(** ,
+.BR ? ,
+.BR ( ,
+and
+.B \*(OK\^
+unless the
+.B \-f
+option has been set.
+If one of these characters appears,
+then the word is regarded as a
+.IR pattern .
+Each file name component that contains any pattern character
+is replaced with a lexicographically sorted set of names
+that matches the pattern
+from
+that directory.
+If no file name is found that matches the pattern, then
+that component of the filename is left unchanged unless
+the pattern is prefixed with
+.B \(ap(N)\fP
+in which case it is removed as described below.
+If
+.SM
+.B FIGNORE
+is set,
+then each file name component
+that matches the pattern defined by the value of
+.SM
+.B FIGNORE
+is ignored when generating the matching filenames.
+The names
+.B .
+and
+.B ..
+are also ignored.
+If
+.SM
+.B FIGNORE
+is not set,
+the character
+.B .
+at the start of each file name component
+will be ignored unless the first character of the pattern
+corresponding to this component is the character
+.BR .
+itself.
+Note, that for other
+uses of pattern matching the
+.B /
+and
+.B .
+are not treated specially.
+.PP
+.PD 0
+.RS
+.TP
+.B \(**
+Matches any string, including the null string.
+When used for filename expansion,
+if the
+.B globstar
+option is on, two adjacent
+.BR \(** 's
+by itself
+will match all files and zero or more directories
+and subdirectories.
+If followed by a
+.B /
+then only directories and subdirectories will match.
+.TP
+.B ?
+Matches any single character.
+.TP
+.BR \*(OK \^.\|.\|.\^ \*(CK
+Matches any one of the enclosed characters.
+A pair of characters separated by
+.B \-
+matches any
+character lexically between the pair, inclusive.
+If the first character following the opening
+.B \*(OK\^
+is a
+.B !
+or
+.B ^
+then any character not enclosed is matched.
+A
+.B \-
+can be included in the character set by putting it as the
+first or last character.
+.br
+Within
+.B \*(OK\^
+and
+.BR \*(CK\^ ,
+character classes can be specified with the syntax
+\f3[:\fP\f2class\fP\f3:]\fP
+where class is one of the following classes defined in the ANSI-C standard:
+(Note that \f3word\fP is equivalent to \f3alnum\fP plus the character \f3_\fP.)
+.br
+.B
+.if n alnum alpha blank cntrl digit graph lower print punct space upper word xdigit
+.if t alnum alpha blank cntrl digit graph lower print punct space upper word xdigit
+.br
+Within
+.B \*(OK\^
+and
+.BR \*(CK\^ ,
+an equivalence class can be specified with the syntax
+\f3[=\fP\f2c\fP\f3=]\fP
+which matches all characters with the same primary
+collation weight (as defined by the current locale) as
+the character \f2c\fP.
+Within
+.B \*(OK\^
+and
+.BR \*(CK\^ ,
+\f3[.\fP\f2symbol\fP\f3.]\fP
+matches the collating symbol \f2symbol\fP.
+.RE
+.PD
+A
+.I pattern-list
+is a list of one or more patterns separated from each other
+with a
+.B &
+or
+.BR \(bv .
+A
+.B &
+signifies that all patterns must be matched whereas
+.BR \(bv
+requires that only one pattern be matched.
+Composite patterns can be formed with one or more of the following sub-patterns:
+.PD 0
+.RS
+.TP
+\f3?(\fP\f2pattern-list\^\fP\f3)\fP
+Optionally matches any one of the given patterns.
+.TP
+\f3*(\fP\f2pattern-list\^\fP\f3)\fP
+Matches zero or more occurrences of the given patterns.
+.TP
+\f3+(\fP\f2pattern-list\^\fP\f3)\fP
+Matches one or more occurrences of the given patterns.
+.TP
+\f3{\fP\f2n\^\fP\f3}\fP(\fP\f2pattern-list\^\fP\f3)\fP
+Matches \f2n\^\fP occurrences of the given patterns.
+.TP
+\f3{\fP\f2m\^\fP\f3,\fP\f2n\^\fP\f3}\fP(\fP\f2pattern-list\^\fP\f3)\fP
+Matches from \f2m\^\fP to \f2n\^\fP occurrences of the given patterns.
+If \f2m\^\fP is omitted, \f30\fP will be used. If \f2n\^\fP
+is omitted at least \f2m\^\fP occurrences will be matched.
+.TP
+\f3\&@\&(\fP\f2pattern-list\^\fP\f3)\fP
+Matches exactly one of the given patterns.
+.br
+.TP
+\f3!(\fP\f2pattern-list\^\fP\f3)\fP
+Matches anything except one of the given patterns.
+.PD
+.RE
+By default, each pattern, or sub-pattern will match the
+longest string possible consistent with generating
+the longest overall match. If more than one match is
+possible, the one starting closest to the beginning
+of the string will be chosen. However, for each of the above
+compound patterns a \f3\-\fP can be inserted in front of the \f3(\fP
+to cause the shortest match to the specified \f2pattern-list\^\fP
+to be used.
+.PP
+When \f2pattern-list\^\fP is contained within parentheses,
+the backslash character \f3\e\fP is treated specially even
+when inside a character class. All ANSI-C character escapes are
+recognized and match the specified character. In addition
+the following escape sequences are recognized:
+.PD 0
+.RS
+.TP
+.B \ed
+Matches any character in the \f3digit\fP class.
+.TP
+.B \eD
+Matches any character not in the \f3digit\fP class.
+.TP
+.B \es
+Matches any character in the \f3space\fP class.
+.TP
+.B \eS
+Matches any character not in the \f3space\fP class.
+.TP
+.B \ew
+Matches any character in the \f3word\fP class.
+.TP
+.B \eW
+Matches any character not in the \f3word\fP class.
+.PD
+.RE
+.PP
+A pattern of the form
+\f3%(\fP\f2pattern-pair\^\fP(s)\f3)\fP
+is a sub-pattern that
+can be used to match nested character expressions.
+Each
+.I pattern-pair\^
+is a two character sequence which cannot contain
+.B &
+or
+.BR \(bv .
+The first
+.I pattern-pair\^
+specifies the starting and ending characters for the match.
+Each subsequent
+.I pattern-pair\^
+represents the beginning and ending characters of a nested group that
+will be skipped over when counting starting and ending character matches.
+The behavior is unspecified when the first character of a
+.I pattern-pair\^
+is alpha-numeric
+except for the following:
+.PD 0
+.RS
+.TP
+.B D
+Causes the ending character to terminate the search for this pattern without
+finding a match.
+.TP
+.B E
+Causes the ending character to be interpreted as an escape character.
+.TP
+.B L
+Causes the ending character to be interpreted as a quote character
+causing all characters to be ignored when looking for a match.
+.TP
+.B Q
+Causes the ending character to be interpreted as a quote character
+causing all characters other than any escape character to be ignored
+when looking for a match.
+.PD
+.RE
+Thus,
+\f3%(\^{\^}Q"E\e\^)\fP,
+matches characters starting at
+.B {
+until the matching
+.B }
+is found not counting any
+.B {
+or
+.B }
+that is inside a double quoted string or preceded by the escape character
+.BR \e .
+Without the
+.B {\^}
+this pattern matches any C language string.
+.PP
+Each sub-pattern in a composite pattern is numbered,
+starting at 1, by the location of the \f3(\fP within
+the pattern.
+The sequence \f3\e\fP\f2n\^\fP, where \f2n\^\fP
+is a single digit and \f3\e\fP\f2n\^\fP comes after
+the \f2n\fP-th. sub-pattern,
+matches the same string as the sub-pattern itself.
+.PP
+Finally a pattern can contain sub-patterns of the form
+\f3\(ap(\fP\f2options\^\fP\f3:\fP\f2pattern-list\^\fP\f3)\fP,
+where either \f2options\^\fP or \f3:\fP\f2pattern-list\^\fP
+can be omitted. Unlike the other compound patterns,
+these sub-patterns are not counted in the numbered sub-patterns.
+\f3:\fP\f2pattern-list\^\fP must be omitted for the upper-case options below.
+If \f2options\^\fP is present, it can consist of one or more
+of the following:
+.PD 0
+.RS
+.TP
+.B +
+Enable the following options. This is the default.
+.TP
+.B \-
+Disable the following options.
+.TP
+.B E
+The remainder of the pattern uses extended regular expression syntax
+like the
+.IR egrep (1)
+command.
+.TP
+.B F
+The remainder of the pattern uses
+.IR fgrep (1)
+expression syntax.
+.TP
+.B G
+The remainder of the pattern uses basic regular expression syntax
+like the
+.IR grep (1)
+command.
+.TP
+.B K
+The remainder of the pattern uses shell pattern syntax.
+This is the default.
+.TP
+.B N
+This is ignored. However, when it is the first letter and is
+used with file name generation, and no matches occur,
+the file pattern expands to the empty string.
+.TP
+.B X
+The remainder of the pattern uses augmented regular expression syntax
+like the
+.IR xgrep (1)
+command.
+.TP
+.B P
+The remainder of the pattern uses
+.IR perl (1)
+regular expression syntax. Not all perl regular expression syntax is
+currently implemented.
+.TP
+.B i
+Treat the match as case insensitive.
+.TP
+.B g
+File the longest match (greedy). This is the default.
+.TP
+.B l
+Left anchor the pattern. This is the default for
+.B K
+style patterns.
+.TP
+.B r
+Right anchor the pattern. This is the default for
+.B K
+style patterns.
+.PD
+.RE
+If both \f2options\^\fP and \f3:\fP\f2pattern-list\^\fP
+are specified, then the options apply only to \f2pattern-list\^\fP.
+Otherwise, these options remain in effect until they are disabled
+by a subsequent \f3\(ap(\fP\f2...\^\fP\f3)\fP or at the end of
+the sub-pattern containing \f3\(ap(\fP\f2...\^\fP\f3)\fP.
+.SS Quoting.
+Each of the
+.I metacharacters\^
+listed earlier (see
+.I Definitions\^
+above)
+has a special meaning to the shell
+and causes termination of a word unless quoted.
+A character may be
+.I quoted\^
+(i.e., made to stand for itself)
+by preceding
+it with a
+.BR \e .
+The pair
+.B \enew-line
+is removed.
+All characters enclosed between a pair of single quote marks
+(\^\f3\(fm\^\(fm\fP\^)
+that is not preceded by a
+.B $
+are quoted.
+A single quote cannot appear within the single quotes.
+A single quoted string preceded by an unquoted
+.B $
+is processed as an ANSI-C string
+except for the following:
+.PD 0
+.TP
+.B \e0
+Causes the remainder of the string to be ignored.
+.TP
+.B \eE
+Equivalent to the escape character
+(ascii
+.BR 033 ),
+.TP
+.B \ee
+Equivalent to the escape character
+(ascii
+.BR 033 ),
+.TP
+.BI \ec x
+Expands to the character control-\f2x\fP.
+.TP
+.BI \eC[. name .]
+Expands to the collating element \f2name\fP.
+.PD
+.PP
+Inside double quote marks
+(\f3"\^"\fP),
+parameter and command substitution occur and
+.B \e
+quotes the characters
+.BR \e ,
+.BR \*` ,
+\f3"\fP,
+and
+.BR $ .
+A
+.B $
+in front of a double quoted string will be ignored
+in the "C" or "POSIX" locale, and may cause
+the string to be replaced by a locale specific string otherwise.
+The meaning of
+.B "$\(**"
+and
+.B "$@"
+is identical when not quoted or when used as a variable assignment value
+or as a file name.
+However, when used as a command argument,
+.B
+"$\(**"
+is equivalent to
+\f3"$1\fP\f2d\fP\f3\|$2\fP\f2d\fP\|.\|.\|.\f3"\fP,
+where
+.I d
+is the first character of the
+.SM
+.B IFS
+variable, whereas
+.B
+"$@"
+is equivalent to
+.B
+"$1"\|
+.B
+"$2"\|
+\&.\|.\|.\^.
+Inside grave quote marks
+(\f3\*`\^\*`\fP),
+.B \e
+quotes the characters
+.BR \e ,
+.BR \*` ,
+and
+.BR $ .
+If the grave quotes occur within double quotes, then
+.B \e
+also quotes the character
+\f3"\fP.
+.PP
+The special meaning of reserved words or aliases can be removed by quoting any
+character of the reserved word.
+The recognition of function names or built-in command names listed below
+cannot be altered by quoting them.
+.SS Arithmetic Evaluation.
+The shell performs arithmetic evaluation for
+arithmetic substitution, to evaluate an arithmetic command,
+to evaluate an indexed array subscript,
+and to evaluate arguments to
+the built-in commands
+.B shift\^
+and
+.BR let .
+Evaluations are performed using
+double precision floating point
+arithmetic or long double precision floating point for
+systems that provide this data type.
+Floating point constants follow the ANSI-C programming language
+floating point conventions.
+The floating point constants
+.B Nan
+and
+.B Inf
+can be use to represent "not a number" and infinity respectfully.
+Integer constants follow the ANSI-C programming language
+integer constant conventions although only single byte
+character constants are recognized and character casts
+are not recognized.
+In addition constants can be of the form
+\*(OK\f2base\f3#\^\f1\*(CK\f2n\^\fP
+where
+.I base\^
+is a decimal number between two and sixty-four
+representing the arithmetic base
+and
+.I n\^
+is a number in that base.
+The digits above 9 are represented
+by the lower case letters, the upper case letters,
+.BR @ ,
+and
+.B _
+respectively.
+For bases less than or equal to 36, upper and lower case
+characters can be used interchangeably.
+.PP
+An arithmetic expression uses the same syntax, precedence, and
+associativity of
+expression as the C language.
+All the C language operators
+that apply to floating point quantities can be used.
+In addition, the operator
+.B **
+can be used for exponentiation.
+It has higher precedence than multiplication and is left associative.
+In addition, when the value of an arithmetic variable
+or sub-expression can be represented as a long integer,
+all C language integer arithmetic operations can be performed.
+Variables can be referenced by name within an arithmetic expression
+without using the parameter expansion syntax.
+When a variable is referenced, its value is evaluated as
+an arithmetic expression.
+.PP
+Any of the following math library functions that are in the C math library
+can be used within an arithmetic expression:
+.PP
+.if t .RS
+.B
+.if n abs acos acosh asin asinh atan atan2 atanh cbrt ceil copysign cos cosh erf erfc exp exp2 expm1 fabs fpclassify fdim finite floor fma fmax fmin fmod hypot ilogb int isfinite sinf isnan isnormal issubnormal issubordered iszero j0 j1 jn lgamma log log10 log2 logb nearbyint nextafter nexttoward pow remainder rint round scanb signbit sin sinh sqrt tan tanh tgamma trunc y0 y1 yn
+.if t abs acos acosh asin asinh atan atan2 atanh cbrt ceil copysign cos cosh erf erfc exp exp2 expm1 fabs fpclassify fdim finite floor fma fmax fmod j0 j1 jn hypot ilogb int isfinite isinf isnan isnormal issubnormal issubordered iszero lgamma log log10 log2 logb nearbyint nextafter nexttoward pow rint round scalb signbit sin sinh sqrt tan tanh tgamma trunc y0 y1 yn
+.if t .RE
+In addition, arithmetic functions can be define as shell functions with a
+variant of the
+.B function
+.I name\^
+syntax,
+.TP
+.PD 0
+\f3function .sh.math.\fP\f2name ident\^\fP ... \f3{\fP \f2list\^\fP \f3;}\fP
+.PD
+where
+.I name\^
+is the function name used in the arithmetic expression and each identifier,
+.I ident\^
+is a name reference to the long double precision floating point argument.
+The value of
+.B .sh.value
+when the function returns is the value of this function.
+User defined functions can take up to 3 arguments and override C math library
+functions.
+.PP
+An internal representation of a
+.I variable\^
+as a double precision floating point can be specified with the
+\f3\-E\fP \*(OK\f2n\^\fP\*(CK,
+\f3\-F\fP \*(OK\f2n\^\fP\*(CK,
+or
+\f3\-X\fP \*(OK\f2n\^\fP\*(CK
+option of the
+.B typeset
+special built-in command.
+The
+.B \-E
+option causes the expansion of the value to be represented using
+scientific notation when it is expanded.
+The optional option argument
+.I n
+defines the number of significant figures.
+The
+.B \-F
+option causes the expansion to be represented as a floating decimal number
+when it is expanded.
+The
+.B \-X
+option cause the expansion to be represented using the
+.B %a
+format defined by ISO C-99.
+The optional option argument
+.I n
+defines the number of places after the decimal (or radix) point in this case.
+.PP
+An internal integer representation of a
+.I variable\^
+can be specified with the
+\f3\-i\fP \*(OK\f2n\^\fP\*(CK
+option of the
+.B typeset
+special built-in command.
+The optional option argument
+.I n
+specifies an arithmetic base to be used when expanding the variable.
+If you do not specify an arithmetic base,
+base 10 will be used.
+.PP
+Arithmetic evaluation is performed on the value of each
+assignment to a variable with the
+.BR \-E ,
+.BR \-F ,
+.BR \-X ,
+or
+.B \-i
+attribute.
+Assigning a floating point number to a
+variable whose type is an integer causes the fractional
+part to be truncated.
+.PP
+.SS Prompting.
+When used interactively,
+the shell prompts with the value of
+.SM
+.B PS1
+after expanding it for parameter expansion, command substitution, and
+arithmetic substitution,
+before reading a command.
+In addition, each single
+.B !
+in the prompt is replaced by the command number.
+A
+.B !!
+is required to place
+.B !
+in the prompt.
+If at any time a new-line is typed and further input is needed
+to complete a command, then the secondary prompt
+(i.e., the value of
+.BR \s-1PS2\s+1 )
+is issued.
+.SS Conditional Expressions.
+A
+.I "conditional expression"
+is used with the
+.B [[
+compound command to test attributes of files and to compare
+strings.
+Field splitting and file name generation are
+not performed on the words between
+.B [[
+and
+.BR ]] .
+Each expression can be constructed from one or more
+of the following unary or binary expressions:
+.PD 0
+.TP
+\f2string\fP
+True, if
+.I string
+is not null.
+.TP
+\f3\-a\fP \f2file\fP
+Same as \f3\-e\fP below.
+This is obsolete.
+.TP
+\f3\-b\fP \f2file\fP
+True, if
+.I file\^
+exists and is a block special file.
+.TP
+\f3\-c\fP \f2file\fP
+True, if
+.I file\^
+exists and is a character special file.
+.TP
+\f3\-d\fP \f2file\fP
+True, if
+.I file\^
+exists and is a directory.
+.TP
+\f3\-e\fP \f2file\fP
+True, if
+.I file\^
+exists.
+.TP
+\f3\-f\fP \f2file\fP
+True, if
+.I file\^
+exists and is an ordinary file.
+.TP
+\f3\-g\fP \f2file\fP
+True, if
+.I file\^
+exists and it has its setgid bit set.
+.TP
+\f3\-k\fP \f2file\fP
+True, if
+.I file\^
+exists and it has its sticky bit set.
+.TP
+\f3\-n\fP \f2string\fP
+True, if length of
+.I string\^
+is non-zero.
+.TP
+\f3\-o\fP \f3?\fP\f2option\fP
+True, if option named
+.I option\^
+is a valid option name.
+.TP
+\f3\-o\fP \f2option\fP
+True, if option named
+.I option\^
+is on.
+.TP
+\f3\-p\fP \f2file\fP
+True, if
+.I file\^
+exists and is a fifo special file or a pipe.
+.TP
+\f3\-r\fP \f2file\fP
+True, if
+.I file\^
+exists and is readable by current process.
+.TP
+\f3\-s\fP \f2file\fP
+True, if
+.I file\^
+exists and has size greater than zero.
+.TP
+\f3\-t\fP \f2fildes\fP
+True, if file descriptor number
+.I fildes\^
+is open and associated with a terminal device.
+.TP
+\f3\-u\fP \f2file\fP
+True, if
+.I file\^
+exists and it has its setuid bit set.
+.TP
+\f3\-w\fP \f2file\fP
+True, if
+.I file\^
+exists and is writable by current process.
+.TP
+\f3\-x\fP \f2file\fP
+True, if
+.I file\^
+exists and is executable by current process.
+If
+.I file\^
+exists and is a directory, then true if the current process
+has permission to search in the directory.
+.TP
+\f3\-z\fP \f2string\fP
+True, if length of
+.I string\^
+is zero.
+.TP
+\f3\-L\fP \f2file\fP
+True, if
+.I file\^
+exists and is a symbolic link.
+.TP
+\f3\-h\fP \f2file\fP
+True, if
+.I file\^
+exists and is a symbolic link.
+.TP
+\f3\-N\fP \f2file\fP
+True, if
+.I file\^
+exists and the modification time is greater than the last access time.
+.TP
+\f3\-O\fP \f2file\fP
+True, if
+.I file\^
+exists and is owned by the effective user id of this process.
+.TP
+\f3\-G\fP \f2file\fP
+True, if
+.I file\^
+exists and its group matches the effective group id of this process.
+.TP
+\f3\-S\fP \f2file\fP
+True, if
+.I file\^
+exists and is a socket.
+.TP
+\f2file1\fP \f3\-nt\fP \f2file2\fP
+True, if
+.I file1\^
+exists and
+.I file2\^
+does not, or
+.I file1\^
+is newer than
+.IR file2 .
+.TP
+\f2file1\fP \f3\-ot\fP \f2file2\fP
+True, if
+.I file2\^
+exists and
+.I file1\^
+does not, or
+.I file1\^
+is older than
+.IR file2 .
+.TP
+\f2file1\fP \f3\-ef\fP \f2file2\fP
+True, if
+.I file1\^
+and
+.I file2\^
+exist and refer to the same file.
+.TP
+\f2string\fP \f3==\fP \f2pattern\fP
+True, if
+.I string\^
+matches
+.IR pattern .
+Any part of
+.I pattern\^
+can be quoted to cause it to be matched as a string.
+With a successful match to a pattern, the
+.B .sh.match
+array variable will contain the match and sub-pattern matches.
+.TP
+\f2string\fP \f3=\fP \f2pattern\fP
+Same as \f3==\fP above, but is obsolete.
+.TP
+\f2string\fP \f3!=\fP \f2pattern\fP
+True, if
+.I string\^
+does not match
+.IR pattern .
+When the
+.I string\^
+matches the
+.I pattern\^
+the
+.B .sh.match
+array variable will contain the match and sub-pattern matches.
+.TP
+\f2string\fP \f3=\(ap\fP \f2ere\fP
+True if
+.I string\^
+matches the pattern
+.BI \(ap(E) ere\^
+where
+.I ere\^
+is an extended regular expression.
+.TP
+\f2string1\fP \f3<\fP \f2string2\fP
+True, if
+.I string1\^
+comes before
+.I string2\^
+based on ASCII value of their characters.
+.TP
+\f2string1\fP \f3>\fP \f2string2\fP
+True, if
+.I string1\^
+comes after
+.I string2\^
+based on ASCII value of their characters.
+.PP
+The following obsolete arithmetic comparisons are also permitted:
+.PD 0
+.TP
+\f2exp1\fP \f3\-eq\fP \f2exp2\fP
+True, if
+.I exp1\^
+is equal to
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-ne\fP \f2exp2\fP
+True, if
+.I exp1\^
+is not equal to
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-lt\fP \f2exp2\fP
+True, if
+.I exp1\^
+is less than
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-gt\fP \f2exp2\fP
+True, if
+.I exp1\^
+is greater than
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-le\fP \f2exp2\fP
+True, if
+.I exp1\^
+is less than or equal to
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-ge\fP \f2exp2\fP
+True, if
+.I exp1\^
+is greater than or equal to
+.IR exp2 .
+.PD
+.PP
+In each of the above expressions, if
+.I file\^
+is of the form
+\f3/dev/fd/\fP\f2n\fP,
+where
+.I n\^
+is an integer,
+then the test is applied to the open file whose
+descriptor number is
+.IR n .
+.PP
+A compound expression can be constructed from these primitives by
+using any of the following, listed in decreasing order of precedence.
+.PD 0
+.TP
+\f3(\fP\f2expression\fP\f3)\fP
+True, if
+.I expression\^
+is true.
+Used to group expressions.
+.TP
+\f3!\fP \f2expression\fP
+True if
+.I expression\^
+is false.
+.TP
+\f2expression1\fP \f3&&\fP \f2expression2\fP
+True, if
+.I expression1\^
+and
+.I expression2\^
+are both true.
+.TP
+\f2expression1\fP \f3\(bv\(bv\fP \f2expression2\fP
+True, if either
+.I expression1\^
+or
+.I expression2\^
+is true.
+.PD
+.SS Input/Output.
+Before a command is executed, its input and output
+may be redirected using a special notation interpreted by the shell.
+The following may appear anywhere in a simple-command
+or may precede or follow a
+.I command\^
+and are
+.I not\^
+passed on to the invoked command.
+Command substitution, parameter expansion,
+and arithmetic substitution occur before
+.I word\^
+or
+.I digit\^
+is used except as noted below.
+File name generation
+occurs only if the shell is interactive and
+the pattern matches a single file.
+Field splitting is not performed.
+.PP
+In each of the following redirections, if
+.I file\^
+is of the form
+\f3/dev/sctp/\fP\f2host\fP\f3/\fP\f2port\fP,
+\f3/dev/tcp/\fP\f2host\fP\f3/\fP\f2port\fP,
+or
+\f3/dev/udp/\fP\f2host\fP\f3/\fP\f2port\fP,
+where
+.I host\^
+is a hostname or host address,
+and
+.I port\^
+is a service given by name or an integer port number,
+then the redirection attempts to make a
+\f3tcp\fP, \f3sctp\fP or \f3udp\fP connection to the corresponding
+socket.
+.PP
+No intervening space is allowed between the characters of redirection operators.
+.TP 14
+.BI < word
+Use file
+.I word\^
+as standard input (file descriptor 0).
+.TP
+.BI > word
+Use file
+.I word\^
+as standard output (file descriptor 1).
+If the file does not exist then it is created.
+If the file exists, and the
+.B noclobber
+option is on,
+this causes an error;
+otherwise, it is truncated to zero length.
+.TP
+.BI >| word
+Sames as
+.BR > ,
+except that it overrides the
+.B noclobber
+option.
+.TP
+.BI >; word
+Write output to a temporary file. If the command completes
+successfully rename it to
+.IR word ,
+otherwise, delete the temporary file.
+.BI >; word
+cannot be used with the
+.IR exec (2).
+built-in.
+.TP
+.BI >> word
+Use file
+.I word\^
+as standard output.
+If the file exists, then output is appended to it (by first seeking to the end-of-file);
+otherwise, the file is created.
+.TP
+.BI <> word
+Open file
+.I word\^
+for reading and writing
+as standard output.
+.TP
+.BI <>; word
+The same as
+.BI <> word
+except that if the command completes successfully,
+.I word\^
+is truncated to the offset at command completion.
+.BI <>; word
+cannot be used with the
+.IR exec (2).
+built-in.
+.TP
+\f3<<\fP\*(OK\f3\-\fP\*(CK\f2word\fP
+The shell input is read up to a line that is the same as
+.IR word
+after any quoting has been removed,
+or to an end-of-file.
+No parameter substitution, command substitution, arithmetic substitution or
+file name generation is performed on
+.IR word .
+The resulting document,
+called a
+.IR here-document ,
+becomes
+the standard input.
+If any character of
+.I word\^
+is quoted, then no interpretation
+is placed upon the characters of the document;
+otherwise, parameter expansion, command substitution, and arithmetic
+substitution occur,
+.B \enew-line
+is ignored,
+and
+.B \e
+must be used to quote the characters
+.BR \e ,
+.BR $ ,
+.BR \*` .
+If
+.B \-
+is appended to
+.BR << ,
+then all leading tabs are stripped from
+.I word\^
+and from the document.
+If
+.B #
+is appended to
+.BR << ,
+then leading spaces and tabs will be stripped off the first
+line of the document and up to an equivalent indentation will
+be stripped from the remaining lines and from
+.IR word .
+A tab stop is assumed to occur at every 8 columns for the
+purposes of determining the indentation.
+.TP
+\f3<<<\fP\f2word\fP
+A short form of here document in which \f2word\fP becomes the
+contents of the here-document after any
+parameter expansion, command substitution, and arithmetic
+substitution occur.
+.TP
+.BI <& digit
+The standard input is duplicated from file descriptor
+.I digit
+(see
+.IR dup (2)).
+Similarly for the standard output using
+\f3>&\^\f2digit\fR.
+.TP
+.BI <& digit \-
+The file descriptor given by
+.I digit
+is moved to standard input.
+Similarly for the standard output using
+\f3>&\^\f2digit\f3\-\fR.
+.TP
+.B <&\-
+The standard input is closed.
+Similarly for the standard output using
+.BR >&\- .
+.TP
+.B <&p
+The input from the co-process is moved to standard input.
+.TP
+.B >&p
+The output to the co-process is moved to standard output.
+.TP
+.BI <# \^\^\^ (( expr ))
+Evaluate arithmetic expression
+.I expr\^
+and position file descriptor 0
+to the resulting value
+bytes from the start of the file.
+The variables
+.B CUR
+and
+.B EOF
+evaluate to the current offset and end-of-file offset
+respectively when evaluating
+.IR expr.
+.TP
+.BI ># \^\^\^ (( offset ))
+The same as
+.B <#
+except applies to file descriptor 1.
+.TP
+.BI <# pattern
+Seeks forward to the beginning of the next line containing
+.IR pattern .
+.TP
+.BI <## pattern
+The same as
+.B <#
+except that the portion of the file that is skipped is copied to
+standard output.
+.PP
+If one of the above is preceded by a digit,
+with no intervening space, then the
+file descriptor number referred to is that specified
+by the digit
+(instead of the default 0 or 1).
+If one of the above, other than
+.BR >&\-
+and the
+.B >#
+and
+.B <#
+forms,
+is preceded by
+.BI { varname }
+with no intervening space,
+then a file descriptor number > 10
+will be selected by
+the shell and stored in the variable
+.IR varname .
+If
+.B >&\-
+or the any of the
+.B >#
+and
+.B <#
+forms
+is preceded by
+.BI { varname }
+the value of
+.I varname\^
+defines the file descriptor to close or position.
+For example:
+.PP
+.RS
+\fB\&.\|.\|. \|2>&1\fR
+.RE
+.PP
+means file descriptor 2 is to be opened
+for writing as a duplicate
+of file descriptor 1 and
+.PP
+.RS
+\fBexec {n}<file\fR
+.RE
+.PP
+means open file named
+.B file
+for reading and store
+the file descriptor number in variable
+.BR n .
+.PP
+The order in which redirections are specified is significant.
+The shell evaluates each redirection in terms of the
+.RI ( "file descriptor" ", " file )
+association at the time of evaluation.
+For example:
+.PP
+.RS
+\fB\&.\|.\|. \|1>\f2fname\^\fP 2>&1\fR
+.RE
+.PP
+first associates file descriptor 1 with file
+.IR fname\^ .
+It then associates file descriptor 2 with the file associated with file
+descriptor 1 (i.e.
+.IR fname\^ ).
+If the order of redirections were reversed, file descriptor 2 would be associated
+with the terminal (assuming file descriptor 1 had been) and then file descriptor
+1 would be associated with file
+.IR fname\^ .
+.PP
+If a command is followed by
+.B &
+and job control is not active,
+then the default standard input
+for the command
+is the empty file
+.BR /dev/null .
+Otherwise, the environment for the execution of a command contains the
+file descriptors of the invoking shell as modified by
+input/output specifications.
+.SS Environment.
+The
+.I environment\^
+(see
+.IR environ (7))
+is a list of name-value pairs that is passed to
+an executed program in the same way as a normal argument list.
+The names must be
+.I identifiers\^
+and the values are character strings.
+The shell interacts with the environment in several ways.
+On invocation, the shell scans the environment
+and creates a
+variable
+for each name found,
+giving it the corresponding value and attributes and marking it
+.IR export .
+Executed commands inherit the environment.
+If the user modifies the values of these
+variables
+or creates new ones,
+using the
+.B export
+or
+.B typeset \-x
+commands, they become part of the
+environment.
+The environment seen by any executed command is thus composed
+of any name-value pairs originally inherited by the shell,
+whose values may be modified by the current shell,
+plus any additions
+which must be noted in
+.B export
+or
+.B typeset \-x
+commands.
+.PP
+The environment for any
+.I simple-command\^
+or function
+may be augmented by prefixing it with one or more variable assignments.
+A variable assignment argument is a word of the form
+.IR identifier=value .
+Thus:
+.PP
+.RS
+\fB\s-1TERM\s+1=450 \|cmd \|args\fR and
+.br
+\fB(export \|\s-1TERM\s+1; \|\s-1TERM\s+1=450; \|cmd \|args)\fR
+.RE
+.PP
+are equivalent (as far as the above execution of
+.I cmd\^
+is concerned except for special built-in commands listed below \-
+those that are
+preceded with a dagger).
+.PP
+If the obsolete
+.B \-k
+option is set,
+.I all\^
+variable assignment arguments are placed in the environment,
+even if they occur after the command name.
+The following
+first prints
+.B "a=b c"
+and then
+.BR c :
+.PP
+.RS
+.nf
+.ft B
+echo \|a=b \|c
+set \|\-k
+echo \|a=b \|c
+.ft R
+.fi
+.RE
+This feature is intended for use with scripts written
+for early versions of the shell and its use in new scripts
+is strongly discouraged.
+It is likely to disappear someday.
+.SS Functions.
+.PP
+For historical reasons, there are two
+ways to define functions,
+the
+.IB name (\^)
+syntax and
+the
+.B function
+.I name\^
+syntax, described in the
+.I Commands
+section above.
+Shell functions are read in and stored internally.
+Alias names are resolved when the function is read.
+Functions are executed like commands with the arguments
+passed as positional parameters.
+(See
+.I Execution
+below.)
+.PP
+Functions defined by the
+.B function
+.I name
+syntax and called by name execute in the same process as the caller and
+share all files
+and present working directory with the
+caller.
+Traps caught by the caller are reset to their default action
+inside the function.
+A trap condition that is not caught or ignored by the
+function causes the function to terminate and the condition
+to be passed on to the caller.
+A trap on
+.SM
+.B EXIT
+set inside a function
+is executed
+in the environment
+of the caller
+after the function completes.
+Ordinarily,
+variables are shared between the calling program
+and the function.
+However,
+the
+.B typeset
+special built-in command used within a function
+defines local variables whose scope includes
+the current function.
+They can be passed to functions that they call in the
+variable assignment list that precedes the call or as arguments
+passed as name references.
+Errors within functions return control to the caller.
+.PP
+Functions defined with the
+.IB name (\^)
+syntax and functions defined with the
+.B function
+.I name
+syntax that are invoked with the \f3\s+2.\s-2\fP
+special built-in
+are executed in the caller's
+environment and share all variables
+and traps with the caller.
+Errors within these function executions cause the script that contains
+them to abort.
+.PP
+The special built-in command
+.B return
+is used to return
+from function calls.
+.PP
+Function names
+can be listed with the
+.B \-f
+or
+.B +f
+option of the
+.B typeset
+special built-in command.
+The text of functions, when available, will also
+be listed with
+.BR \-f .
+Functions can be undefined with the
+.B \-f
+option of the
+.B unset
+special built-in command.
+.PP
+Ordinarily, functions are unset when the shell executes a shell script.
+Functions that need to be defined across separate
+invocations of the shell should
+be placed in a directory and the
+.B
+.SM
+FPATH
+variable should contain the name of this directory.
+They may also
+be specified in the
+.B
+.SM
+ENV
+file.
+.SS Discipline Functions.
+Each variable can have zero or more discipline functions
+associated with it.
+The shell initially understands the discipline names \f3get\fP,
+\f3set\fP, \f3append\fP, and \f3unset\fP but can be added
+when defining new types. On most systems
+others can be added at run time via the
+C programming interface extension provided by the
+.B builtin
+built-in utility.
+If the \f3get\fP discipline is defined for a variable, it is invoked
+whenever the given variable is referenced.
+If the variable \f3.sh.value\fP is assigned a value inside
+the discipline function, the referenced variable will evaluate
+to this value instead.
+If the \f3set\fP discipline is defined for a variable, it is invoked
+whenever the given variable is assigned a value.
+If the \f3append\fP discipline is defined for a variable, it is invoked
+whenever a value is appended to the given variable.
+The variable \f3.sh.value\fP is given the value
+of the variable before invoking the discipline, and
+the variable will be assigned the value of \f3.sh.value\fP
+after the discipline completes.
+If \f3.sh.value\fP is unset inside the discipline, then
+that value is unchanged.
+If the \f3unset\fP discipline is defined for a variable, it is invoked
+whenever the given variable is unset.
+The variable will not be unset unless it is unset explicitly
+from within this discipline function.
+.PP
+The variable
+.B .sh.name
+contains the name of the variable for which the discipline function is called,
+.B .sh.subscript
+is the subscript of the variable, and
+.B .sh.value
+will contain the value being assigned inside the
+.B set
+discipline function.
+The variable
+.B _
+is a reference to the variable including the subscript if any.
+For the \f3set\fP discipline,
+changing
+.B .sh.value
+will change the value that gets assigned.
+Finally, the expansion \f3${\fP\f2var\^\fP\f3.\fP\f2name\^\fP\f3}\fP,
+when \f2name\^\fP is the name of a discipline, and there is
+no variable of this name, is equivalent to the command substitution
+\f3${ \fP\f2var\^\fP\f3.\fP\f2name\^\fP\f3;}\fP.
+
+.SS Name Spaces.
+Commands and functions that are executed as part of the
+.I list\^
+of a
+.B namespace
+command that modify variables or create new ones, create
+a new variable whose
+name is the name of the name space
+as given by
+.I identifier\^
+preceded by \fB\s+2.\s-2\fP.
+When a variable whose name is
+.I name\^
+is referenced, it is
+first searched for
+using \fB\s+2.\s-2\fP\f2identifier\fP\fB\s+2.\s-2\fP\f2name\fP.
+Similarly, a function defined by a command in the
+.B namespace
+.I list\^
+is created using the name space name preceded by a \fB\s+2.\s-2\fP.
+.PP
+When the
+.I list\^
+of a
+.B namespace
+command contains a
+.B namespace
+command, the names of variable and functions that are created consist
+of the variable or function name preceded by the list of
+.IR identifier\^ s
+each preceded by \fB\s+2.\s-2\fP.
+.PP
+Outside of a name space, a variable or function created inside a
+names space can be referenced by preceding it with the name space name.
+.PP
+By default, variables staring with
+\fB\s+2.\s-2sh\fP are in the
+.B sh
+name space.
+
+.SS Type Variables.
+Typed variables provide a way to create data structure and objects.
+A type can be defined either by a shared library, by the
+.B enum
+built-in command described below, or by using the new
+.B \-T
+option of the
+.B typeset
+built-in command.
+With the
+.B \-T
+option of
+.BR typeset ,
+the type name, specified as an option argument to
+.BR \-T ,
+is set with a compound variable assignment that defines the type.
+Function definitions can appear inside the compound variable
+assignment and these become discipline functions for this type and
+can be invoked or redefined by each instance of the type.
+The function name
+.B create
+is treated specially. It is invoked for each instance of
+the type that is created but is not inherited and cannot be
+redefined for each instance.
+.PP
+When a type is defined a special built-in command of that name
+is added. These built-ins are declaration commands and follow the
+same expansion rules as all the special built-in commands defined
+below that are preceded by \(dg\(dg. These commands can subsequently
+be used inside further type definitions. The man page for these commands can
+be generated by using the
+.B \-\-man
+option or any of the other
+.B \-\-
+options described with
+.BR getopts .
+The
+.BR \-r ,
+.BR \-a ,
+.BR \-A ,
+.BR \-h ,
+and
+.B \-S
+options of
+.B typeset
+are permitted with each of these new built-ins.
+.PP
+An instance of a type is created by invoking the type name
+followed by one or more instance names.
+Each instance of the type is initialized with a copy of the sub-variables
+except for sub-variables that are defined with the
+.B \-S
+option. Variables defined with the
+.B \-S
+are shared by all instances of the type.
+Each instance can change the value of any sub-variable and can also
+define new discipline functions of the same names
+as those defined by the type definition as well as any
+standard discipline names.
+No additional sub-variables can be defined for any instance.
+.PP
+When defining a type,
+if the value of a sub-variable is not set and the
+.B \-r
+attribute is specified, it causes the sub-variable
+to be a required sub-variable.
+Whenever an instance of a type is created, all required sub-variables
+must be specified.
+These sub-variables become readonly in each instance.
+.PP
+When
+.B unset
+is invoked on a sub-variable within a type,
+and the
+.B \-r
+attribute has not been specified for this field,
+the value is reset to the default value associative with
+the type.
+Invoking
+.B unset
+on a type instance not contained within another type deletes
+all sub-variables and the variable itself.
+.PP
+A type definition can be derived from another type definition
+by defining the first sub-variable name as
+.B _
+and defining its type as the base type.
+Any remaining definitions will be additions and modifications
+that apply to the new type.
+If the new type name is the same is that of the base type,
+the type will be replaced and the original type will
+no longer be accessible.
+.PP
+The
+.B typeset
+command with the
+.B \-T
+and no option argument or operands will write all the type definitions to
+standard output in a form that that can be read in to create all they types.
+.SS Jobs.
+.PP
+If the
+.B monitor
+option of the
+.B set
+command is turned on,
+an interactive shell associates a \fIjob\fR with each pipeline.
+It keeps
+a table of current jobs, printed by the
+.B jobs
+command, and assigns them small integer numbers.
+When a job is started asynchronously with
+.BR & ,
+the shell prints a line which looks
+like:
+.PP
+.DT
+ [1] 1234
+.PP
+indicating that the job which was started asynchronously was job number
+1 and had one (top-level) process, whose process id was 1234.
+.PP
+This paragraph and the next require features that are
+not in all versions of UNIX and may not apply.
+If you are running a job and wish to do something else you may hit the key
+\fB^Z\fR (control-Z) which sends a STOP signal to the current job.
+The shell will then normally indicate that the job has been `Stopped',
+and print another prompt.
+You can then manipulate the state of this job,
+putting it in the background with the
+.B bg
+command, or run some other
+commands and then eventually bring the job back into the foreground with
+the foreground command
+.BR fg .
+A \fB^Z\fR takes effect immediately and
+is like an interrupt in that pending output and unread input are discarded
+when it is typed.
+.PP
+A job being run in the background will stop if it tries to read
+from the terminal.
+Background jobs are normally allowed to produce output,
+but this can be disabled by giving the command
+.BR "stty tostop" .
+If you set this
+tty option, then background jobs will stop when they try to produce
+output like they do when they try to read input.
+.PP
+A job pool is a collection of jobs started with
+.I list\^
+.B &
+associated with a name.
+.PP
+There are several ways to refer to jobs in the shell.
+A job can be referred to by the process id of any process of the job
+or by one of the following:
+.PD 0
+.TP
+.BI % number
+The job with the given number.
+.TP
+.I pool\^
+All the jobs in the job pool named by
+.IR pool .
+.TP
+.IB pool . number
+The job number
+.I number\^
+in the job pool named by
+.IR pool .
+.TP
+.BI % string
+Any job whose command line begins with
+.IR string .
+.TP
+.BI %? string
+Any job whose command line contains
+.IR string .
+.TP
+.BI %%
+Current job.
+.TP
+.BI %+
+Equivalent to
+.BR %% .
+.TP
+.BI %\-
+Previous job.
+.PD
+In addition, unless noted otherwise, wherever a job can be specified,
+the name of a background job pool can be used to represent all the
+jobs in that pool.
+.PP
+The shell learns immediately whenever a process changes state.
+It normally informs you whenever a job becomes blocked so that
+no further progress is possible, but only just before it prints
+a prompt.
+This is done so that it does not otherwise disturb your work.
+The
+.B notify
+option of the
+.B set
+command causes
+the shell to print these job change messages
+as soon as they occur.
+.PP
+When the
+.B monitor
+option is on, each background job that completes
+triggers any trap set for
+.BR CHLD .
+.PP
+When you try to leave the shell while jobs are running or stopped, you will
+be warned that `You have stopped(running) jobs.'
+You may use the
+.B jobs
+command to see what they are.
+If you immediately try to
+exit again, the shell will not warn you a second time, and the stopped
+jobs will be terminated.
+When a login shell receives a HUP signal, it sends
+a HUP signal to each job that has not been disowned with the
+.B disown
+built-in command described below.
+.SS Signals.
+The \s-1INT\s+1 and \s-1QUIT\s+1 signals for an invoked
+command are ignored if the command is followed by
+.B &
+and the
+.B monitor
+option is not active.
+Otherwise, signals have the values
+inherited by the shell from its parent
+(but see also
+the
+.B trap
+built-in command below).
+.SS Execution.
+Each time a command is read, the above substitutions
+are carried out.
+If the command name matches one
+of the
+.I "Special Built-in Commands\^"
+listed below,
+it is executed within the
+current shell process.
+Next, the command name is checked to see if
+it matches a user defined function.
+If it does,
+the positional parameters are saved
+and then reset to the arguments of the
+.I function\^
+call.
+A function is also executed in the
+current shell process.
+When the
+.I function\^
+completes or issues a
+.BR return ,
+the positional parameter list is restored.
+For functions defined with the
+.B function
+.I name\^
+syntax,
+any trap set on
+.SM
+.B EXIT
+within the function is executed.
+The exit value of a
+.I function\^
+is the value of the last command executed.
+If a command name is not a
+.I "special built-in command\^"
+or a user defined
+.IR function ,
+but it is one of the built-in commands listed below,
+it is executed in the current shell process.
+.PP
+The shell variable
+.B
+.SM PATH
+defines the search path for
+the directory containing the command.
+Alternative directory names are separated by
+a colon
+.RB ( : ).
+The default path is
+.B /bin:/usr/bin:
+(specifying
+.BR /bin ,
+.BR /usr/bin ,
+and the current directory
+in that order).
+The current directory can be specified by
+two or more adjacent colons, or by a colon
+at the beginning or end of the path list.
+If the command name contains a \f3/\fP, then the search path
+is not used.
+Otherwise, each directory in the path is
+searched for an executable file
+of the given name
+that is not a directory.
+If found, and if the shell
+determines that there is a built-in version
+of a command corresponding to a given pathname,
+this built-in is invoked in the current process.
+If found, and this directory is also contained in the value of the
+.B
+.SM FPATH
+variable,
+then this file is loaded into the current shell environment
+as if it were the argument to the \fB.\fP command
+except that only preset aliases are expanded,
+and a function of the given name is executed
+as described above.
+If not found, and the file
+.B .paths
+is found, and this file contains a line of the form
+.BI FPATH= path
+where
+.I path\^
+names an
+existing directory, and this directory contains
+a file of the given name,
+then this file is loaded into the current shell environment
+as if it were the argument to the \fB.\fP special built-in command
+and a function of the given name is executed.
+Otherwise, if found,
+a process is created and
+an attempt is made to execute the command via
+.IR exec (2).
+.P
+When an executable is found, the directory where it is found
+in is searched for a file named
+.BR .paths .
+If this file is found and it contains a line of the form
+.BI BUILTIN_LIB= value\^
+, then the library named by
+.I value\^
+will be searched for as if it were an option argument to
+.BR "builtin -f" ,
+and if it contains a built-in of the specified name
+this will be executed instead of a command by this name.
+Otherwise, if this file is found and it contains a line of the form
+.IB name\^ = value\^
+in the first or second line, then the environment variable
+.I name\^
+is modified by prepending the directory specified by
+.I value\^
+to the directory list.
+If
+.I value\^
+is not an absolute directory, then it
+specifies a directory relative to the directory that the
+executable was found.
+If the environment variable
+.I name\^
+does not already exist it will be added to the environment
+list for the specified command.
+.P
+If the file has execute permission but is not an
+.B a.out
+file,
+it is assumed to be a file containing shell commands.
+A separate shell is spawned to read it.
+All non-exported variables are removed in this case.
+If the shell command
+file doesn't have read permission,
+or if the
+.I setuid
+and/or
+.I setgid
+bits are set on the file,
+then the shell executes an agent whose job it is to
+set up the permissions and execute the shell with the
+shell command file passed down as an open file.
+A parenthesized command is executed in
+a sub-shell without removing non-exported variables.
+.SS Command Re-entry.
+The text of the last
+.B
+.SM
+HISTSIZE
+(default 512)
+commands entered from a terminal device
+is saved in a
+.I history
+file.
+The file
+.B \s-1$HOME\s+1/.sh_history
+is used if the
+.B
+.SM
+HISTFILE
+variable is not set
+or if the file it names is not writable.
+A shell can access the commands of
+all
+.I interactive
+shells which use the same named
+.SM
+.BR HISTFILE .
+The built-in command
+.B hist\^
+is used to list or
+edit a portion of this file.
+The portion of the file to be edited or listed can be selected by
+number or by giving the first character or
+characters of the command.
+A single command or range of commands can be specified.
+If you do not specify an editor program as
+an argument to
+.B hist\^
+then the value of the variable
+.SM
+.B HISTEDIT
+is used.
+If
+.SM
+.B HISTEDIT
+is unset, the obsolete variable
+.SM
+.B FCEDIT
+is used.
+If
+.SM
+.B FCEDIT
+is not defined, then
+.B /bin/ed
+is used.
+The edited command(s) is printed and re-executed upon
+leaving the editor unless you quit without writing.
+The
+.B \-s
+option
+(and in obsolete versions, the editor name
+.BR \-\^ )
+is used to skip the editing phase and
+to re-execute the command.
+In this case a substitution parameter of the form
+\f2old\fP\f3=\fP\f2new\fP
+can be used to modify the command before execution.
+For example, with the preset alias
+.BR r ,
+which is aliased to
+.BR "\(fmhist \-s\(fm" ,
+typing
+`\f3r bad=good c\fP'
+will re-execute the most recent command which starts with the letter
+.BR c ,
+replacing the first occurrence of the string
+.B bad
+with the string
+.BR good .
+.SS In-line Editing Options.
+Normally, each command line entered from a terminal device is simply
+typed followed by a \f3new-line\fP (`RETURN' or `LINE\ FEED').
+If either the
+.BR emacs ,
+.BR gmacs ,
+or
+.B vi
+option is active, the user can edit the command line.
+To be in either of these edit modes
+.B set
+the corresponding
+option.
+An editing option is automatically selected each time the
+.SM
+.B VISUAL
+or
+.SM
+.B EDITOR
+variable is assigned a value ending in either of these
+option names.
+.PP
+The editing features require that the user's terminal
+accept `RETURN' as carriage return without line feed
+and that a space (`\ ') must overwrite the current character on
+the screen.
+.PP
+Unless the
+.B multiline
+option is on,
+the editing modes implement a concept where the user is looking through a
+window at the current line.
+The window width is the value of
+.SM
+.B COLUMNS
+if it is defined, otherwise 80.
+If the window width is too small to display the prompt and leave
+at least 8 columns to enter input, the prompt is truncated from the
+left.
+If the line is longer than the window width minus two, a mark is
+displayed at the end of the window to notify the user.
+As the cursor moves and reaches the window boundaries the window will be
+centered about the cursor.
+The mark is a
+.BR > " (<" ,
+.BR * )
+if the line extends on the
+right (left, both) side(s) of the window.
+.PP
+The search commands in each edit mode provide access to the history file.
+Only strings are matched, not patterns, although a leading
+.B ^
+in the string restricts the match
+to begin at the first character in the line.
+.PP
+Each of the edit modes has an operation to list the files
+or commands that match a partially entered word.
+When applied to the first word on the line,
+or the first word after a
+.BR ; ,
+.BR \(bv ,
+.BR & ,
+or
+.BR ( ,
+and the word does not begin with
+.B \(ap
+or contain a
+.BR / ,
+the list of aliases, functions, and executable commands
+defined by the
+.B
+.SM PATH
+variable that could match the partial word is displayed.
+Otherwise, the list of files that match the given
+word is displayed.
+If the partially entered word does not contain any
+file expansion characters, a
+.B *
+is appended before generating these lists.
+After displaying the generated list, the input line
+is redrawn.
+These operations are called command name listing and file name listing,
+respectively.
+There are additional operations, referred to as command name
+completion and file name completion, which compute the list
+of matching commands or files, but instead of printing the list,
+replace
+the current word with a complete or partial match.
+For file name completion,
+if the match is unique, a
+.B /
+is appended if the file is a directory and a space is
+appended if the file is not a directory.
+Otherwise, the longest common prefix for all the matching
+files replaces the word.
+For command name completion, only the portion of the file names
+after the last
+.B /
+are used to find the longest command prefix.
+If only a single name matches this prefix, then the
+word is replaced with the command name followed by a space.
+When using a
+.I tab\^
+for completion that does not yield a unique match,
+a subsequent
+.I tab\^
+will provide a numbered list of matching alternatives.
+A specific selection can be made by entering the
+selection number followed by a
+.IR tab .
+.SS Key Bindings.
+The
+.B
+.SM KEYBD
+trap can be used to intercept keys as they are typed
+and change the characters that are actually seen by
+the shell.
+This trap is executed after each character
+(or sequence of characters when the first character is ESC)
+is entered while reading from a terminal.
+The variable
+.B .sh.edchar
+contains the character or character sequence which
+generated the trap.
+Changing the value of
+.B .sh.edchar
+in the trap action causes the shell to behave as if the
+new value were entered from the keyboard rather than
+the original value.
+.PP
+The variable
+.B .sh.edcol
+is set to the input column number of the cursor at the time
+of the input.
+The variable
+.B .sh.edmode
+is set to
+ESC
+when in
+.B vi
+insert mode (see below) and is null otherwise.
+By prepending
+.B ${.sh.editmode}
+to a value assigned to
+.B .sh.edchar
+it will cause the shell
+to change to control mode if it is not already in this mode.
+.PP
+This trap is not invoked for characters entered as arguments to
+editing directives, or while reading input for a character search.
+.SS Emacs Editing Mode.
+This mode is entered by enabling either the
+.B emacs
+or
+.B gmacs
+option.
+The only difference between these two modes is the way
+they handle
+.BR ^T .
+To edit, the user
+moves the cursor to the point needing correction and
+then inserts or deletes characters or words as needed.
+All the editing commands are control characters or escape
+sequences.
+The notation for control characters is caret
+.RB ( ^ )
+followed
+by the character.
+For example,
+.B ^F
+is the notation for control
+.BR F .
+This is entered by depressing `f' while holding down the
+`CTRL' (control) key.
+The `SHIFT' key is
+.I not
+depressed.
+(The notation
+.B ^?
+indicates the DEL (delete) key.)
+.PP
+The notation for escape sequences is
+.B M-
+followed by a
+character.
+For example,
+.B M-f
+(pronounced Meta f)
+is entered by depressing ESC
+(ascii
+.BR 033 )
+followed by `f'.
+.RB ( M-F
+would be the notation for ESC followed by `SHIFT' (capital) `F'.)
+.PP
+All edit commands
+operate from any place on the line
+(not just at the beginning).
+Neither the `RETURN' nor the `LINE FEED' key is
+entered after edit commands except when noted.
+.PP
+.PD 0
+.TP 10
+.BI ^F
+Move cursor forward (right) one character.
+.PP
+.TP 10
+.BI M-[C
+Move cursor forward (right) one character.
+.PP
+.TP 10
+.BI M-f
+Move cursor forward one word.
+(The
+.B emacs
+editor's idea of a word is a string of characters
+consisting of only letters, digits and underscores.)
+.PP
+.TP 10
+.BI ^B
+Move cursor backward (left) one character.
+.PP
+.TP 10
+.BI M-[D
+Move cursor backward (left) one character.
+.PP
+.TP 10
+.BI M-b
+Move cursor backward one word.
+.PP
+.TP 10
+.BI ^A
+Move cursor to start of line.
+.PP
+.TP 10
+.BI M-[H
+Move cursor to start of line.
+.PP
+.TP 10
+.BI ^E
+Move cursor to end of line.
+.PP
+.TP 10
+.BI M-[Y
+Move cursor to end of line.
+.PP
+.TP 10
+.BI ^] char
+Move cursor forward to character
+.I char
+on current line.
+.PP
+.TP 10
+.BI M-^] char
+Move cursor backward to character
+.I char
+on current line.
+.PP
+.TP 10
+.BI ^X^X
+Interchange the cursor and mark.
+.PP
+.TP 10
+.I erase
+(User defined erase character as defined
+by the
+.IR stty (1)
+command, usually
+.B ^H
+or
+.BR # .)
+Delete previous character.
+.PP
+.TP 10
+.I lnext
+(User defined literal next character as defined
+by the
+.IR stty (1)
+command,
+or
+.B ^V
+if not defined.)
+Removes the next character's
+editing features (if any).
+.PP
+.TP 10
+.BI ^D
+Delete current character.
+.PP
+.TP 10
+.BI M-d
+Delete current word.
+.PP
+.TP 10
+.BI M-^H
+(Meta-backspace) Delete previous word.
+.PP
+.TP 10
+.BI M-h
+Delete previous word.
+.PP
+.TP 10
+.BI M-^?
+(Meta-DEL) Delete previous word (if your interrupt character is
+.B ^?
+(DEL, the default) then this command will not work).
+.PP
+.TP 10
+.BI ^T
+Transpose current character with previous character
+and advance the cursor
+in
+.I emacs
+mode.
+Transpose two previous characters in
+.I gmacs
+mode.
+.PP
+.TP 10
+.BI ^C
+Capitalize current character.
+.PP
+.TP 10
+.BI M-c
+Capitalize current word.
+.PP
+.TP 10
+.BI M-l
+Change the current word to lower case.
+.PP
+.TP 10
+.BI ^K
+Delete from the cursor to the end of the line.
+If preceded by a numerical parameter whose value is less than the
+current cursor position, then delete from given position
+up to the cursor.
+If preceded by a numerical parameter whose value is greater than the
+current cursor position, then delete from cursor up to
+given cursor position.
+.PP
+.TP 10
+.BI ^W
+Kill from the cursor to the mark.
+.PP
+.TP 10
+.BI M-p
+Push the region from the cursor to the mark on the stack.
+.PP
+.TP 10
+.I kill
+(User defined kill character as defined
+by the stty command, usually
+.B ^G
+or
+.BR @ .)
+Kill the entire current line.
+If two
+.I kill
+characters are entered in succession, all
+kill characters from then on cause a line feed
+(useful when using paper terminals).
+.PP
+.TP 10
+.BI ^Y
+Restore last item removed from line. (Yank item back to the line.)
+.PP
+.TP 10
+.BI ^L
+Line feed and print current line.
+.PP
+.TP 10
+.BI M-^L
+Clear the screen.
+.PP
+.TP 10
+.BI ^@
+(Null character) Set mark.
+.PP
+.TP 10
+.BI M- space
+(Meta space) Set mark.
+.PP
+.TP 10
+.BI ^J
+(New\ line) Execute the current line.
+.PP
+.TP 10
+.BI ^M
+(Return) Execute the current line.
+.PP
+.TP 10
+.I eof
+End-of-file character,
+normally
+.BR ^D ,
+is processed as an End-of-file only
+if the current line is null.
+.PP
+.TP 10
+.BI ^P
+Fetch previous command.
+Each time
+.B ^P
+is entered
+the previous command back in time is accessed.
+Moves back one line when not on the first line of a multi-line command.
+.PP
+.TP 10
+.BI M-[A
+If the cursor is at the end of the line, it is equivalent to
+.B ^R
+with
+.I string\^
+set to the contents of the current line.
+Otherwise, it is
+equivalent to
+.BR ^P.
+.PP
+.TP 10
+.BI M-<
+Fetch the least recent (oldest) history line.
+.PP
+.TP 10
+.BI M->
+Fetch the most recent (youngest) history line.
+.PP
+.TP 10
+.BI ^N
+Fetch next command line.
+Each time
+.B ^N
+is entered
+the next command line forward in time is accessed.
+.PP
+.TP 10
+.BI M-[B
+Equivalent to
+.BR ^N.
+.PP
+.TP 10
+.BI ^R string
+Reverse search history for a previous command line containing
+.IR string .
+If a parameter of zero is given, the search is forward.
+.I String
+is terminated by a `RETURN' or `NEW\ LINE'.
+If string is preceded by a
+.BR ^ ,
+the matched line must begin with
+.IR string .
+If
+.I string
+is omitted,
+then the next command line containing the most recent
+.I string
+is accessed.
+In this case a parameter of zero
+reverses the direction of the search.
+.PP
+.TP 10
+.B ^O
+Operate \- Execute the current line and fetch
+the next line relative to current line from the
+history file.
+.PP
+.TP 10
+.BI M- digits
+(Escape) Define numeric parameter, the digits
+are taken as a parameter to the next command.
+The commands that accept a parameter are
+.BR ^F ,
+.BR ^B ,
+.IR erase ,
+.BR ^C ,
+.BR ^D ,
+.BR ^K ,
+.BR ^R ,
+.BR ^P ,
+.BR ^N ,
+.BR ^] ,
+.BR M-. ,
+.BR M-^] ,
+.BR M-_ ,
+.BR M-= ,
+.BR M-b ,
+.BR M-c ,
+.BR M-d ,
+.BR M-f ,
+.BR M-h ,
+.B M-l
+and
+.BR M-^H .
+.PP
+.TP 10
+.BI M- letter
+Soft-key \- Your alias list is searched for an
+alias by the name
+.BI _ letter
+and if an alias of this name is defined, its
+value will be inserted on the input queue.
+The
+.I letter
+must not be one of the above meta-functions.
+.PP
+.TP 10
+.BI M-[ letter
+Soft-key \- Your alias list is searched for an
+alias by the name
+.BI _\&_ letter
+and if an alias of this name is defined, its
+value will be inserted on the input queue.
+This can be used to program function keys on many terminals.
+.PP
+.TP 10
+.B M-.
+The last word of the previous command is inserted
+on the line.
+If preceded by a numeric parameter, the value
+of this parameter determines which word to insert rather than
+the last word.
+.PP
+.TP 10
+.B M-_
+Same as
+.BR M-. .
+.PP
+.TP 10
+.B M-*
+Attempt file name generation on the current word.
+An asterisk is appended if the word doesn't match any file
+or contain any special
+pattern characters.
+.PP
+.TP 10
+.B M-ESC
+Command or file name completion as described above.
+.PP
+.TP 10
+.BI ^I " tab"
+Attempts command or file name completion as described above.
+If a partial completion occurs, repeating this will
+behave as if
+.B M-=
+were entered.
+If no match is found or entered after
+.IR space\^ ,
+a
+.I tab\^
+is inserted.
+.PP
+.TP 10
+.B M-=
+If not preceded by a numeric parameter,
+it generates the list of matching commands or
+file names as described above.
+Otherwise, the word under the cursor is replaced by
+the item corresponding to the value of the numeric parameter
+from the most recently generated command or file list.
+If the cursor is not on a word, it is inserted instead.
+.PP
+.TP 10
+.BI ^U
+Multiply parameter of next command by 4.
+.PP
+.TP 10
+.BI \e
+Escape next character.
+Editing characters, the user's erase, kill and
+interrupt (normally
+.BR ^? )
+characters
+may be entered
+in a command line or in a search string if preceded by a
+.BR \e .
+The
+.B \e
+removes the next character's
+editing features (if any).
+.PP
+.TP 10
+.B M-^V
+Display version of the shell.
+.PP
+.TP 10
+.B M-#
+If the line does not begin with a
+.BR # ,
+a
+.B #
+is inserted
+at the beginning of the line
+and after each new-line,
+and the line is entered.
+This causes a comment to be inserted in the history file.
+If the line begins with a
+.BR # ,
+the
+.B #
+is deleted and one
+.B #
+after each new-line is also deleted.
+.PD
+.SS Vi Editing Mode.
+There are two typing modes.
+Initially, when you enter a command you are in the
+.I input\^
+mode.
+To edit, the user enters
+.I control\^
+mode by typing ESC
+.RB ( 033 )
+and moves the cursor to the point needing correction and
+then inserts or deletes characters or words as needed.
+Most control commands accept an optional repeat
+.I count
+prior to the command.
+.PP
+When in
+.B vi
+mode on most systems,
+canonical processing is initially enabled and the
+command will be echoed again if the speed is 1200 baud or greater and it
+contains any control characters or less than one second has elapsed
+since the prompt was printed.
+The ESC character terminates canonical processing for the remainder of the command
+and the user can then modify the command line.
+This scheme has the advantages of canonical processing with the type-ahead
+echoing of raw mode.
+.PP
+If the option
+.B viraw
+is also set, the terminal will always have canonical processing
+disabled.
+This mode is implicit for systems that do not support two
+alternate end of line delimiters,
+and may be helpful for certain terminals.
+.SS "\ \ \ \ \ Input Edit Commands"
+.PP
+.RS
+By default the editor is in input mode.
+.PD 0
+.TP 10
+.I erase
+(User defined erase character as defined
+by the stty command, usually
+.B ^H
+or
+.BR # .)
+Delete previous character.
+.TP 10
+.BI ^W
+Delete the previous blank separated word.
+On some systems the \f3viraw\fP option
+may be required for this to work.
+.TP 10
+.I eof
+As the first character of the line causes
+the shell to terminate unless the \f3ignoreeof\fP
+option is set.
+Otherwise this character is ignored.
+.TP 10
+.I lnext
+(User defined literal next character as defined
+by the
+.IR stty (1)
+or
+.B ^V
+if not defined.)
+Removes the next character's
+editing features (if any).
+On some systems the \f3viraw\fP option
+may be required for this to work.
+.TP 10
+.BI \e
+Escape the next
+.I erase
+or
+.I kill
+character.
+.TP 10
+.BI ^I " tab"
+Attempts command or file name completion as described above
+and returns to input mode.
+If a partial completion occurs, repeating this will
+behave as if
+.B =
+were entered from control mode.
+If no match is found or entered after
+.IR space\^ ,
+a
+.I tab\^
+is inserted.
+.RE
+.SS "\ \ \ \ \ Motion Edit Commands"
+.RS
+These commands will move the cursor.
+.TP 10
+[\f2count\fP]\f3l\fP
+Cursor forward (right) one character.
+.TP 10
+[\f2count\fP]\f3[C\fP
+Cursor forward (right) one character.
+.TP 10
+[\f2count\fP]\f3w\fP
+Cursor forward one alpha-numeric word.
+.TP 10
+[\f2count\fP]\f3W\fP
+Cursor to the beginning of the next word that follows a blank.
+.TP 10
+[\f2count\fP]\f3e\fP
+Cursor to end of word.
+.TP 10
+[\f2count\fP]\f3E\fP
+Cursor to end of the current blank delimited word.
+.TP 10
+[\f2count\fP]\f3h\fP
+Cursor backward (left) one character.
+.TP 10
+[\f2count\fP]\f3[D\fP
+Cursor backward (left) one character.
+.TP 10
+[\f2count\fP]\f3b\fP
+Cursor backward one word.
+.TP 10
+[\f2count\fP]\f3B\fP
+Cursor to preceding blank separated word.
+.TP 10
+[\f2count\fP]\f3\(bv\fP
+Cursor to column
+.IR count .
+.TP 10
+[\f2count\fP]\f3f\fP\f2c\fP
+Find the next character \fIc\fP in the current line.
+.TP 10
+[\f2count\fP]\f3F\fP\f2c\fP
+Find the previous character \fIc\fP in the current line.
+.TP 10
+[\f2count\fP]\f3t\fP\f2c\fP
+Equivalent to
+.B f
+followed by
+.BR h .
+.TP 10
+[\f2count\fP]\f3T\fP\f2c\fP
+Equivalent to
+.B F
+followed by
+.BR l .
+.TP 10
+[\f2count\fP]\f3;\fP
+Repeats
+.I count
+times,
+the last single character find command,
+.BR f ,
+.BR F ,
+.BR t ,
+or
+.BR T .
+.TP 10
+[\f2count\fP]\f3,\fP
+Reverses the last single character find command
+.I count
+times.
+.TP 10
+.B 0
+Cursor to start of line.
+.TP 10
+.B ^
+Cursor to start of line.
+.TP 10
+.B [H
+Cursor to first non-blank character in line.
+.TP 10
+.B $
+Cursor to end of line.
+.TP 10
+.B [Y
+Cursor to end of line.
+.TP 10
+.B %
+Moves to balancing
+.BR ( ,
+.BR ) ,
+.BR { ,
+.BR } ,
+.BR [ ,
+or
+.BR ] .
+If cursor is not on one of the above characters,
+the remainder of the line is searched for the first
+occurrence of one of the above characters first.
+.RE
+.SS "\ \ \ \ \ Search Edit Commands"
+.RS
+These commands access your command history.
+.TP 10
+[\f2count\fP]\f3k\fP
+Fetch previous command.
+Each time
+.B k
+is entered
+the previous command back in time is accessed.
+.TP 10
+[\f2count\fP]\f3\-\fP
+Equivalent to
+.BR k .
+.TP 10
+[\f2count\fP]\f3[A\fP
+If cursor is at the end of the line it is equivalent to
+.B /
+with
+.I string^\
+set to the contents of the current line.
+Otherwise, it is equivalent to
+.BR k .
+.TP 10
+[\f2count\fP]\f3j\fP
+Fetch next command.
+Each time
+.B j
+is entered
+the next command forward in time is accessed.
+.TP 10
+[\f2count\fP]\f3+\fP
+Equivalent to
+.BR j .
+.TP 10
+[\f2count\fP]\f3[B\fP
+Equivalent to
+.BR j .
+.TP 10
+[\f2count\fP]\f3G\fP
+The command number
+.I count
+is fetched.
+The default is the least recent history command.
+.TP 10
+.BI / string
+Search backward through history for a previous command containing
+.IR string .
+.I String
+is terminated by a `RETURN' or `NEW\ LINE'.
+If string is preceded by a
+.BR ^ ,
+the matched line must begin with
+.IR string .
+If \fIstring\fP is null, the previous string will be used.
+.TP 10
+.BI ? string
+Same as
+.B /
+except that search will be in the forward direction.
+.TP 10
+.B n
+Search for next match of the last pattern to
+.B /
+or
+.B ?
+commands.
+.TP 10
+.B N
+Search for next match of the last pattern to
+.B /
+or
+.BR ? ,
+but in reverse direction.
+.RE
+.SS "\ \ \ \ \ Text Modification Edit Commands"
+.RS
+These commands will modify the line.
+.TP 10
+.B a
+Enter input mode and enter text after the current character.
+.TP 10
+.B A
+Append text to the end of the line.
+Equivalent to
+.BR $a .
+.TP 10
+[\f2count\fP]\f3c\fP\f2motion\fP
+.TP 10
+\f3c\fP[\f2count\fP]\f2motion\fP
+Delete current character through the character that
+.I motion
+would move the cursor to and enter input mode.
+If \fImotion\fP is
+.BR c ,
+the entire line will be deleted and
+input mode entered.
+.TP 10
+.B C
+Delete the current character through the end of line and enter input mode.
+Equivalent to
+.BR c$ .
+.TP 10
+.B S
+Equivalent to
+.BR cc .
+.TP 10
+[\f2count\fP]\f3s\fP
+Replace characters under the cursor in input mode.
+.TP 10
+.B D
+Delete the current character through the end of line.
+Equivalent to
+.BR d$ .
+.TP 10
+[\f2count\fP]\f3d\fP\f2motion\fP
+.TP 10
+\f3d\fP[\f2count\fP]\f2motion\fP
+Delete current character through the character that
+.I motion
+would move to.
+If \fImotion\fP is
+.B d ,
+the entire line will be deleted.
+.TP 10
+.B i
+Enter input mode and insert text before the current character.
+.TP 10
+.B I
+Insert text before the beginning of the line.
+Equivalent to
+.BR 0i .
+.TP 10
+[\f2count\fP]\f3P\fP
+Place the previous text modification before the cursor.
+.TP 10
+[\f2count\fP]\f3p\fP
+Place the previous text modification after the cursor.
+.TP 10
+.B R
+Enter input mode and
+replace characters on the screen with characters you type overlay fashion.
+.TP 10
+[\f2count\fP]\f3r\fP\f2c\fP
+Replace the
+.I count
+character(s) starting at the current cursor position with
+.IR c ,
+and advance the cursor.
+.TP 10
+[\f2count\fP]\f3x\fP
+Delete current character.
+.TP 10
+[\f2count\fP]\f3X\fP
+Delete preceding character.
+.TP 10
+[\f2count\fP]\f3.\fP
+Repeat the previous text modification command.
+.TP 10
+[\f2count\fP]\f3\(ap\fP
+Invert the case of the
+.I count
+character(s) starting at the current cursor position and advance the cursor.
+.TP 10
+[\f2count\fP]\f3_\fP
+Causes the
+.I count\^
+word of the previous command to be appended and
+input mode entered.
+The last word is used
+if
+.I count\^
+is omitted.
+.TP 10
+.B *
+Causes an
+.B *
+to be appended to the current word and file name generation attempted.
+If no match is found,
+it rings the bell.
+Otherwise, the word is replaced
+by the matching pattern and input mode is entered.
+.TP 10
+.B \e
+Command or file name completion as described above.
+.RE
+.SS "\ \ \ \ \ Other Edit Commands"
+.RS
+Miscellaneous commands.
+.TP 10
+[\f2count\fP]\f3y\fP\f2motion\fP
+.TP 10
+\f3y\fP[\f2count\fP]\f2motion\fP
+Yank current character through character that
+.I motion
+would move the cursor to and puts them into the delete buffer.
+The text and cursor are unchanged.
+.TP 10
+.B yy
+Yanks the entire line.
+.TP 10
+.B Y
+Yanks from current position to end of line.
+Equivalent to
+.BR y$ .
+.TP 10
+.B u
+Undo the last text modifying command.
+.TP 10
+.B U
+Undo all the text modifying commands performed on the line.
+.TP 10
+[\f2count\fP]\f3v\fP
+Returns the command
+.BI "hist \-e ${\s-1VISUAL\s+1:\-${\s-1EDITOR\s+1:\-vi}}" " count"
+in the input buffer.
+If
+.I count\^
+is omitted, then the current line is used.
+.TP 10
+.BI ^L
+Line feed and print current line.
+Has effect only in control mode.
+.TP 10
+.BI ^J
+(New\ line) Execute the current line, regardless of mode.
+.TP 10
+.BI ^M
+(Return) Execute the current line, regardless of mode.
+.TP 10
+.B #
+If the first character of the command is a
+.BR # ,
+then this command deletes this
+.B #
+and each
+.B #
+that follows a newline.
+Otherwise,
+sends the line after
+inserting a
+.B #
+in front of each line in the command.
+Useful for causing the current line to be
+inserted in the history as a comment and
+uncommenting previously commented commands
+in the history file.
+.TP 10
+[\f2count\fP]\f3=\fP
+If \f2count\fP is not specified,
+it generates the list of matching commands or
+file names as described above.
+Otherwise, the word under the the cursor is replaced by the
+\f2count\fP item from the most recently generated command or file list.
+If the cursor is not on a word, it is inserted instead.
+.TP 10
+.BI @ letter
+Your alias list is searched for an
+alias by the name
+.BI _ letter
+and if an alias of this name is defined, its
+value will be inserted on the input queue for processing.
+.TP 10
+.BI ^V
+Display version of the shell.
+.RE
+.PD
+.SS Built-in Commands.
+The following simple-commands are executed in the shell process.
+Input/Output redirection is permitted.
+Unless otherwise indicated, the output is written on file descriptor 1
+and the exit status, when there is no syntax error, is zero.
+Except for
+.BR : ,
+.BR true ,
+.BR false ,
+.BR echo ,
+.BR newgrp ,
+and
+.BR login ,
+all built-in commands accept
+.B \-\-
+to indicate end of options.
+They also interpret the option
+.B \-\-man
+as a request to display the man page onto
+standard error and
+.B \-?
+as a help request which prints a
+.I usage\^
+message
+on standard error.
+Commands that are preceded by one or two \(dg symbols
+are special built-in commands and
+are treated specially in the following ways:
+.PD 0
+.TP
+1.
+Variable assignment lists preceding the command
+remain in effect when the command completes.
+.TP
+2.
+I/O redirections are processed after variable assignments.
+.TP
+3.
+Errors
+cause a script
+that contains them to abort.
+.TP
+4.
+They are not valid function names.
+.TP
+5.
+Words
+following a command preceded by \(dg\(dg
+that are in the format of a variable assignment
+are expanded with the same rules as a variable assignment.
+This means that
+tilde substitution is performed after the
+.B =
+sign and field splitting and file name generation are not
+performed.
+These are called
+.I declaration\^
+built-ins.
+.PD
+.TP
+\(dg \f3:\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The command only expands parameters.
+.br
+.ne 2
+.TP
+\(dg \f3\|. \f2name\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+If
+.I name\^
+is a function defined with the
+.B function
+.I name\^
+reserved word syntax,
+the function is executed in the current environment
+(as if it had been defined with the
+.IB name ()
+syntax.)
+Otherwise if
+.I name\^
+refers to a file, the
+file is read in its entirety and the commands are
+executed in the current shell environment.
+The search path
+specified by
+.B
+.SM PATH
+is used to find the directory containing the file.
+If any arguments
+.I arg\^
+are given,
+they become the positional parameters while processing
+the
+.B .
+command and the original positional parameters are restored upon completion.
+Otherwise the positional parameters are unchanged.
+The exit status is the exit status of the last command executed.
+.TP
+\(dg\(dg \f3alias\fP \*(OK \f3\-ptx\fP \*(CK \*(OK \f2name\fP\*(OK \f3=\fP\f2value\^\fP \*(CK \*(CK .\|.\|.
+.B alias\^
+with no arguments prints the list of aliases
+in the form
+.I name=value\^
+on standard output.
+The
+.B \-p
+option
+causes the word
+.B alias
+to be inserted before each one.
+When one or more arguments are given,
+an
+.I alias\^
+is defined
+for each
+.I name\^
+whose
+.I value\^
+is given.
+A trailing space in
+.I value\^
+causes the next word to be checked for
+alias substitution.
+The obsolete
+.B \-t
+option is used to set and list tracked aliases.
+The value of a tracked alias is the full pathname
+corresponding to the given
+.IR name .
+The value becomes undefined when the value of
+.SM
+.B PATH
+is reset but the alias remains tracked.
+Without the
+.B \-t
+option,
+for each
+.I name\^
+in the argument list
+for which no
+.I value\^
+is given, the name
+and value of the alias is printed.
+The obsolete
+.B \-x
+option has no effect.
+The exit status is non-zero if a
+.I name\^
+is given, but no value, and no alias has been defined for the
+.IR name\^ .
+.TP
+\f3bg\fP \*(OK \f2job\^\fP.\|.\|. \*(CK
+This command is only on systems that support job control.
+Puts each specified
+.I job\^
+into the background.
+The current job is put in the background
+if
+.I job\^
+is not specified.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+\(dg \f3break\fP \*(OK \f2n\^\fP \*(CK
+Exit from the enclosing
+.BR for\^ ,
+.BR while\^ ,
+.BR until\^ ,
+or
+.B select\^
+loop, if any.
+If
+.I n\^
+is specified, then break
+.I n\^
+levels.
+.TP
+\f3builtin\fP \*(OK \f3\-ds\fP \*(CK \*(OK \f3\-f\fP \f2file\^\fP \*(CK \*(OK \f2name\^\fP .\|.\|. \*(CK
+If
+.I name\^
+is not specified,
+and no
+.B \-f
+option is specified,
+the built-ins are printed on standard output.
+The
+.B \-s
+option prints only the special built-ins.
+Otherwise, each
+.I name\^
+represents the pathname whose basename is the name of the built-in.
+The entry point function name is determined by prepending
+.B b_
+to the built-in name.
+The ISO C/C++ prototype is
+\f3b_\fP\f2mycommand\fP\f3(int\fP \f2argc\fP, \f3char *\fP\f2argv\fP\f3[]\fP, \f3void *\fP\f2context\fP\f3)\fP
+for the builtin command
+.I mycommand\^
+where
+.I argv\^
+is array an of
+.I argc\^
+elements and context is an optional pointer to a
+.B Shell_t
+structure as described in
+.BR <ast/shell.h> .
+.sp .5
+Special built-ins cannot be bound to a pathname or deleted.
+The
+.B \-d
+option deletes each of the given built-ins.
+On systems that support dynamic loading, the
+.B \-f
+option names a shared library containing the code for built-ins.
+The shared library prefix and/or suffix, which depend on the system,
+can be omitted.
+Once a library is loaded, its symbols become available
+for subsequent invocations of
+.BR builtin .
+Multiple libraries can be specified with separate invocations
+of the
+.B builtin
+command.
+Libraries are searched in the reverse order in which they are specified.
+When a library is loaded, it looks for a function in the library
+whose name is
+.B lib_init()
+and invokes this function with an argument of
+.BR 0 .
+.TP
+.PD 0
+\f3cd\fP \*(OK \f3\-LP\fP \*(CK \*(OK \f2arg\^\fP \*(CK
+.TP
+\f3cd\fP \*(OK \f3\-LP\fP \*(CK \f2old\^\fP \f2new\^\fP
+.PD
+This command can be in either of two forms.
+In the first form it
+changes the current directory to
+.IR arg .
+If
+.I arg\^
+is
+.B \-
+the directory is changed to the previous
+directory.
+The shell
+variable
+.B
+.SM HOME
+is the default
+.IR arg .
+The variable
+.SM
+.B PWD
+is set to the current directory.
+The shell variable
+.B
+.SM CDPATH
+defines the search path for
+the directory containing
+.IR arg .
+Alternative directory names are separated by
+a colon
+.RB ( : ).
+The default path is
+.B <null>
+(specifying the current directory).
+Note that the current directory is specified by a null path name,
+which can appear immediately after the equal sign
+or between the colon delimiters anywhere else in the path list.
+If
+.I arg
+begins with a \f3/\fP then the search path
+is not used.
+Otherwise, each directory in the path is
+searched for
+.IR arg .
+.sp .5
+The second form of
+.B cd
+substitutes the string
+.I new
+for the string
+.I old
+in the current directory name,
+.SM
+.BR PWD ,
+and tries to change to this new directory.
+.sp .5
+By default, symbolic link names are treated literally when
+finding the directory name.
+This is equivalent to the
+.B \-L
+option.
+The
+.B \-P
+option causes
+symbolic links to be resolved when determining the directory.
+The last instance of
+.B \-L
+or
+.B \-P
+on the command line
+determines which method is used.
+.sp .5
+The
+.B cd\^
+command may not be executed by
+.if \nZ=0 .B rsh\^.
+.if \nZ=1 .B rksh\^.
+.if \nZ=1 .B rksh93\^.
+.TP
+\f3command\fP \*(OK \f3\-pvxV\fP \*(CK \f2name\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+Without the
+.B \-v
+or
+.B \-V
+options,
+.B command
+executes
+.I name\^
+with the arguments given by
+.IR arg .
+The
+.B \-p
+option causes
+a default path to be searched
+rather than the one defined by the value of
+.SM
+.BR PATH .
+Functions will not be searched for when finding
+.IR name .
+In addition, if
+.I name\^
+refers to a special built-in,
+none of the special properties associated with the leading
+daggers will be honored.
+(For example, the predefined alias
+.B "redirect=\(fmcommand exec\(fm"
+prevents a script from terminating when an invalid
+redirection is given.)
+With the
+.B \-x
+option,
+if command execution would result in a failure because
+there are too many arguments, errno
+.SM
+.BR E2BIG ,
+the shell will invoke command
+.I name\^
+multiple times with a subset of the arguments on each invocation.
+Arguments that occur prior to the first word that
+expands to multiple arguments and after the last word
+that expands to multiple arguments will be passed on each invocation.
+The exit status will be the maximum invocation exit status.
+With the
+.B \-v
+option,
+.B command
+is equivalent to the built-in
+.B whence
+command described below.
+The
+.B \-V
+option causes
+.B command
+to act like
+.BR "whence \-v" .
+.TP
+\(dg \f3continue\fP \*(OK \f2n\^\fP \*(CK
+Resume the next iteration of the enclosing
+.BR for\^ ,
+.BR while\^ ,
+.BR until\^ ,
+or
+.B select\^
+loop.
+If
+.I n\^
+is specified, then resume at the
+.IR n -th
+enclosing loop.
+.TP
+\f3disown\fP \*(OK \f2job\^\fP.\|.\|. \*(CK
+Causes the shell not to send a HUP signal to
+each given
+.IR job ,
+or all active jobs if
+.I job
+is omitted,
+when a login shell terminates.
+.TP
+\f3echo\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+When the first
+.I arg\^
+does not begin with a \-, and
+none of the arguments contain a \e,
+then
+.B echo
+prints each of its arguments separated by a space
+and terminated by a new-line.
+Otherwise, the behavior of
+.B echo
+is system dependent
+and
+.B print
+or
+.B printf
+described below should be used.
+See
+.IR echo (1)
+for usage and description.
+.TP
+\(dg\(dg \f3enum\fP \*(OK \f3\-i\fP \*(CK \f2type\^\fP\*(OK=(\f2value\^\fP .\|.\|.) \*(CK
+Creates a declaration command named \f2type\^\fP that is an
+integer type that allows one of the specified \f2value\fPs as
+enumeration names. If \f3=(\fP\f2value\^\ .\|.\|.\|\fP\f3)\fP is
+omitted, then \f2type\^\fP must be an indexed array variable with at
+least two elements and the values are taken from this array variable.
+If
+.B -i
+is specified the values are case insensitive.
+.TP
+\(dg \f3eval\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The arguments are read as input
+to the shell
+and the resulting command(s) executed.
+.TP
+\(dg \f3exec\fP \*(OK \f3\-c\fP \*(CK \*(OK \f3\-a\fP \f2name\^\fP \*(CK \*(OK \f2arg\^\fP .\|.\|. \*(CK
+If
+.I arg\^
+is given,
+the command specified by
+the arguments is executed in place of this shell
+without creating a new process.
+The
+.B \-c
+option causes the environment to be cleared before applying
+variable assignments associated with the
+.B exec
+invocation.
+The
+.B \-a
+option
+causes
+.I name\^
+rather than the first
+.IR arg ,
+to become
+.B argv[0]
+for the new process.
+Input/output arguments may appear and
+affect the current process.
+If
+.I arg\^
+is not given,
+the effect of this command is to
+modify file descriptors
+as prescribed by the input/output redirection list.
+In this case,
+any file descriptor numbers greater than 2 that are
+opened with this mechanism are closed when invoking
+another program.
+.TP
+\(dg \f3exit\fP \*(OK \f2n\^\fP \*(CK
+Causes the shell to exit
+with the exit status specified by
+.IR n .
+The value will be the least significant 8 bits of the specified status.
+If
+.I n\^
+is omitted, then the exit status is that of the last command executed.
+An end-of-file will also cause the shell to exit
+except for a
+shell which has the
+.B ignoreeof
+option (see
+.B set
+below) turned on.
+.TP
+\(dg\(dg \f3export\fP \*(OK \f3\-p\fP \*(CK \*(OK \f2name\^\fP\*(OK\f3=\fP\f2value\^\fP\*(CK \*(CK .\|.\|.
+If
+.I name\^
+is not given,
+the names and values of each variable with
+the export attribute are printed with the values
+quoted in a manner that allows them to be re-input.
+The
+.B export
+command is the same as
+.B typeset \-x
+except that if you use
+.B export
+within a function, no local
+variable is created.
+The
+.B \-p
+option
+causes the word
+.B export
+to be inserted before each one.
+Otherwise, the given
+.IR name s
+are marked for automatic
+export to the
+.I environment\^
+of subsequently-executed commands.
+.TP
+\f3false\fP
+Does nothing, and exits 1. Used with
+.B until
+for infinite loops.
+.TP
+\f3fg\fP \*(OK \f2job\^\fP.\|.\|. \*(CK
+This command is only on systems that support job control.
+Each
+.I job\^
+specified is brought to the foreground and waited for in
+the specified order.
+Otherwise, the current job is
+brought into the foreground.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+\f3getconf\fP \*(OK \f2name\^\fP \*(OK \f2pathname\^\fP \*(CK \*(CK
+Prints the current value of the configuration parameter given by
+.IR name .
+The configuration parameters are defined by the IEEE POSIX 1003.1
+and IEEE POSIX 1003.2 standards.
+(See
+.IR pathconf (2)
+and
+.IR sysconf (2).)
+The
+.I pathname
+argument is required for parameters whose value depends on
+the location in the file system.
+If no arguments are given,
+.B getconf
+prints the names and values of the current configuration
+parameters.
+The pathname
+.B /
+is used for each of the parameters that requires
+.IR pathname .
+.TP
+\f3getopts\fP \*(OK \f3\ \-a\fP \f2name\^\fP \*(CK \f2optstring vname\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+Checks
+.I arg
+for legal options.
+If
+.I arg
+is omitted,
+the positional parameters are used.
+An option argument begins with a
+.B +
+or a
+.BR \- .
+An option not beginning with
+.B +
+or
+.B \-
+or the argument
+.B \-\|\-
+ends the options.
+Options beginning with
+.B +
+are only recognized when
+.I optstring\^
+begins with a
+.BR + .
+.I optstring\^
+contains the letters that
+.B getopts
+recognizes.
+If a letter is followed by a
+.BR : ,
+that option is expected to have an argument.
+The options can be separated from the argument by blanks.
+The option
+.B \-?
+causes
+.B getopts
+to generate a usage message on standard error.
+The
+.B \-a
+argument can be used to specify the name to use for the
+usage message, which defaults to
+.BR $0 .
+.sp .5
+.B
+getopts
+places the next option letter it finds inside variable
+.I vname\^
+each time it is invoked.
+The option letter will be prepended with a
+.B +
+when
+.I arg
+begins with a
+.BR + .
+The index of the next
+.I arg
+is stored in
+.SM
+.BR OPTIND .
+The option argument,
+if any,
+gets stored in
+.SM
+.BR OPTARG .
+.sp .5
+A leading
+.B :
+in
+.I optstring
+causes
+.B getopts
+to store the letter of an invalid
+option in
+.SM
+.BR OPTARG ,
+and to set
+.I vname
+to
+.B ?
+for an unknown option and to
+.B :
+when a required option argument is missing.
+Otherwise,
+.B getopts
+prints an error message.
+The exit status is non-zero when there are no more options.
+.sp .5
+There is no way to specify any of the options
+.BR : ,
+.BR + ,
+.BR \- ,
+.BR ? ,
+.BR [ ,
+and
+.BR ] .
+The option
+.B #
+can only be specified as the first option.
+.TP
+.PD 0
+\f3hist\fP \*(OK \f3\-e\fP \f2ename\^\fP \ \*(CK \*(OK \f3\-nlr\^\fP \*(CK \*(OK \f2first\^\fP \*(OK \f2last\^\fP \*(CK \*(CK
+.TP
+\f3hist \-s \fP \*(OK \f2old\fP\f3\=\fP\f2new\^\fP \*(CK \*(OK \f2command\^\fP \*(CK
+.PD
+In the first form,
+a range of commands from
+.I first\^
+to
+.I last\^
+is selected from the last
+.SM
+.B HISTSIZE
+commands that were typed at the terminal.
+The arguments
+.I first\^
+and
+.I last\^
+may be specified as a number or as a string.
+A string is used to locate the most recent command starting with
+the given string.
+A negative number is used as an offset to the current command number.
+If the
+.B \-l
+option
+is selected,
+the commands are listed on standard output.
+Otherwise, the editor program
+.I ename\^
+is invoked on a file containing these
+keyboard commands.
+If
+.I ename\^
+is not supplied, then the value of the variable
+.SM
+.B HISTEDIT
+is used.
+If
+.SM
+.B HISTEDIT
+is not set, then
+.SM
+.B FCEDIT
+(default
+.BR /bin/ed\^ )
+is used as the editor.
+When editing is complete, the edited command(s)
+is executed if the changes have been saved.
+If
+.I last\^
+is not specified,
+then it will be set to
+.IR first .
+If
+.I first\^
+is not specified,
+the default is the previous command
+for editing and \-16 for listing.
+The option
+.B \-r
+reverses the order of the commands and
+the option
+.B \-n
+suppresses command numbers when listing.
+In the second form,
+.I command\^
+is interpreted as
+.I first\^
+described above
+and defaults to the last command executed.
+The resulting command is executed
+after the optional substitution
+\f2old\^\fP\f3=\fP\f2new\^\fP
+is performed.
+.TP
+\f3jobs\fP \*(OK \f3\-lnp\^\fP \*(CK \*(OK \f2job\^\fP \.\|.\|. \*(CK
+Lists information about each given job; or all active jobs if
+.I job
+is omitted.
+The
+.B \-l
+option lists process ids in addition to the normal information.
+The
+.B \-n
+option only displays jobs that have stopped or exited since last
+notified.
+The
+.B \-p
+option causes only the process group to be listed.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+.PD 0
+\f3kill\fP \*(OK \f3\-s\fP \f2signame\^\fP \*(CK \f2job\^\fP .\|.\|.
+.TP
+.PD 0
+\f3kill\fP \*(OK \f3\-n\fP \f2signum\^\fP \*(CK \f2job\^\fP .\|.\|.
+.TP
+\f3kill\fP \f3\-l\fP \*(OK \f2sig\^\fP .\|.\|. \*(CK
+.PD
+Sends either the TERM (terminate) signal or the
+specified signal to the specified jobs or processes.
+Signals are either given by number with the
+.B \-n
+option or by name with the
+.B \-s
+option
+(as given in
+.BR <signal.h> ,
+stripped of the prefix ``SIG'' with
+the exception that SIGCLD is named CHLD).
+For backward compatibility, the
+.B n
+and
+.B s
+can be omitted and the number or name placed immediately
+after the
+.BR \- .
+If the signal being sent is TERM (terminate) or HUP (hangup),
+then the job or process will be sent a CONT (continue) signal
+if it is stopped.
+The argument
+.I job\^
+can be the process id of a process that is not a member of one of the
+active jobs.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+In the third form,
+.BR "kill \-l" ,
+if
+.I sig\^
+is not specified,
+the signal names are listed.
+Otherwise, for each
+.I sig\^
+that is a name, the corresponding signal number is listed.
+For each
+.I sig\^
+that is a number, the signal name corresponding to the
+least significant 8 bits of
+.I sig\^
+is listed.
+.TP
+\f3let\fP \f2arg\^\fP .\|.\|.
+Each
+.I arg
+is a separate
+.I "arithmetic expression"
+to be evaluated.
+.B let
+only recognizes octal constants starting with
+.B 0
+when the
+.B set
+option
+.B letoctal
+is on.
+See
+.I "Arithmetic Evaluation"
+above, for a description of arithmetic expression evaluation.
+.sp .5
+The exit status is
+0 if the value of the last expression
+is non-zero, and 1 otherwise.
+.TP
+\(dg \f3newgrp\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+Equivalent to
+.BI "exec /bin/newgrp" " arg\^"
+\&.\|.\|.\^.
+.TP
+\f3print\fP \*(OK \f3\-CRenprsv\^\fP \*(CK \*(OK \f3\-u\fP \f2unit\^\fP\*(CK \*(OK \f3\-f\fP \f2format\^\fP \*(CK \*(OK \f2arg\^\fP .\|.\|. \*(CK
+With no options or with option
+.B \-
+or
+.BR \-\|\- ,
+each
+.I arg
+is printed
+on standard output.
+The
+.B \-f
+option causes the arguments to be printed as
+described by
+.BR printf .
+In this case, any
+.BR e ,
+.BR n ,
+.BR r ,
+.B R
+options are ignored.
+Otherwise,
+unless the
+.BR \-C ,
+.BR \-R ,
+.BR \-r ,
+or
+.B \-v
+are specified, the following
+escape conventions will be applied:
+.RS
+.PD 0
+.TP
+.B \ea
+The alert character (ascii
+.BR 07 ).
+.TP
+.B \eb
+The backspace character (ascii
+.BR 010 ).
+.TP
+.B \ec
+Causes
+.B print
+to end without processing more arguments and
+not adding a new-line.
+.TP
+.B \ef
+The formfeed character (ascii
+.BR 014 ).
+.TP
+.B \en
+The new-line character (ascii
+.BR 012 ).
+.TP
+.B \er
+The carriage return character (ascii
+.BR 015 ).
+.TP
+.B \et
+The tab character (ascii
+.BR 011 ).
+.TP
+.B \ev
+The vertical tab character (ascii
+.BR 013 ).
+.TP
+.B \eE
+The escape character (ascii
+.BR 033 ).
+.TP
+.B \e\e
+The backslash character \e.
+.TP
+.BI \e0 x
+The character defined by the 1, 2, or 3-digit octal
+string given by \fIx\fP.
+.PD
+.PP
+The
+.B \-R
+option will print all subsequent arguments and options
+other than
+.BR \-n .
+The
+.B \-e
+causes the above escape conventions to be applied.
+This is the default behavior.
+It reverses the effect of an earlier
+.BR \-r .
+The
+.B \-p
+option causes the
+arguments to be written onto the pipe
+of the process spawned with
+.B \(bv&
+instead of standard output.
+The
+.B \-v
+option treats each
+.I arg\^
+as a variable name and writes the value in
+the
+.B printf
+.B %B
+format.
+The
+.B \-C
+option treats each
+.I arg\^
+as a variable name and writes the value in
+the
+.B printf
+.B %#B
+format.
+The
+.B \-s
+option causes the
+arguments to be written onto the history file
+instead of standard output.
+The
+.B \-u
+option can be used to specify a one digit
+file descriptor unit number
+.I unit\^
+on which the
+output will be placed.
+The default is 1.
+If the option
+.B \-n
+is used, no
+.B new-line\^
+is added to the output.
+.RE
+.TP
+\f3printf\fP \f2format\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The arguments
+.I arg\^
+are printed on standard output
+in accordance with the ANSI-C
+formatting rules associated with the format string
+.IR format .
+If the number of arguments exceeds the number of
+format specifications, the
+.B format\^
+string is reused to format remaining arguments.
+The following extensions can also be used:
+.RS
+.PD 0
+.TP
+.B %b
+A
+.B %b
+format can be used instead of
+.B %s
+to cause escape sequences in the corresponding
+.I arg\^
+to be expanded as described in
+.BR print.
+.TP
+.B %B
+A
+.B %B
+option causes each of the arguments to be treated
+as variable names and the binary value of variable
+will be printed.
+The alternate flag
+.B #
+causes a compound variable to be output on a single line.
+This is most useful for compound variables and variables whose attribute
+is
+.BR \-b .
+.TP
+.B %H
+A
+.B %H
+format can be used instead of
+.B %s
+to cause characters in
+.I arg\^
+that are special in HTML and XML
+to be output as their entity name.
+The alternate flag
+.B #
+formats the output for use as a URI.
+.TP
+.B %P
+A
+.B %P
+format can be used instead of
+.B %s
+to cause
+.I arg\^
+to be interpreted as an extended regular
+expression and be printed as a shell pattern.
+.TP
+.B %R
+A
+.B %R
+format can be used instead of
+.B %s
+to cause
+.I arg\^
+to be interpreted as a shell pattern
+and to be printed as an extended regular expression.
+.TP
+.B %q
+A
+.B %q
+format can be used instead of
+.B %s
+to cause the resulting string to be quoted in a manner than can
+be reinput to the shell.
+When
+.B q
+is preceded by the alternative format specifier,
+.BR # ,
+The string is quoted in manner suitable as a field in a
+.B .csv
+format file.
+.TP
+.BI %( date-format )T
+A
+.BI %( date-format )T
+format can be use to treat an argument as a date/time string
+and to format the date/time according to the
+.I date-format\^
+as defined for the
+.BR date (1)
+command.
+.TP
+.B %Z
+A
+.B %Z
+format will output a byte whose value is 0.
+.TP
+.B %d
+The precision field of the
+.B %d
+format can be followed by a
+.B .
+and the output base.
+In this case, the
+.B #
+flag character causes
+.IB base #
+to be prepended.
+.TP
+.B #
+The
+.B #
+flag, when used with the
+.B %d
+format without an output base,
+displays the output in powers of 1000 indicated by one of the following suffixes:
+.BR "k M G T P E" ,
+and when used with the
+.B %i
+format displays the output in powers of 1024 indicated by one of the following suffixes:
+.BR "Ki Mi Gi Ti Pi Ei" .
+.TP
+.B =
+The
+.B =
+flag centers the output within the specified field width.
+.TP
+.B L
+The
+.B L
+flag, when used with the
+.B %c
+or
+.B %s
+formats, treats precision as character width instead of byte count.
+.TP
+.B ,
+The
+.B ,
+flag, when used with the
+.B %d
+or
+.B %f
+formats, separates groups of digits with the grouping delimiter
+.RB ( ,
+on groups of 3 in the C locale.)
+.PD
+.PP
+.RE
+.TP
+\f3pwd\fP \*(OK \f3\-LP\fP \*(CK
+Outputs the value of the current working
+directory.
+The
+.B \-L
+option is the default; it prints the logical name of the current directory.
+If the
+.B \-P
+option is given,
+all symbolic links are resolved from the name.
+The last instance of
+.B \-L
+or
+.B \-P
+on the command line
+determines which method is used.
+.TP
+\f3read\fP \*(OK \f3\-ACSprsv\^\fP \*(CK \*(OK \f3\-d\fP \f2delim\^\fP\*(CK \*(OK \f3\-n\fP \f2n\^\fP\*(CK \*(OK \*(OK \f3\-N\fP \f2n\^\fP\*(CK \*(OK \*(OK \f3\-t\fP \f2timeout\^\fP\*(CK \*(OK \f3\-u\fP \f2unit\^\fP\*(CK \*(OK \f2vname\f3?\f2prompt\^\f1 \*(CK \*(OK \f2vname\^\fP .\|.\|. \*(CK
+The shell input mechanism.
+One line is read and
+is broken up into fields using the characters in
+.B
+.SM IFS
+as separators.
+The escape character,
+.BR \e ,
+is used to remove any special meaning for the next
+character and for line continuation.
+The
+.B \-d
+option
+causes the read to continue to the first character of
+.I delim\^
+rather than new-line.
+The
+.B \-n
+option causes at most
+.I n\^
+bytes to read rather a full line
+but will return when reading from a slow device
+as soon as any characters have been read.
+The
+.B \-N
+option causes exactly
+.I n\^
+to be read unless an end-of-file has been encountered or
+the read times out because of the
+.B \-t
+option.
+In raw mode,
+.B \-r,
+the
+.B \e
+character is not treated specially.
+The first
+field is assigned to the first
+.IR vname ,
+the second field
+to the second
+.IR vname ,
+etc., with leftover fields assigned to the last
+.IR vname .
+When
+.IR vname
+has the binary attribute and
+.B \-n
+or
+.B \-N
+is specified, the bytes that are read are stored directly
+into the variable.
+If the
+.B \-v
+is specified, then the value of the first
+.I vname\^
+will be used as a default value when reading from a terminal device.
+The
+.B \-A
+option causes the variable
+.I vname\^
+to be unset and each field that is read to be stored in
+successive elements of the indexed array
+.IR vname.
+The
+.B \-C
+option causes the variable
+.I vname\^
+to be read as a compound variable. Blanks will be ignored when
+finding the beginning open parenthesis.
+The \-S
+option causes the line to be treated like a record in a
+.B .csv
+format file so that double quotes can be used to allow the delimiter
+character and the new-line character to appear within a field.
+The
+.B \-p
+option causes the input line
+to be taken from the input pipe
+of a process spawned by the shell
+using
+.BR \(bv& .
+If the
+.B \-s
+option is present,
+the input will be saved as a command in the history file.
+The option
+.B \-u
+can be used to specify a one digit file
+descriptor unit
+.I unit\^
+to read from.
+The file descriptor can be opened with the
+.B exec\^
+special built-in command.
+The default value of unit
+.I n\^
+is 0.
+The option
+.B \-t
+is used to specify a timeout in
+seconds when reading from a terminal or pipe.
+If
+.I vname\^
+is omitted, then
+.SM
+.B REPLY
+is used as the default
+.IR vname .
+An end-of-file with the
+.B \-p
+option causes cleanup for this process
+so that another can be spawned.
+If the first argument contains a
+.BR ? ,
+the remainder of this word is used as a
+.I prompt\^
+on standard error
+when the shell is interactive.
+The exit status is 0 unless an end-of-file is encountered
+or
+.B read
+has timed out.
+.TP
+\(dg\(dg \f3readonly\fP \*(OK \f3\-p\fP \*(CK \*(OK \f2vname\fP\*(OK\f3=\fP\f2value\^\fP\*(CK \*(CK .\|.\|.
+If
+.I vname\^
+is not given,
+the names and values of each variable with
+the readonly attribute is printed with the values
+quoted in a manner that allows them to be re-inputted.
+The
+.B \-p
+option
+causes the word
+.B readonly
+to be inserted before each one.
+Otherwise, the given
+.IR vname s
+are marked
+readonly and these
+names cannot be changed
+by subsequent assignment.
+When defining a type, if the value of a readonly sub-variable is not defined
+the value is required when creating each instance.
+.TP
+\(dg \f3return\fP \*(OK \f2n\^\fP \*(CK
+Causes a shell
+.I function
+or
+\f3\|.\fP
+script to return
+to the invoking script
+with the exit status specified by
+.IR n .
+The value will be the least significant 8 bits of the specified status.
+If
+.I n\^
+is omitted, then the return status is that of the last command executed.
+If
+.B return
+is invoked while not in a
+.I function
+or a
+\f3\|.\fP
+script,
+then it behaves the same as
+.BR exit .
+.TP
+\(dg \f3set\fP \*(OK \f3\(+-BCGabefhkmnoprstuvx\fP \*(CK \*(OK \f3\(+-o\fP \*(OK \f2option\^\fP \*(CK \*(CK .\|.\|. \*(OK \f3\(+-A\fP \f2vname\^\fP \*(CK \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The options for this command have meaning as follows:
+.RS
+.PD 0
+.TP 8
+.B \-A
+Array assignment.
+Unset the variable
+.I vname
+and assign values sequentially from the
+.I arg\^
+list.
+If
+.B +A
+is used, the variable
+.I vname
+is not unset first.
+.TP 8
+.B \-B
+Enable brace pattern field generation.
+This is the default behavior.
+.TP 8
+.B \-B
+Enable brace group expansion. On by default.
+.TP 8
+.B \-C
+Prevents redirection
+.B >
+from truncating existing files.
+Files that are created are opened with the O_EXCL mode.
+Requires
+.B >\(bv
+to truncate a file when turned on.
+.TP 8
+.B \-G
+Causes the pattern
+.B \(**\(**
+by itself to match files and zero or more directories and sub-directories
+when used for file name generation.
+If followed by a
+.B /
+only directories and sub-directories are matched.
+.TP 8
+.B \-a
+All subsequent variables that are defined are automatically exported.
+.TP 8
+.B \-b
+Prints job completion messages as soon as a background job changes
+state rather than waiting for the next prompt.
+.TP 8
+.B \-e
+Unless contained in a
+.B \(bv\(bv
+or
+.B &&
+command, or the command following an
+.B if
+.B while
+or
+.B until
+command or in the pipeline following
+.BR ! ,
+if a command has a non-zero exit status,
+execute the
+.SM
+.B ERR
+trap, if set,
+and exit.
+This mode is disabled while reading profiles.
+.TP 8
+.B \-f
+Disables file name generation.
+.TP 8
+.B \-h
+Each command
+becomes a tracked alias when first encountered.
+.TP 8
+.B \-k
+(Obsolete). All variable assignment arguments are placed in the environment for a command,
+not just those that precede the command name.
+.TP 8
+.B \-m
+Background jobs will run in a separate process group
+and a line will print upon completion.
+The exit status of background jobs is reported in a completion message.
+On systems with job control,
+this option is turned on automatically for
+interactive shells.
+.TP 8
+.B \-n
+Read commands and check them for syntax errors, but do not execute them.
+Ignored for interactive shells.
+.TP 8
+.B \-o
+The following argument can be one of the following option names:
+.RS
+.TP 8
+.B allexport
+Same as
+.BR \-a .
+.TP 8
+.B errexit
+Same as
+.BR \-e .
+.TP 8
+.B bgnice
+All background jobs are run at a lower priority.
+This is the default mode.
+.TP 8
+.B braceexpand
+Same as
+.BR \-B .
+.TP 8
+.B emacs
+Puts you in an
+.I emacs
+style in-line editor for command entry.
+.TP 8
+.B globstar
+Same as
+.BR \-G .
+.TP 8
+.B gmacs
+Puts you in a
+.I gmacs
+style in-line editor for command entry.
+.TP 8
+.B ignoreeof
+The shell will not exit on end-of-file.
+The command
+.B exit
+must be used.
+.TP 8
+.B keyword
+Same as
+.BR \-k .
+.TP 8
+.B letoctal
+The
+.B let
+command allows octal constants starting with
+.BR 0 .
+.TP 8
+.B markdirs
+All directory names resulting from file name generation have a trailing
+.B /
+appended.
+.TP 8
+.B monitor
+Same as
+.BR \-m .
+.TP 8
+.B multiline
+The built-in editors will use multiple lines on the screen for lines
+that are longer than the width of the screen. This may not work
+for all terminals.
+.TP 8
+.B noclobber
+Same as
+.BR \-C .
+.TP 8
+.B noexec
+Same as
+.BR \-n .
+.TP 8
+.B noglob
+Same as
+.BR \-f .
+.TP 8
+.B nolog
+Do not save function definitions in the history file.
+.TP 8
+.B notify
+Same as
+.BR \-b .
+.TP 8
+.B nounset
+Same as
+.BR \-u .
+.TP 8
+.B pipefail
+A pipeline will not complete until all components
+of the pipeline have completed, and the return value
+will be the value of the last non-zero command
+to fail or zero if no command has failed.
+.TP 8
+.B showme
+When enabled, simple commands or pipelines preceded by a semicolon
+.RB ( ; )
+will be displayed as if the
+.B xtrace
+option were enabled but will not be executed.
+Otherwise, the leading
+.B ;
+will be ignored.
+.TP 8
+.B privileged
+Same as
+.BR \-p .
+.TP 8
+.B verbose
+Same as
+.BR \-v .
+.TP 8
+.B trackall
+Same as
+.BR \-h .
+.TP 8
+.B vi
+Puts you in insert mode of a
+.I vi\^
+style in-line editor
+until you hit the escape character
+.BR 033 .
+This puts you in control mode.
+A return sends the line.
+.TP 8
+.B viraw
+Each character is processed as it is typed
+in
+.I vi\^
+mode.
+.TP 8
+.B xtrace
+Same as
+.BR \-x .
+.PP
+If no option name is supplied, then the current option settings are printed.
+.RE
+.TP 8
+.B \-p
+Disables processing of the
+.B \s-1$HOME\s+1/.profile
+file and uses the file
+.B /etc/suid_profile
+instead of the
+.SM
+.B ENV
+file.
+This mode is on whenever the effective uid (gid)
+is not equal to the real uid (gid).
+Turning this off causes the effective uid and gid to be
+set to the real uid and gid.
+.TP 8
+.B \-r
+Enables the restricted shell. This option cannot be unset
+once set.
+.TP 8
+.B \-s
+Sort the positional parameters lexicographically.
+.TP 8
+.B \-t
+(Obsolete). Exit after reading and executing one command.
+.TP 8
+.B \-u
+Treat unset parameters as an error when substituting.
+.TP 8
+.B \-v
+Print shell input lines as they are read.
+.TP 8
+.B \-x
+Print commands and their arguments as they are executed.
+.TP 8
+.B \-\|\-
+Do not change any of the options; useful in setting
+.B $1
+to a value beginning with
+.BR \- .
+If no arguments follow this option then the positional parameters are unset.
+.PD
+.PP
+As an obsolete feature,
+if the first
+.I arg\^
+is
+.B \-
+then the
+.B \-x
+and
+.B \-v
+options are turned off and the next
+.I arg
+is treated as the first argument.
+Using
+.B \+
+rather than
+.B \-
+causes these options to be turned off.
+These options can also be used upon invocation of the shell.
+The current set of options may be found in
+.BR $\- .
+Unless
+.B \-A
+is specified,
+the remaining arguments are positional
+parameters and are assigned, in order, to
+.B $1
+.B $2
+\&.\|.\|.\^.
+If no arguments are given, then the names and values
+of all variables are printed on the standard output.
+.RE
+.TP
+\(dg \f3shift\fP \*(OK \f2n\^\fP \*(CK
+.br
+The positional parameters from
+\f3$\fP\f2n\fP\f3+1\fP
+\&.\|.\|.
+are renamed
+.B $1
+\&.\|.\|.\^
+, default
+.I n\^
+is 1.
+The parameter
+.I n\^
+can be any arithmetic expression that evaluates to a non-negative
+number less than or equal to
+.BR $# .
+.TP
+\f3sleep\fP \f2seconds\^\fP
+Suspends execution for the number of decimal seconds or fractions of a
+second given by
+.IR seconds .
+.TP
+\(dg \f3trap\fP \*(OK \f3\-p\fP \*(CK \*(OK \f2action\^\fP \*(CK \*(OK \f2sig\^\fP \*(CK .\|.\|.
+The
+.B \-p
+option causes the trap
+action associated with each trap as specified by the arguments
+to be printed with appropriate quoting.
+Otherwise,
+.I action\^
+will be processed as if it were an argument to
+.B eval
+when the shell
+receives signal(s)
+.IR sig .
+Each
+.I sig\^
+can be given as a number or as the name of the signal.
+Trap commands are executed in order of signal number.
+Any attempt to set a trap on a signal that
+was ignored on entry to the current shell
+is ineffective.
+If
+.I action\^
+is omitted and the first
+.I sig\^
+is a number, or if
+.I action\^
+is
+.BR \- ,
+then the trap(s) for each
+.I sig\^
+are reset
+to their original values.
+If
+.I action\^
+is the null
+string then this signal is ignored by the shell and by the commands
+it invokes.
+If
+.I sig\^
+is
+.SM
+.B ERR
+then
+.I action\^
+will be executed whenever a command has a non-zero exit status.
+If
+.I sig\^
+is
+.SM
+.B DEBUG
+then
+.I action\^
+will be executed before each command.
+The variable
+.B .sh.command
+will contain the contents of the current command line
+when
+.I action\^
+is running.
+If the exit status of the trap is
+.B 2
+the command will not be executed.
+If the exit status of the trap is
+.B 255
+and inside a function or a dot script,
+the function or dot script will return.
+If
+.I sig\^
+is
+.B 0
+or
+.SM
+.B EXIT
+and the
+.B trap
+statement is executed inside the body of a function defined with the
+.B function
+.I name\^
+syntax,
+then the command
+.I action\^
+is executed
+after the function completes.
+If
+.I sig\^
+is
+.B 0
+or
+.SM
+.B EXIT
+for a
+.B trap
+set outside any function
+then the command
+.I action\^
+is executed
+on exit from the shell.
+If
+.I sig\^
+is
+.SM
+.BR KEYBD ,
+then
+.I action\^
+will be executed whenever a key is read
+while in
+.BR emacs ,
+.BR gmacs ,
+or
+.B vi\^
+mode.
+The
+.B trap
+command
+with no arguments prints a list
+of commands associated with each signal number.
+.PP
+An
+.B exit
+or
+.B return
+without an argument in a trap action will
+preserve the exit status of the command that invoked the trap.
+.TP
+\f3true\fP
+Does nothing, and exits 0. Used with
+.B while
+for infinite loops.
+.TP
+\(dg\(dg \f3typeset\fP \*(OK \f3\(+-ACHSfblmnprtux\^\fP \*(CK \*(OK \f3\(+-EFLRXZi\*(OK\f2n\^\fP\*(CK \*(CK \*(OK \f3\+-M \*(OK \f2mapname\fP \*(CK \*(CK \*(OK \f3\-T \*(OK \f2tname\fP=(\f2assign_list\fP) \*(CK \*(CK \*(OK \f3\-h \f2str\fP \*(CK \*(OK \f3\-a\fP \*(OK\f2type\fP\*(CK \*(CK \*(OK \f2vname\^\fP\*(OK\f3=\fP\f2value\^\fP \*(CK \^ \*(CK .\|.\|.
+Sets attributes and values for shell variables and functions.
+When invoked inside a function defined with the
+.B function
+.I name\^
+syntax,
+a new instance of the variable
+.I vname\^
+is created,
+and the variable's value and type are restored
+when the function completes.
+The following list of attributes may be specified:
+.RS
+.PD 0
+.TP
+.B \-A
+Declares
+.I vname\^
+to be an associative array.
+Subscripts are strings rather than arithmetic
+expressions.
+.TP
+.B \-C
+causes each
+.I vname\^
+to be a compound variable.
+.I value\^
+names a compound variable it is copied into
+.IR vname .
+Otherwise, it unsets each
+.IR vname .
+.TP
+.B \-a
+Declares
+.I vname\^
+to be an indexed array.
+If
+.I type\^
+is specified, it must be the name of an enumeration
+type created with the
+.B enum
+command and it allows enumeration constants to be used
+as subscripts.
+.TP
+.B \-E
+Declares
+.I vname\^
+to be a double precision floating point number.
+If
+.I n\^
+is non-zero, it defines the number of significant figures
+that are used when expanding
+.IR vname .
+Otherwise, ten significant figures will be used.
+.TP
+.B \-F
+Declares
+.I vname\^
+to be a double precision floating point number.
+If
+.I n\^
+is non-zero, it defines the number of places after the
+decimal point that are used when expanding
+.IR vname .
+Otherwise ten places after the decimal point will be used.
+.TP
+.B \-H
+This option provides UNIX to host-name file mapping on non-UNIX
+machines.
+.TP
+.B \-L
+Left justify and remove leading blanks from
+.IR value .
+If
+.I n\^
+is non-zero, it defines the width
+of the field,
+otherwise it is determined by the width of the value of
+first assignment.
+When the variable is assigned to, it is
+filled on the right with blanks or truncated, if necessary, to
+fit into the field.
+The
+.B \-R
+option is turned off.
+.TP
+.B \-M
+Use the character mapping
+.I mapping\^
+defined by
+.IR wctrans (3).
+such as
+.B tolower
+and
+.B toupper
+when assigning a value to each of the specified operands.
+When
+.I mapping\^
+is specified and there are not operands, all variables
+that use this mapping are written to standard output.
+When
+.I mapping\^
+is omitted and there are no operands, all mapped
+variables are written to standard output.
+.TP
+.B \-R
+Right justify and fill with leading blanks.
+If
+.I n\^
+is non-zero, it defines the width
+of the field,
+otherwise it is determined by the width of the value of
+first assignment.
+The field is left filled with blanks or
+truncated from the end if the
+variable is reassigned.
+The
+.B \-L
+option is turned off.
+.TP
+.B \-S
+When used within the
+.I assign_list\^
+of a type definition, it causes the specified sub-variable
+to be shared by all instances of the type.
+When used inside a function defined with the
+.B function
+reserved word, the specified variables will have
+.I "function static\^"
+scope.
+Otherwise, the variable is unset prior to processing the assignment list.
+.TP
+.B \-T
+If followed by \fItname\^\fP, it
+creates a type named by \fItname\^\fP using the compound
+assignment
+.I assign_list\^
+to \f2tname\fP.
+Otherwise, it writes all the type definitions to standard output.
+.TP
+.B \-X
+Declares
+.I vname\^
+to be a double precision floating point number
+and expands using the
+.B %a
+format of ISO-C99.
+If
+.I n\^
+is non-zero, it defines the number of hex digits after
+the radix point that is used when expanding
+.IR vname .
+The default is 10.
+.TP
+.B \-Z
+Right justify and fill with leading zeros if
+the first non-blank character is a digit and the
+.B \-L
+option has not been set.
+Remove leading zeros if the
+.B \-L
+option is also set.
+If
+.I n\^
+is non-zero, it defines the width
+of the field,
+otherwise it is determined by the width of the value of
+first assignment.
+.TP
+.B \-f
+The names refer to function names rather than
+variable names.
+No assignments can be made and the only other
+valid options are
+.BR \-S ,
+.BR \-t ,
+.B \-u
+and
+.BR \-x .
+The \-S
+can be used with discipline functions defined in a type to indicate that
+the function is static. For a static function, the same method will be used by all instances of that type no matter which instance references it. In addition,
+it can only use value of variables from the original type definition. These
+discipline functions cannot be redefined in any type instance.
+The
+.B \-t
+option
+turns on execution tracing for this function.
+The
+.B \-u
+option
+causes this function to be marked undefined.
+The
+.SM
+.B FPATH
+variable will be searched to find the function definition
+when the function is referenced.
+If no options other than
+.B \-f
+is specified, then the function definition will be displayed
+on standard output. If
+.B +f
+is specified, then a line containing the function name followed
+by a shell comment containing the line number and path name of the
+file where this function was defined, if any, is displayed.
+The exit status can be used to determine whether the function is
+defined so that
+.BI "typeset \-f .sh.math." name\^
+will return 0 when math function
+.I name\^
+is defined and non-zero otherwise.
+.TP
+.B \-b
+The variable can hold any number of bytes of data.
+The data can be text or binary.
+The value is represented by the base64 encoding of the data.
+If
+.B \-Z
+is also specified, the size in bytes of the
+data in the buffer will be determined by the size associated with the
+.BR \-Z .
+If the base64 string assigned results in more data, it will be
+truncated. Otherwise, it will be filled with bytes
+whose value is zero.
+The
+.B printf
+format
+.B %B
+can be used to output the actual data in this buffer instead
+of the base64 encoding of the data.
+.TP
+.B \-h
+Used within type definitions to add information when generating
+information about the sub-variable on the man page.
+It is ignored when used outside of a type definition.
+When used with
+.B \-f
+the information is associated with the corresponding discipline
+function.
+.TP
+.B \-i
+Declares
+.I vname\^
+to be represented internally as integer.
+The right hand side of an assignment is evaluated as an
+arithmetic expression when assigning to an integer.
+If
+.I n\^
+is non-zero, it defines the output arithmetic base,
+otherwise the output base will be ten.
+.TP
+.B \-l
+Used with
+.BR \-i ,
+.B \-E
+or
+.BR \-F ,
+to indicate long integer, or long float.
+Otherwise, all upper-case characters are
+converted to lower-case.
+The upper-case option,
+.BR \-u ,
+is turned off.
+Equivalent to
+.B "\-M tolower" .
+.TP
+.B \-m
+moves or renames the variable.
+The value is the name of a variable whose value will be moved to
+.IR vname\^ .
+The original variable will be unset.
+Cannot be used with any other options.
+.TP
+.B \-n
+Declares
+.I vname\^
+to be a reference to the variable whose name is
+defined by the value of variable
+.IR vname .
+This is usually used to reference a variable inside
+a function whose name has been passed as an argument.
+Cannot be used with any other options.
+.TP
+.B \-p
+The name, attributes and values for the given
+.IR vname s
+are written on standard output in a form that can be
+used as shell input.
+If
+.B +p
+is specified, then the values are not displayed.
+.TP
+.B \-r
+The given
+.IR vname s
+are marked
+readonly and these
+names cannot be changed
+by subsequent assignment.
+.TP
+.B \-t
+Tags the variables.
+Tags are user definable and have no special
+meaning to the shell.
+.TP
+.B \-u
+When given along with
+.BR \-i ,
+specifies unsigned integer.
+Otherwise, all lower-case characters are converted
+to upper-case.
+The lower-case option,
+.BR \-l ,
+is turned off.
+Equivalent to
+.B "\-M toupper" .
+.TP
+.B \-x
+The given
+.IR vname s
+are marked for automatic
+export to the
+.I environment\^
+of subsequently-executed commands.
+Variables whose names contain a \fB\s+2.\s-2\fP
+cannot be exported.
+.PD
+.PP
+The
+.B \-i
+attribute cannot be specified along with
+.BR \-R ,
+.BR \-L ,
+.BR \-Z ,
+or
+.BR \-f .
+.PP
+Using
+.B \+
+rather than
+.B \-
+causes these options to be turned off.
+If no
+.I vname\^
+arguments are given,
+a list of
+.I vnames\^
+(and optionally the
+.IR values\^ )
+of the
+.I variables\^
+is printed.
+(Using
+.B \+
+rather than
+.B \-
+keeps the
+values from being printed.)
+The
+.B \-p
+option causes
+.B typeset
+followed by the option letters
+to be printed before each name
+rather than the names of the options.
+If any option other than
+.B \-p
+is given,
+only those variables
+which have all of the given
+options are printed.
+Otherwise, the
+.IR vname s
+and
+.I attributes\^
+of all
+.I variables\^
+that have attributes
+are printed.
+.RE
+.TP
+\f3ulimit\fP \*(OK \f3\-HSacdfmnpstv\fP \*(CK \*(OK \f2limit\^\fP \*(CK
+Set or display a resource limit.
+The available resource limits are listed below.
+Many systems do not support one or more of these limits.
+The limit for a specified resource is set when
+.I limit\^
+is specified.
+The value of
+.I limit\^
+can be a number in the unit specified below with each resource,
+or the value
+.BR unlimited .
+The
+.B \-H
+and
+.B \-S
+options specify whether the hard limit or the
+soft limit for the given resource is set.
+A hard limit cannot be increased once it is set. A soft
+limit can be increased up to the value of the hard limit.
+If neither the
+.B H
+nor
+.B S
+option is specified, the limit applies to both.
+The current resource limit is printed when
+.I limit\^
+is omitted.
+In this case, the soft limit is printed unless
+.B H
+is specified.
+When more than one resource is specified, then the limit
+name and unit is printed before the value.
+.RS
+.PD 0
+.TP
+.B \-a
+Lists all of the current resource limits.
+.TP
+.B \-c
+The number of 512-byte blocks on the size of core dumps.
+.TP
+.B \-d
+The number of K-bytes on the size of the data area.
+.TP
+.B \-f
+The number of 512-byte blocks on files that can be written by the
+current process or by child processes (files of any size may be read).
+.TP
+.B \-m
+The number of K-bytes on the size of physical memory.
+.TP
+.B \-n
+The number of file descriptors plus 1.
+.TP
+.B \-p
+The number of 512-byte blocks for pipe buffering.
+.TP
+.B \-s
+The number of K-bytes on the size of the stack area.
+.TP
+.B \-t
+The number of CPU seconds to be used by each process.
+.TP
+.B \-v
+The number of K-bytes for virtual memory.
+.PD
+.PP
+If no option is given,
+.B \-f
+is assumed.
+.RE
+.TP
+\f3umask\fP \*(OK \f3\-S\fP \*(CK \*(OK \f2mask\^\fP \*(CK
+The user file-creation mask is set to
+.I mask\^
+(see
+.IR umask (2)).
+.I mask
+can either be an octal number or
+a symbolic value as described in
+.IR chmod (1).
+If a symbolic value is given,
+the new
+umask value is the complement of the result of
+applying
+.I mask\^
+to the complement of the previous umask value.
+If
+.I mask\^
+is omitted, the current value of the mask is printed.
+The
+.B \-S
+option causes the mode to be printed as a symbolic
+value. Otherwise, the
+mask is printed in octal.
+.TP
+\(dg \f3unalias\fP \*(OK \f3\-a\fP \*(CK \f2name\^\fP .\|.\|.
+The aliases
+given by the list of
+.IR name s
+are removed from the alias list.
+The
+.B \-a
+option causes all the
+aliases to be unset.
+.TP
+\(dg\f3unset\fP \*(OK \f3\-fnv\fP \*(CK \f2vname\^\fP .\|.\|.
+The variables given by the list of
+.IR vname s
+are unassigned,
+i.e.,
+except for sub-variables within a type,
+their values and attributes are erased.
+For sub-variables of a type, the values are reset to the
+default value from the type definition.
+Readonly variables cannot be unset.
+If the
+.B \-f
+option
+is set, then the names refer to
+.I function\^
+names.
+If the
+.B \-v
+option is set, then the names refer to
+.I variable\^
+names.
+The
+.B \-f
+option overrides
+.BR \-v .
+If
+.B \-n
+is set and
+.I name\^
+is a name reference, then
+.I name\^
+will be unset rather than the variable
+that it references.
+The default is equivalent to
+.BR \-v .
+Unsetting
+.SM
+.BR LINENO ,
+.SM
+.BR MAILCHECK ,
+.SM
+.BR OPTARG ,
+.SM
+.BR OPTIND ,
+.SM
+.BR RANDOM ,
+.SM
+.BR SECONDS ,
+.SM
+.BR TMOUT ,
+and
+.SM
+.B _
+removes their special meaning even if they are
+subsequently assigned to.
+.TP
+\f3wait\fP \*(OK \f2job\^\fP .\|.\|. \*(CK
+Wait for the specified
+.I job
+and
+report its termination status.
+If
+.I job\^
+is not given, then all currently active child processes are waited for.
+The exit status from this command is that of
+the last process waited for if
+.I job\^
+is specified; otherwise it is zero.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+\f3whence\fP \*(OK \f3\-afpv\fP \*(CK \f2name\^\fP .\|.\|.
+For each
+.IR name ,
+indicate how it
+would be interpreted if used as a command name.
+.sp .5
+The
+.B \-v
+option
+produces a more verbose report.
+The
+.B \-f
+option skips the search for functions.
+The
+.B \-p
+option
+does a path search for
+.I name\^
+even if name is an alias, a function, or a reserved word.
+The
+.B \-p
+option turns off the
+.B \-v
+option.
+The
+.B \-a
+option
+is similar to the
+.B \-v
+option but causes
+all interpretations of the given name to be reported.
+.SS Invocation.
+If the shell is invoked by
+.IR exec (2),
+and the first character of argument zero
+.RB ( $0 )
+is
+.BR \- ,
+then the shell is assumed to be a
+.I login
+shell and
+commands are read from
+.B /etc/profile
+and then from either
+.B .profile
+in the current directory or
+.BR \s-1$HOME\s+1/.profile ,
+if either file exists.
+Next, for interactive shells, commands are read from
+the file named by
+performing parameter expansion, command substitution,
+and arithmetic substitution on
+the value of the environment variable
+.SM
+.B ENV
+if the file exists.
+If the
+.B \-s
+option is not present and
+.I arg\^
+and a file by the name of
+.I arg\^
+exists, then it reads and executes this script.
+Otherwise, if the first
+.I arg\^
+does not contain a
+.BR / ,
+a path search is performed on the first
+.I arg\^
+to determine the name of the script to execute.
+The script
+.I arg\^
+must have execute permission and any
+.I setuid
+and
+.I setgid
+settings will be ignored.
+If the script is not found on the path,
+.I arg\^
+is processed as if it named a built-in command or function.
+Commands are then read as described below;
+the following options are interpreted by the shell
+when it is invoked:
+.PP
+.PD 0
+.TP 8
+.B \-D
+Do not execute the script, but output the set of double quoted strings
+preceded by a
+.BR $ .
+These strings are needed for localization of the script to different locales.
+.TP 8
+.B \-E
+Reads the file named by the
+.B ENV
+variable or by
+\s-1$HOME\s+1/\f3.\fPkshrc
+if not defined after the profiles.
+.TP 10
+.BI \-c
+If the
+.B \-c
+option is present, then
+commands are read from the first
+.IR arg .
+Any remaining arguments become
+positional parameters starting at
+.BR 0 .
+.TP
+.B \-s
+If the
+.B \-s
+option is present or if no
+arguments remain,
+then commands are read from the standard input.
+Shell output,
+except for the output of the
+.I Special Commands\^
+listed above,
+is written to
+file descriptor 2.
+.TP
+.B \-i
+If the
+.B \-i
+option is present or
+if the shell input and output are attached to a terminal (as told by
+.IR tcgetattr (2)),
+then this shell is
+.IR interactive .
+In this case \s-1TERM\s+1 is ignored (so that \f3kill 0\fP
+does not kill an interactive shell) and \s-1INTR\s+1 is caught and ignored
+(so that
+.B wait
+is ).
+In all cases, \s-1QUIT\s+1 is ignored by the shell.
+.TP
+.B \-r
+If the
+.B \-r
+option is present, the shell is a restricted shell.
+.TP
+.B \-D
+A list of all double quoted strings that are preceded by a
+.B $
+will be printed on standard output and the shell will exit.
+This set of strings will be subject to language translation
+when the locale is not C or POSIX.
+No commands will be executed.
+.PD
+.TP
+.B \-P
+If
+.B \-P
+or
+.B \-o profile
+is present, the shell is a profile shell (see
+.IR pfexec (1)).
+.TP
+.BI \-R " filename\^"
+The
+.B \-R
+.I filename\^
+option is used
+to generate a cross reference database
+that can be used by a separate utility
+to find definitions and references for variables and commands.
+.PP
+The remaining options and arguments are described under the
+.B set
+command above.
+An optional
+.B \-
+as the first argument is ignored.
+.if \nZ=0 \{.SS Rsh Only.
+.I Rsh\}
+.if \nZ=1 \{.SS Rksh Only.
+.I Rksh\}
+.if \nZ=2 \{.SS Rksh93 Only.
+.I Rksh93\}
+is used to set up login names and execution environments whose
+capabilities are more controlled than those of the standard shell.
+The actions of
+.if \nZ=0 .B rsh\^
+.if \nZ=1 .B rksh\^
+.if \nZ=2 .B rksh93\^
+are identical to those of
+.if \nZ=0 .BR sh\^ ,
+.if \nZ=1 .BR ksh\^ ,
+.if \nZ=2 .BR ksh93\^ ,
+except that the following are disallowed:
+.RS
+.PD 0
+.PP
+Unsetting the restricted option.
+.br
+changing directory (see
+.IR cd (1)),
+.br
+setting or unsetting the value or attributes of
+.SM
+.BR SHELL ,
+.SM
+.BR ENV ,
+.SM
+.BR FPATH ,
+or
+.SM
+.BR PATH\*S,
+.br
+specifying path or
+command names containing
+.BR / ,
+.br
+redirecting output
+.RB ( > ,
+.BR >| ,
+.BR <> ,
+and
+.BR >> ).
+.br
+adding or deleting built-in commands.
+.br
+using
+.B "command -p"
+to invoke a command.
+.PD
+.RE
+.PP
+The restrictions above are enforced
+after \f3.profile\fP and the
+.SM
+.B ENV
+files are interpreted.
+.PP
+When a command to be executed is found to be a shell procedure,
+.if \nZ=0 \{.B rsh\^
+invokes
+.I sh\^\}
+.if \nZ=1 \{.B rksh\^
+invokes
+.I ksh\^\}
+.if \nZ=2 \{.B rksh93\^
+invokes
+.I ksh93\^\}
+to execute it.
+Thus, it is possible to provide to the end-user shell procedures
+that have access to the full power of
+the standard shell,
+while imposing a limited menu of commands;
+this scheme assumes that the end-user does not have write and
+execute permissions in the same directory.
+.PP
+The net effect of these rules is that the writer of the
+.B .profile
+has complete control over user actions,
+by performing guaranteed setup actions
+and leaving the user in an appropriate directory
+(probably
+.I not\^
+the login directory).
+.PP
+The system administrator often sets up a directory
+of commands
+(e.g.,
+.BR /usr/rbin )
+that can be safely invoked by
+.if \nZ=0 .BR rsh .
+.if \nZ=1 .BR rksh .
+.if \nZ=2 .BR rksh93 .
+.SH EXIT STATUS
+Errors detected by the shell, such as syntax errors,
+cause the shell
+to return a non-zero exit status.
+If the shell is being used non-interactively,
+then execution of the shell file is abandoned
+unless the error occurs inside a subshell in which case
+the subshell is abandoned.
+Otherwise, the shell returns the exit status of
+the last command executed (see also the
+.B exit
+command above).
+Run time errors detected by the shell are reported by
+printing the command or function name and the error condition.
+If the line number that the error occurred on is greater than one,
+then the line number is also printed in square brackets
+.RB ( "[]" )
+after the command or function name.
+.SH FILES
+.TP
+.B /etc/profile
+The system wide initialization file, executed for login shells.
+.if \nZ=2 \{.br
+.TP
+.B /etc/ksh.kshrc
+The system wide startup file, executed for interactive shells.
+\}
+.TP
+.B \s-1$HOME\s+1/\f3.\fPprofile
+The personal initialization file, executed for login shells after /etc/profile.
+.TP
+\s-1$HOME\s+1/\f3.\fP.kshrc
+Default personal initialization file, executed for interactive shells when
+.SM
+.B ENV
+is not set.
+.TP
+.B /etc/suid_profile
+Alternative initialization file, executed instead of the personal initialization
+file when the real and effective user or group id do not match.
+.TP
+.B /dev/null
+NULL device
+.SH SEE ALSO
+cat(1),
+cd(1),
+chmod(1),
+cut(1),
+egrep(1),
+echo(1),
+emacs(1),
+env(1),
+fgrep(1),
+gmacs(1),
+grep(1),
+newgrp(1),
+pfexec(1),
+stty(1),
+test(1),
+umask(1),
+vi(1),
+dup(2),
+exec(2),
+fork(2),
+getpwnam(3),
+ioctl(2),
+lseek(2),
+paste(1),
+pathconf(2),
+pipe(2),
+sysconf(2),
+umask(2),
+ulimit(2),
+wait(2),
+wctrans(3),
+rand(3),
+a.out(5),
+profile(5),
+environ(7).
+.PP
+Morris I. Bolsky and David G. Korn,
+.IR "The New KornShell Command and Programming Language" ,
+Prentice Hall, 1995.
+.PP
+.I "POSIX \- Part 2: Shell and Utilities,"
+IEEE Std 1003.2-1992, ISO/IEC 9945-2, IEEE, 1993.
+.SH CAVEATS
+.PP
+If a command
+is executed, and then a command with the same name is
+installed in a directory in the search path before the directory where the
+original command was found, the shell will continue to
+.I exec\^
+the original command.
+Use the
+.B \-t
+option of the
+.B alias\^
+command to correct this situation.
+.PP
+Some very old shell scripts contain a
+.B ^
+as a synonym for the pipe character
+.BR \(bv .
+.PP
+Using the
+.B hist\^
+built-in command within a compound command will cause the whole
+command to disappear from the history file.
+.PP
+The built-in command \f3\|.\fP \f2file\^\fP
+reads the whole file before any commands are executed.
+Therefore,
+.B alias
+and
+.B unalias
+commands in the file
+will not apply to any commands defined in the file.
+.PP
+Traps are not processed while a job is waiting for a foreground process.
+Thus, a trap on
+.B CHLD
+won't be executed until the foreground job terminates.
+.PP
+It is a good idea to leave a space after the comma operator in
+arithmetic expressions to prevent the comma from being interpreted
+as the decimal point character in certain locales.
diff --git a/src/cmd/ksh93/sh.memo b/src/cmd/ksh93/sh.memo
new file mode 100644
index 0000000..9f321e6
--- /dev/null
+++ b/src/cmd/ksh93/sh.memo
@@ -0,0 +1,3248 @@
+. \" use troff -mm
+.nr C 3
+.nr N 2
+.SA 1 \" right justified
+.ND "December 21, 1993"
+.TL "311466-6713" "61175" \" charging case filing case
+Introduction to \f5ksh-93\fP
+.AU "David G. Korn" DGK MH 11267 7975 3C-526B "(research!dgk)"
+.TM 11267-931221-26 \" technical memo + TM numbers
+.MT 1 \" memo type
+.OK Shell "Command interpreter" Language UNIX \" keyword
+.AS 2 \" abstract start for TM
+\f5ksh-93\fP is a
+major rewrite of \f5ksh\fP,
+a program that serves as a command language
+(shell) for the UNIX*
+.FS *
+UNIX is a registered trademark of Novell.
+.FE
+operating system.
+As with \f5ksh\fP, \f5ksh-93\fP
+is essentially compatible with the System V version of the Bourne shell\*(Rf,
+.RS
+S. R. Bourne,
+.I "An Introduction to the UNIX
+Shell,"
+BSTJ - Vol. 57, No. 6 part 2, pages 1947-1972, 1978.
+.RF
+and compatible with previous versions of \f5ksh\fP.
+\f5ksh-93\fP is intended to comply with the IEEE POSIX 1003.2
+and ISO 9945-2\*(Rf
+.RS
+.I "POSIX \- Part 2: Shell and Utilities,"
+IEEE Std 1003.2-1992, ISO/IEC 9945-2, IEEE, 1993.
+.RF
+shell standard.
+In addition to changes in the language required
+by these standards, the primary focus of \f5ksh-93\fP
+is related to shell programming.
+\f5ksh-93\fP provides the programming power of several
+other interpretive languages such as \f5awk\fP\*(Rf,
+.RS
+Al Aho,
+Brian Kernighan,
+and
+Peter Weinberger,
+.I "The AWK Programming Language,"
+Addison Wesley, 1988.
+.RF
+\f5FIT\fP\*(Rf,
+.RS
+Lloyd H. Nakatani and Laurence W. Ruedisueli,
+.I "The FIT Programming Language Primer",
+TM 1126-920301-03, 1992.
+.RF
+\f5PERL\fP\*(Rf,
+.RS
+Larry Wall and Randal Schwartz,
+.I "Programming perl,"
+O'Reilly & Assoc, 1990.
+.RF
+and
+\f5tcl\fP\*(Rf.
+.RS
+John K. Ousterhout,
+.I "Tcl: An Embeddable Command Language",
+Proceedings of the Washington USENIX meeting, pp. 133-146, 1990.
+.RF
+.P
+This memo
+assumes that the reader is already familiar with the Bourne shell.
+It introduces most of the features of \f5ksh-93\fP
+relative to the Bourne shell; both
+as a command language and as a programming language.
+The Appendix contains
+a sample script written in \f5ksh-93\fP.
+.AE \" abstract end
+.H 1 "INTRODUCTION"
+.P
+The term "shell" is used to describe a program that provides
+a command language
+interface.
+Because the UNIX*\
+.FS *
+UNIX is a registered trademark of USL
+.FE
+system shell is a user level program, and not part of
+the operating system itself,
+anyone can write a new shell or modify an existing one.
+This has caused an evolutionary progress
+in the design and implementation of shells,
+with the better ones surviving.
+The most widely available UNIX system shells are the Bourne shell\*(Rf,
+.RS
+S. R. Bourne,
+.IR "An Introduction to the UNIX Shell" ,
+Bell System Technical Journal,
+Vol. 57, No. 6, Part 2, pp. 1947-1972, July 1978.
+.RF
+written by Steve Bourne
+at AT&T Bell Laboratories,
+the C shell\*(Rf,
+.RS
+W. Joy,
+.IR "An Introduction to the C Shell" ,
+Unix Programmer's Manual, Berkeley Software Distribution,
+University of California, Berkeley, 1980.
+.RF
+written by Bill Joy at the University of California, Berkeley,
+and the KornShell language \*(Rf,
+.RS
+Morris Bolsky and David Korn,
+.IR "The KornShell Command and Programming Language" ,
+Prentice Hall, 1989.
+.RF
+written by David Korn
+at AT&T Bell Laboratories.
+The Bourne shell is available on almost all versions of the UNIX
+system.
+The C Shell is available with all Berkeley Software Distribution (BSD) UNIX systems and on many other systems.
+The KornShell
+is available on System V Release 4 systems.
+In addition, it is available on many other systems.
+The source for the KornShell language is available from the AT&T Toolchest,
+an electronic software distribution system.
+It runs on all known versions of the UNIX system and
+on many UNIX system look-alikes.
+.P
+There have been several articles comparing the UNIX system shells.
+Jason Levitt\*(Rf
+.RS
+Jason Levitt,
+.IR "The Korn Shell: An Emerging Standard" ,
+UNIX/World, pp. 74-81, September 1986.
+.RF
+highlights some of the new features
+introduced by the KornShell language.
+Rich Bilancia\*(Rf
+.RS
+Rich Bilancia,
+.IR "Proficiency and Power are Yours With the Korn Shell" ,
+UNIX/World, pp. 103-107, September 1987.
+.RF
+explains some of the advantages of using the KornShell language.
+John Sebes\*(Rf
+.RS
+John Sebes,
+.I "Comparing UNIX Shells,"
+UNIX Papers,
+Edited by the Waite Group, Howard W. Sams & Co., 1987.
+.RF
+provides a more detailed comparison of the three shells,
+both as a command language and as a programming language.
+.P
+The KornShell language is a superset of the
+Bourne shell. The KornShell language has many of the popular C shell features,
+plus additional features of its own.
+Its initial popularity stems primarily from its improvements as
+a command language.
+The primary interactive benefit of the KornShell command language
+is a visual command line editor that allows you to
+make corrections to your current command line
+or to earlier command lines,
+without having to retype them.
+.P
+However,
+in the long run,
+the power of the KornShell language as a high-level programming language,
+as described by Dolotta and Mashey\*(Rf,
+.RS
+T. A. Dolotta and J. R. Mashey,
+.I "Using the shell as a Primary Programming Tool,"
+Proc. 2nd. Int. Conf. on Software Engineering, 1976,
+pages 169-176.
+.RF
+may prove to be of greater significance.
+\f5ksh-93\fP provides the programming power of several
+other interpretive languages such as \f5awk\fP,
+\f5FIT\fP,
+\f5PERL\fP,
+and
+\f5tcl\fP.
+An application that was originally written in the C programming language
+was rewritten in the KornShell language.
+More than 20,000 lines of C code were replaced with KornShell scripts
+totaling fewer than 700 lines.
+In most instances there was no perceptible difference in performance
+between the two versions of the code.
+.P
+The KornShell language has been embedded into windowing systems
+allowing graphical user interfaces to be developed in shell
+rather than having to build applications that need to be
+compiled.
+The \f5wksh\fP program\*(Rf
+.RS
+J. S. Pendergrast,
+.IR "WKSH - Korn Shell with X-Windows Support",
+USL. 1991.
+.RF
+provides a method of developing OpenLook or Motif
+applications as \f5ksh\fP scripts.
+.P
+This memo is an introduction to \f5ksh-93\fP,
+the program that implements an enhanced version
+of the KornShell language.
+It is referred to as \f5ksh\fP in the rest of this memo.
+The memo describes the KornShell language based on the
+features of the 12/28/93 release of \f5ksh\fP.
+This memo is not a tutorial, only an introduction.
+The second edition of reference [9] gives
+a more complete treatment of the KornShell language.
+.P
+A concerted effort has been made to achieve both System V Bourne shell
+compatibility and IEEE POSIX compatibility
+so that scripts written for either of these shells
+can run without modification with \f5ksh\fP.
+In addition, \f5ksh-93\fP attempts to
+be compatible with older versions of \f5ksh\fP.
+When there are conflicts between versions of the shell,
+\f5ksh-93\fP selects the behavior dictated by the IEEE POSIX
+standard.
+The description of features in this memo assumes
+that the reader is already familiar with the Bourne shell.
+.H 1 "COMMAND LANGUAGE"
+There is no separate command language.
+All features of the language, except job control,
+can be
+used both within a script and interactively from a terminal.
+However, features that are more likely to be used
+while running commands interactively from a terminal
+are presented here.
+.H 2 "Setting Options"
+By convention, UNIX commands
+consist of a command name followed by options and other arguments.
+Options are either of the form \f5-\fP\fIletter\fP,
+or \f5-\fP\fIletter value\fP.
+In the former case, several options may be grouped after a single \f5-\fP.
+The argument \f5--\fP signifies an end to the option list and is
+only required when the first non-option argument begins with
+a \f5-\fP.
+Most commands print an error message which
+shows which options are permitted
+when given incorrect arguments.
+In addition, the option sequence \f5-?\fP causes most commands
+to print a usage message which lists the valid options.
+.P
+Ordinarily, \f5ksh\fP executes a command by
+using the command name to locate a program to run
+and by running the program as a separate process.
+Some commands, referred to as
+.IR built-ins ,
+are carried out by \f5ksh\fP itself,
+without creating a separate process.
+The reasons that some commands are built-in are presented later.
+In nearly all cases the distinction
+between a command that is built-in and one that
+is not is invisible to the user.
+However, nearly
+all commands that are built-in follow command line conventions.
+.P
+\f5ksh\fP has several options that can be set by the user
+as command line arguments at invocation and as option arguments to the
+\f5set\fP command.
+Most other options can be set with a single letter option or as a name
+that follows the \f5-o\fP option.
+Use
+\f5set\ -o\fP
+to display the current option settings.
+Some of these options, such as
+.B interactive
+and
+.B monitor
+(see
+.I "Job Control"
+below),
+are enabled automatically by \f5ksh\fP
+when the shell is connected to a terminal device.
+Other options, such as
+.B noclobber
+and
+.BR ignoreeof ,
+are normally placed in a startup file.
+The
+.B noclobber
+option causes
+\f5ksh\fP
+to print an error message when you use
+.B >
+to redirect output to a file that already exists.
+If you want to redirect to an existing file, then
+you have to use
+.B >|
+to override
+the
+.B noclobber
+option.
+The
+.B ignoreeof
+option
+is used to prevent the
+.I end-of-file
+character, normally
+.B ^D
+(Control- d),
+from exiting the shell and possibly logging you out.
+You must type \f5exit\fP
+to log out.
+Most of the options are described in this memo as appropriate.
+.H 2 "Command Aliases"
+.P
+Command aliases provide a mechanism of associating a command name and
+arguments with a shorter name.
+Aliases are defined with the \f5alias\fP
+built-in.
+The form of an \f5alias\fP
+command definition is:
+.ce
+\f5alias\fP \fIname\fP\f5=\fP\fIvalue\fP
+As with most other shell assignments, no space is allowed before or after
+the \f5=\fP.
+The characters of an alias name cannot be characters that are
+special to the shell.
+The replacement string,
+.I value,
+can contain any valid shell script,
+including meta-characters such as pipe symbols and i/o-redirection
+provided that they are quoted.
+Unlike
+\f5csh\fP,
+aliases in
+\f5ksh\fP
+cannot take arguments.
+The equivalent functionality of aliases with arguments can
+be achieved with shell functions, described later.
+.P
+As a command is being read,
+the command name is checked against a list of
+.I alias
+names.
+If it is found,
+the name is replaced by the alias value associated with the
+.I alias
+and then rescanned.
+When rescanning the value for an alias, alias substitutions
+are performed except for an alias that is currently being processed.
+This prevents infinite loops in alias substitutions.
+For example with the aliases, \f5alias\ l=ls\ 'ls=ls\ -C'\fP,
+the command name \f5l\fP becomes \f5ls\fP, which becomes \f5ls\ -C\fP.
+Ordinarily, only the command name word is processed for alias substitution.
+However, if the value of an alias ends in a space,
+then the word following the alias is also checked for alias substitution.
+This makes it possible
+to define an alias whose first argument is the name of a command
+and have alias substitution performed on this argument,
+for example
+\f5nohup='nohup\ '\fP.
+.P
+Aliases can be used to redefine built-in commands so that
+the alias,
+.ce
+\f5alias test=./test\fP
+can be used to look for \f5test\fP
+in your current working directory rather than
+using the built-in \f5test\fP command.
+Reserved words such as
+\f5for\fP and \f5while\fP
+cannot be changed by aliasing.
+The command \f5alias\fP,
+without arguments, generates
+a list of aliases and corresponding alias values.
+The \f5unalias\fP command removes the name and text of an alias.
+.P
+Aliases are used to save typing and to improve readability of scripts.
+Several aliases are predefined by \f5ksh\fP.
+For example, the predefined alias
+.ce
+\f5alias integer='typeset -i'\fP
+allows the integer variables \f5i\fP and \f5j\fP
+to be declared and initialized with the command
+.ce
+\f5integer i=0 j=1\fP
+.P
+While aliases can be defined in scripts,
+it is not recommended.
+The location of an alias command can be important
+since aliases are only processed when a command is read.
+A \fB\s+2.\s-2\fP
+procedure (the shell equivalent of an include file)
+is read all at once (unlike
+start up files
+which are read a command at
+a time) so that any aliases defined there will not effect any commands
+within this script.
+Predefined aliases do not have this problem.
+.H 2 "Command Re-entry"
+.P
+When run interactively,
+\f5ksh\fP saves the
+commands you type at a terminal in a file.
+If the variable
+\fB\s-1HISTFILE\s+1\fP
+is set to the name of a file to which the user
+has write access,
+then the commands are stored in this
+.I history
+file.
+Otherwise the file
+\fB$\s-1HOME\s+1/.sh_history\fP
+is checked for write access and if this fails
+an unnamed file is used to hold the history lines.
+Commands are always appended to this file.
+Instances of \f5ksh\fP
+that run concurrently and use the same history file
+name, share access to the history file so that a command
+entered in one shell will be available for editing in another
+shell.
+The file may be truncated when \f5ksh\fP
+determines that no other shell is using the history file.
+The number of commands accessible to the user is determined by the value of the
+\fB\s-1HISTSIZE\s+1\fP
+variable at the time the shell is invoked.
+The default value is 256.
+Each command may consist of one or more lines since a compound
+command is considered one command.
+If the character
+.B !
+is placed within the
+.I "primary prompt"
+string,
+\fB\s-1PS1\s+1\fP,
+then it is replaced by the command number each time the prompt is given.
+.P
+A built-in command named \f5hist\fP
+is used to list and/or edit
+any of these saved commands.
+The option
+.B \-l
+is used to specify listing of previous commands.
+The command can always be specified with
+a range of one or more commands.
+The range can be specified by giving the command
+number, relative or absolute, or by giving
+the first character or characters of the command.
+When given without specifying the range,
+the last 16
+commands are listed, each
+preceded by the command number.
+.P
+If the listing option is not selected,
+then the range of commands specified,
+or the last command if no range is given,
+is passed to an editor program before
+being re-executed by \f5ksh\fP.
+The editor to be used may be specified
+with the option
+.B \-e
+and following it with the editor name.
+If this option is not specified, the
+value of the shell variable
+\fB\s-1HISTEDIT\s+1\fP
+is used as the name of the editor,
+providing that this variable has a non-null value.
+If this variable is not set, or is null,
+and the
+.B \-e
+option has not been selected,
+then
+\f5/bin/ed\fP
+is used.
+When editing has been complete,
+the edited text automatically becomes
+the input for \f5ksh\fP.
+As this text is read by \f5ksh\fP, it is echoed onto the terminal.
+.P
+The
+.B \-s
+option causes the editing to be bypassed
+and just re-executes the command.
+In this case only a single command can be specified as the range
+and an optional argument of the form
+\fIold\fP\fB=\fP\fInew\fP
+may be added which requests a simple string substitution
+prior to evaluation.
+A convenient alias,
+.ce
+\f5alias r='hist -s'\fP
+has been pre-defined so that
+the single key-stroke
+\f5r\fP
+can be used to re-execute the previous command
+and the key-stroke sequence,
+\f5r\ abc=def\ c\fP
+can be used to re-execute the last command that starts with
+the letter \f5c\fP
+with the first occurrence of the string \f5abc\fP
+replaced with the string \f5def\fP.
+Typing
+\f5r\ c\ >\ file\fP
+re-executes the most recent command starting with the letter \f5c\fP,
+with standard output redirected to
+.IR file .
+.H 2 "In-line editing"
+.P
+Lines typed from a terminal frequently need changes made
+before entering them.
+With the Bourne shell the only method to fix up commands
+is by backspacing or killing the whole line.
+\f5ksh\fP offers options that allow the user to edit parts of the
+current command line before submitting the command.
+The in-line edit options make the command line into a single
+line screen edit window.
+When the command is longer than the width of the terminal,
+only a portion of the command is visible.
+Moving within the line automatically makes that portion visible.
+Editing can be performed on this window until the
+.I return
+key is pressed.
+The editing modes have editing directives that access the history file
+in which previous commands are saved.
+A user can copy any of the most recent
+\fB\s-1HISTSIZE\s+1\fP
+commands from this file into the input edit window.
+You can locate commands by searching or by position.
+.P
+The in-line editing options do not use the
+.I termcap
+or
+.I terminfo
+databases.
+They work on most standard terminals.
+They only require that the backspace character moves the cursor left
+and the space character overwrites the current character on the screen
+and moves the cursor to the right.
+Very few terminals or terminal emulators do not have
+this behavior.
+.P
+There is a choice of editor options.
+The
+.BR emacs ,
+.BR gmacs ,
+or
+.B vi
+option is selected by turning on the
+corresponding
+option of the \f5set\fP
+command.
+If the value of the
+\fB\s-1EDITOR\s+1\fP
+or
+\fB\s-1VISUAL\s+1\fP
+variables ends with any of these suffixes
+the corresponding option is turned on.
+A large subset of each of these editors'
+features is available within the shell. Additional
+functions, such as file name completion, have also been added.
+.P
+In the
+.B emacs
+or
+.B gmacs
+mode the user positions the cursor to the point
+needing correction and inserts, deletes, or replaces
+characters as needed.
+The only difference between these two modes is the
+meaning of the directive
+.BR ^T .
+Control keys and escape sequences are used for cursor
+positioning and control functions.
+The available editing functions are listed in the manual page.
+.P
+The
+.B vi
+editing mode
+starts in insert mode and enters control mode when the
+user types ESC ( 033 ).
+The
+.I return
+key, which submits the current command for processing,
+can be entered from either mode.
+The cursor can be anywhere on the line.
+A subset of commonly used
+.I vi
+editing directives are available.
+The
+.B k
+and
+.B j
+directives that normally move up and down by one
+.IR line ,
+move up and down one
+.I command
+in the history file,
+copying the command into the input edit window.
+For reasons of efficiency,
+the terminal is kept in canonical mode until an
+ESC
+is typed.
+On some terminals,
+and on earlier versions of the UNIX operating system,
+this doesn't work correctly.
+The
+.B viraw
+option,
+which always uses
+.I raw
+or
+.I cbreak
+mode,
+must be used in this case.
+.P
+Most of the code for the editing options does not rely on the
+\f5ksh\fP code and can be used in a stand-alone mode with most any command
+to add in-line edit capability.
+However,
+all versions of the in-line editors have some features that
+use some shell specific code. For example,
+with all edit modes, the
+ESC-=
+directive applied to command words
+(the first word on the line,
+or the first word after a
+.BR ; ,
+.BR | ,
+.BR ( ,
+or
+.BR & )
+lists all aliases, functions, or commands
+that match the portion of the given current word.
+When applied to other words, this directive
+prints the names of files that match the current
+word.
+The ESC\fB-*\fP directive
+adds the expanded list of matching files to the command line.
+A trailing
+.B *
+is added to the word if it doesn't contain any file pattern matching
+characters before the expansion.
+In
+.B emacs
+and
+.B gmacs
+mode,
+ESC-ESC
+indicates command completion when applied to
+command names, otherwise it indicates pathname completion.
+With command or pathname completion,
+the list generated by the
+ESC-= directive is examined to find
+the longest common prefix.
+With command completion, only the last component of
+the pathname is used to compute the longest command prefix.
+If the longest common prefix is a complete match,
+then the word is replaced by the pathname, and a
+.B /
+is appended if
+pathname is a directory, otherwise a space is added.
+In
+.B vi
+mode,
+.B \e
+from control mode gives the same behavior.
+.H 2 "Key Binding"
+.P
+It is possible to intercept keys as they are entered and
+apply new meanings or bindings.
+A trap named
+\fB\s-1KEYBD\s+1\fP
+is evaluated each time
+\f5ksh\fP processes characters entered
+from the keyboard,
+other than those typed
+while entering a search string or an argument to an
+edit directive such as
+.B r
+in vi-mode.
+The action associated with this trap can change the value of
+the entered key to cause the key to perform a different
+operation.
+.P
+When the
+\fB\s-1KEYBD\s+1\fP
+trap is entered,
+the \fB.sh.edtext\fP
+variable contains the contents of the current input line
+and the \fB.sh.edcol\fP
+variable gives the current cursor position within this line.
+The \fB.sh.edmode\fP
+variable contains the
+.B ESC
+character when the trap is entered from
+.B vi
+insert mode.
+Otherwise, this value is null.
+The \fB.sh.edchar\fP
+variable contains the character or
+escape sequence that caused the trap.
+A key sequence is either a single character,
+.B ESC
+followed by a single character,
+or
+.B ESC[
+followed by a single character.
+In the \fBvi\fP edit mode,
+the characters after the
+.B ESC
+must be entered within half a second after the
+.BR ESC .
+The value of \fB.sh.edchar\fP
+at the end of the trap will be used as
+the input sequence.
+.P
+Using the associative array facility of \f5ksh\fP described later,
+and the function facility of \f5ksh\fP, it is easy to write
+a single trap so that keys can be bound dynamically. For example,
+.sp
+.nf
+.in .5i
+.ta 4i
+\f5typeset -A Keytable
+trap 'eval "${Keytable[${.sh.edchar}]}"' KEYBD
+function keybind # key action
+{
+ typeset key=$(print -f "%q" "$2")
+ case $# in
+ 2) Keytable[$1]='.sh.edchar=${.sh.edmode}'"$key"
+ ;;
+ 1) unset Keytable[$1]
+ ;;
+ *) print -u2 "Usage: $0 key [action]"
+ ;;
+ esac
+}\fP
+.ta
+.in
+.fi
+.sp
+.H 2 "Job Control"
+.P
+The job control mechanism
+is almost identical to the version introduced in \f5csh\fP
+of the Berkeley UNIX operating system,
+version 4.1 and later.
+The job control feature allows the user to stop and
+restart programs, and to move programs to and from the
+foreground and the background.
+It will only work on systems that provide support for
+these features.
+However,
+even systems without job control have a
+.B monitor
+option which, when enabled, will report the progress
+of background jobs and enable the user to \f5kill\fP
+jobs by job number or job name.
+.P
+An interactive shell associates a
+.I job
+with each pipeline typed in from the terminal
+and assigns it a small integer number
+called the job number.
+If the job is run asynchronously,
+the job number is printed at the terminal.
+At any given time, only one job owns the terminal,
+i.e., keyboard signals are only sent to the processes in one job.
+When \f5ksh\fP creates a foreground job,
+it gives it ownership of the terminal.
+If you are running a job and wish to stop
+it you hit the key
+.B ^Z
+(control-\fBZ\fP)
+which sends a
+\fB\s-1STOP\s+1\fP
+signal to all processes in the current job.
+The shell receives notification that the processes
+have stopped and takes back control of the terminal.
+.P
+There are commands to continue programs in the foreground
+and background.
+There are several ways to refer to jobs.
+The character
+.B %
+introduces a job name.
+You can refer to jobs by name or number as described in the manual page.
+The built-in command \f5bg\fP
+allows you to continue a job in the background,
+while the built-in command \f5fg\fP
+allows you to continue a job in the foreground even
+though you may have started it in the background.
+.P
+A job being run in the background will stop if it tries
+to read from the terminal.
+It is also possible to stop background jobs that try to write on
+the terminal by setting the terminal options
+appropriately.
+.P
+There is a built-in command \f5jobs\fP
+that lists the status of all running and stopped jobs.
+In addition,
+you are informed of the change of state (running or stopped)
+of any background
+jobs just before each prompt.
+If you want to be notified about background job completions
+as soon as they occur without waiting for a prompt, then use the
+.B notify
+option.
+When you try to exit the shell while jobs are stopped or running,
+you will receive a message from \f5ksh\fP.
+If you ignore this message and try to exit again,
+all stopped processes will be terminated.
+In addition, for login shells, the
+\fB\s-1HUP\s+1\fP
+signal will be sent to
+all background jobs
+unless the job has been disowned with the
+.B disown
+command.
+.P
+A built-in version of \f5kill\fP
+makes it possible to use
+.I job
+numbers as targets for signals.
+Signals can be selected by number or name.
+The name of the signal is the name found in the
+.I include
+file
+.B /usr/include/sys/signal.h
+with the prefix
+.B \s-1SIG\s+1
+removed.
+The
+.B \-l
+option of \f5kill\fP
+provides a means to map individual signal names to and from
+signal number.
+In addition, if no signal name or number is given,
+\f5kill\ -l\fP
+generates a list of valid signal names.
+.H 2 "Changing Directories"
+By default,
+\f5ksh\fP
+maintains a logical view of the file system hierarchy
+which makes symbolic links transparent.
+For systems that have symbolic links,
+this means that if \f5/bin\fP is a symbolic link to \f5/usr/bin\fP
+and you change directory to \f5/bin\fP, \f5pwd\fP will indicate
+that you are in \f5/bin\fP, not \f5/usr/bin\fP.
+\f5pwd\ -P\fP
+generates the physical pathname of the present working
+directory by resolving all the symbolic links.
+By default,
+the \f5cd\fP
+command will take you where you expect to go even if you cross
+symbolic links.
+A subsequent \f5cd\ ..\fP in the example above
+will place you in \f5/\fP, not \f5/usr\fP.
+On systems with symbolic links,
+\f5cd\ -P\fP
+causes
+.B ..
+to be treated physically.
+.P
+\f5ksh\fP remembers your last directory
+in the variable
+\fB\s-1OLDPWD\s+1\fP.
+The \f5cd\fP
+built-in can be given with argument
+.B \-
+to return to the previous directory
+and print the name of the directory.
+Note that \f5cd\ -\fP
+done twice returns you to the starting directory,
+not the second previous directory.
+A directory
+.I stack
+manager has been written as shell
+.I functions
+to
+.I push
+and
+.I pop
+directories from the stack.
+.H 2 "Prompts"
+.P
+When \f5ksh\fP
+reads commands from a terminal,
+it issues a prompt whenever it is ready
+to accept more input and then
+waits for the user to respond.
+The
+\fB\s-1TMOUT\s+1\fP
+variable
+can be set to be the number of seconds that the shell will wait for
+input before terminating.
+A 60 second warning message is printed
+before terminating.
+.P
+The shell uses two prompts.
+The primary prompt,
+defined by the value of the
+\fB\s-1PS1\s+1\fP
+variable,
+is issued at the start of each command.
+The secondary prompt,
+defined by the value of the
+\fB\s-1PS2\s+1\fP
+variable,
+is issued when more input is needed to complete a command.
+.P
+\f5ksh\fP allows the user to specify a list of files or directories
+to check before issuing the
+\fB\s-1PS1\s+1\fP
+prompt.
+The variable
+\fB\s-1MAILPATH\s+1\fP
+is a colon (
+.B :
+) separated list of file names to be checked for changes
+periodically. The user is notified
+before the next prompt.
+Each of the names in this list can be followed by a
+.B ?
+and a message to be given when a change has been detected in the file.
+The prompt will be evaluated for parameter expansion, command
+substitution and arithmetic expansion which are described later.
+The parameter
+.B $_
+within a mail message will evaluate to the name of the file that
+has changed.
+The parameter
+\fB\s-1MAILCHECK\s+1\fP
+is used to specify the minimal interval in seconds before
+new mail is checked for.
+.P
+In addition to replacing each
+.B !
+in the prompt with the command number,
+\f5ksh\fP expands
+the value of the
+.B \s-1PS1\s+1
+variable
+for parameter expansions, arithmetic expansions,
+and command substitutions as described below
+to generate the prompt.
+The expansion characters that are to be applied when
+the prompt is issued must be quoted to prevent the
+expansions from occurring when assigning the value to
+.B \s-1PS1\s+1.
+For example,
+\f3\s-1PS1\s+1="$\s-1PWD\s+1"\fP
+causes
+.B \s-1PS1\s+1
+to be set to the value of
+.B \s-1PWD\s+1
+at the time of the assignment whereas
+.B \s-1PS1\s+1='$\s-1PWD\s+1'
+causes
+.B \s-1PWD\s+1
+to be expanded at the time the prompt is issued.
+.P
+Command substitution may require a separate process
+to execute and cause the prompt display to be somewhat
+slow, especially
+when the return key is pressed several times in a row.
+Therefore, its use
+within
+.B \s-1PS1\s+1
+is discouraged.
+Some variables are maintained by \f5ksh\fP
+so that their values can be used with
+.B \s-1PS1\s+1.
+The
+.B \s-1PWD\s+1
+variable stores the pathname of the current working directory.
+The value of
+.B \s-1SECONDS\s+1
+variable
+is the value of the most
+recent assignment plus the elapsed time.
+By default, the time is measured in milli-seconds,
+but since
+.B \s-1SECONDS\s+1
+is a floating point variable, the
+number of places after the decimal point in the expanded
+value can be
+specified with
+\f5typeset\ -F\fP\fIplaces\fP\f5\ SECONDS\fP.
+In a roundabout way, this variable
+can be used to generate a time stamp into the
+.B \s-1PS1\s+1
+prompt without creating a process at each prompt.
+The following code explains how you can do this on
+System V. On BSD, you need a different command to initialize
+the
+.B \s-1SECONDS\s+1
+variable.
+\f5
+.sp
+.nf
+.in .5i
+# . this script and use $TIME as part of your PS1 string to
+# get the time of day in your prompt
+typeset -RZ2 _x1 _x2 _x3
+(( SECONDS=$(date '+3600*%H+60*%M+%S') ))
+_s='_x1=(SECONDS/3600)%24,_x2=(SECONDS/60)%60,_x3=SECONDS%60,0'
+TIME='"${_d[_s]}$_x1:$_x2:$_x3"'
+# PS1=${TIME}whatever
+.fi
+.ta
+.in
+.sp
+\fP
+.H 2 "Tilde substitution"
+.P
+The character
+.B \(ap
+at the beginning of a word has special meaning to \f5ksh\fP.
+If the characters after the
+.B \(ap
+up to a
+.B /
+match a user login name in the password database, then the
+.B \(ap
+and the name are replaced by
+that user's login directory.
+If no match is found, the original word
+is unchanged.
+A
+.B \(ap
+by itself, or in front of a
+.BR / ,
+is replaced by the value of the
+\fB\s-1HOME\s+1\fP
+parameter.
+A
+.B \(ap
+followed by a
+.B +
+or
+.B \-
+is replaced by the value of
+.B $\s-1PWD\s+1
+or
+.B $\s-1OLDPWD\s+1
+respectively.
+.H 2 "Output formats"
+The output of built-in commands and traces have values quoted so that they
+can be re-input to the shell.
+This makes it easy to cut and paste shell output on systems
+which use a pointing device such as a mouse.
+In addition, output can be saved in a file for reuse.
+.P
+.H 2 "The \fB\s-1ENV\s+1\fP file"
+When an interactive \f5ksh\fP starts, it evaluates the
+.B $\s-1ENV\s+1
+variable to arrive at a file name.
+If this value is not null,
+\f5ksh\fP attempts to read and process
+commands in a file by this name.
+Earlier versions of \f5ksh\fP read the \fB\s-1ENV\s+1\fP file
+for all invocations of the shell primarily to allow
+function definitions to be available for all shell
+invocations.
+The function search path, \fB\s-1FPATH\s+1\fP, described later,
+eliminated the primary need for this capability and it was
+removed because the high performance cost was no longer
+deemed acceptable.
+.H 1 "PROGRAMMING LANGUAGE"
+The KornShell vastly extends the set of applications that
+can be implemented efficiently at the shell level.
+It does this by providing simple yet powerful mechanisms
+to perform arithmetic, pattern matching,
+substring generation,
+and arrays.
+Users can write applications as separate functions that can
+be defined in the same file or in a library of functions
+stored in a directory and loaded on demand.
+.H 2 "String Processing"
+The shell is primarily a string processing language.
+By default, variables hold variable length strings.
+There are no limits to the length of strings. Storage
+management is handled by the shell automatically.
+Declarations are not required.
+With most programming languages, string constants are designated
+by enclosing characters in single quotes or double quotes.
+Since most of the words in the language are strings, the shell
+requires quotes only when a string contains characters that
+are normally processed specially by the shell, but their
+literal meaning is intended.
+However, since the shell is a string processing language,
+and some characters can occur as literals and as language metacharacters,
+quoting is an important part of the language.
+.P
+There are four quoting mechanisms in \f5ksh\fP.
+The simplest is to enclose a sequence of characters inside single quotes.
+All characters between a pair of single quotes have their literal meaning;
+the single quote itself cannot appear.
+A
+.B $
+immediately preceding
+a single quoted string
+causes all the characters until the matching single quote
+to be interpreted as an ANSI-C language string.
+Thus, \f5'\en'\fP represents characters \f5\e\fP and
+\f5n\fP, whereas, \f5$'\en'\fP
+represents the new-line character.
+Double quoted strings remove the special meaning of all characters
+except
+.BR $ ,
+.BR \(ga ,
+and
+.BR \e ,
+so that parameter expansion and command substitution (defined below)
+are performed.
+The final mechanism for quoting a character is by preceding it with the
+escape character
+.BR \e\^ .
+This mechanism works outside of quoted strings and for the characters
+.BR $ ,
+.BR \(ga ,
+\fB"\fP,
+and
+.B \e
+in double quoted strings.
+.P
+Variables are designated by
+one or more
+strings of alphanumeric
+characters beginning with an alphabetic character
+separated by a \fB\s+2.\s-2\fP.
+Upper and lower case characters are distinct, so that the variable
+.B A
+and
+.B a
+are names of different variables.
+There is no
+limit to the length of the name of a variable.
+You do not have to declare variables.
+You can assign a value to a variable by writing the name of the
+variable, followed by an equal sign, followed by a character string
+that represents its value.
+To create a variable whose name
+contains a \fB\s+2.\s-2\fP,
+the variable whose name consists of
+the characters before the last \fB\s+2.\s-2\fP
+must already exist.
+You reference a variable by
+putting the name inside curly braces and
+preceding the braces with a dollar sign.
+The braces may be omitted when the name
+is alphanumeric.
+If \f5x\fP and \f5y\fP
+are two shell variables, then
+to define a new variable,
+\f5z\fP,
+whose value is
+the concatenation of the values of
+\f5x\fP and \f5y\fP,
+you just say
+\f5z=$x$y\fP.
+It is that easy.
+.P
+The
+.B $
+can be thought of as meaning
+"value of."
+You can also capture the output of any command with the notation
+.BI $( command ) .
+This is referred to as command substitution.
+For example,
+\f5x=$(date)\fP
+assigns the output from the \f5date\fP
+command to the variable \f5x\fP.
+Command substitution in the
+Bourne shell is denoted by enclosing the command between
+backquotes,
+(\fB\(ga\^\(ga\fP).
+This notation
+suffers from some
+complicated quoting rules.
+Thus, it is hard to write \f5sed\fP
+patterns which contains back slashes within command substitution.
+Putting the pattern in single quotes
+is of little help.
+\f5ksh\fP accepts the Bourne shell command substitution syntax
+for backward compatibility.
+The
+.BI $( command )
+notation allows
+the \fIcommand\fP itself to contain quoted strings even if the substitution
+occurs within double quotes. Nesting is legal.
+.P
+The special command substitution of the form
+\f5$(cat\ file)\fP
+can be replaced by
+\f5$(<\ file)\fP,
+which is faster because
+the \f5cat\fP
+command doesn't have to run.
+.H 2 "Shell Parameters and Variables"
+.P
+There are three types of parameters used by \f5ksh\fP,
+special parameters, positional parameters, and named
+parameters which are called variables.
+\f5ksh\fP defines the same special parameters,
+.BR 0 ,
+.BR * ,
+.BR @ ,
+.BR # ,
+.BR ? ,
+.BR $ ,
+.BR ! ,
+and
+.BR \- ,
+as in the Bourne shell.
+.P
+Positional parameters are set when the shell is invoked,
+as arguments to the \f5set\fP built-in,
+and by calls to functions (see below) and \fB\s+2.\s-2\fP
+procedures.
+They are named by numbers starting at 1.
+.P
+The third type of parameter is a variable.
+As mentioned earlier,
+\f5ksh\fP uses variables whose names
+consist of one or more
+alpha-numeric strings separated by a \fB\s+2.\s-2\fP.
+There is no need to specify the
+.I type
+of a variable in the shell because, by default,
+variables store strings of arbitrary length
+and values will automatically be converted to numbers
+when used in an arithmetic context.
+However, \f5ksh\fP variables
+can have one or more
+.I attributes
+that control the internal representation of the variable,
+the way the variable is printed, and its access or
+scope.
+In addition,
+\f5ksh\fP
+allows variables to represent arrays of values
+and references to other variables.
+The \f5typeset\fP
+built-in command of \f5ksh\fP
+assigns attributes to variables.
+Two of the attributes,
+.I readonly
+and
+.IR export ,
+are available in the Bourne shell.
+Most of the remaining attributes are discussed here.
+The complete list of attributes appears in the manual.
+The \f5unset\fP
+built-in of \f5ksh\fP removes
+values and attributes of variables.
+When a variable is exported, certain of its attributes are also exported.
+.P
+Whenever a value is assigned to a variable,
+the value is transformed according to the attributes of the variable.
+Changing the attribute of a variable can change its value.
+The attributes
+.B \-L
+and
+.B \-R
+are for left and right field justification respectively.
+They are useful for aligning columns in a report.
+For each of these attributes, a width can be defined explicitly or else
+it is defined the first time an assignment is made to the variable.
+Each assignment causes justification of the field, truncating
+if necessary.
+Assignment to fixed sized variables
+provides one way to generate a substring consisting of
+a fixed number of characters from
+the beginning or end of a string.
+Other methods are discussed later.
+.P
+The attributes
+.B \-u
+and
+.B \-l
+are used for upper case and lower case
+formatting, respectively.
+Since it makes no sense to have both attributes on simultaneously,
+turning on either of these attributes turns the other off.
+The following script,
+using \f5read\fP and \f5print\fP which are described later,
+provides an example of the use of shell variables
+with attributes.
+This script reads a file of lines each consisting of five fields separated by
+.B :
+and prints fields 4 and 2 in upper case in columns 1-15, left justified,
+and columns 20-25 right-justified respectively.
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5typeset -uL15 f4 # 15 character left justified
+typeset -uR6 f2 # 6 character right justified
+IFS=: # set field separator to :
+while read -r f1 f2 f3 f4 f5 # read line, split into fields
+do print -r -- "$f4 $f2" # print fields 4 and 2
+done\fP
+.fi
+.ta
+.in
+.sp
+.P
+The
+.BR \-i ,
+.BR \-E ,
+and
+.BR \-F ,
+attributes are used to represent numbers.
+Each can be followed by a decimal number.
+The
+.B \-i
+attribute causes the value to be represented as an integer and it
+can be followed by a number representing the numeric base when expanding
+its value.
+Whenever a value is assigned to an integer variable, it is evaluated
+as an arithmetic expression
+and then truncated to an integer.
+.P
+The
+.B \-E
+attribute causes the value to be represented in scientific
+notation whenever its value is expanded. The number following the
+.B \-E
+determines the number of significant figures, and defaults to 6.
+The
+.B \-F
+attribute causes the value to be represented with a fixed number
+of places after the decimal point.
+Assignments to variables with the
+.B \-E
+or
+.B \-F
+attributes cause the evaluation of the right hand side of the assignment.
+.P
+\f5ksh\fP allows one-dimensional
+.I arrays
+in addition to simple variables.
+There are two types of arrays; associative arrays
+and indexed arrays.
+The subscript for an associative array is an arbitrary
+string, whereas the subscript for an indexed array is
+an arithmetic expression that is evaluated to yield an integer
+index.
+Any variable can become an indexed array
+by referring to it with
+an integer
+.IR subscript .
+All elements of an array need not exist.
+Subscripts for arrays
+must evaluate to an
+integer between 0 and some maximum value, otherwise
+an error results.
+The maximum value may vary from one machine to another but
+is at least 4095.
+Evaluation of subscripts is described in
+the next section.
+Attributes apply to the whole array.
+.P
+Assignments to array variables can be made to individual elements
+via parameter
+assignment commands or the
+.B typeset
+built-in.
+Additionally, values can be assigned sequentially with
+compound assignment as described below, or by the
+.B \-A
+.I name
+option of the \f5set\fP command.
+Referencing of subscripted variables requires the character
+.BR $ ,
+but also requires braces around the array element name.
+The braces are needed to avoid conflicts with the
+file name generation mechanism.
+The form of any array element reference is:
+.ce
+.BI ${ name [ subscript ]}
+Subscript values of
+.B *
+and
+.B @
+can be used to generate all elements of an array,
+as they are used for expansion of positional parameters.
+The list of currently defined subscripts for a given
+variable can be generated with
+.BI ${! name [@]} ,
+or
+.BI ${! name [*]} .
+.P
+The
+.B \-n
+or
+.I nameref
+attribute causes the variable to be treated
+as a reference to the variable defined by its value.
+Once this attribute is set, all references to this variable
+become references to the variable named by the value
+of this variable.
+For example, if \f5foo=bar\fP, then setting the reference
+attribute on \f5foo\fP will cause all subsequent references
+to \f5foo\fP to behave as the variable whose name is \f5$foo\fP
+was referenced, which in this case is the variable \f5bar\fP.
+Unsetting this attribute breaks the association.
+Reference variables are usually used inside functions whose
+arguments are the names of shell variables.
+The names for reference variables cannot contain a \fB\s+2.\s-2\fP.
+Whenever a shell variable is referenced, the portion of the
+variable up to the first \fB\s+2.\s-2\fP
+is checked to see whether it matches the name of a reference
+variable.
+If it does, then the name of the variable actually used
+consists of the concatenation of the name of the variable
+defined by the reference plus the remaining portion of the
+original variable name.
+For example, using the predefined alias, \f5alias\ nameref='typeset\ -n'\fP,
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5\^.bar.home.bam="hello world"
+nameref foo=.bar.home
+print ${foo.bam}
+\fBhello world\fP\fP
+.fi
+.ta
+.in
+.sp
+.H 2 "Compound Assignment"
+Compound assignments are used to assign values to arrays
+and compound data structures.
+The syntax for a compound assignment is
+.IB name =( assignment-list )
+where
+\fIname\fP
+is the name of the variable to which you want to assign values.
+No space is permitted between the variable name and the \fB=\fP
+but can appear between the \fB=\fP and the open parenthesis.
+New-lines can appear between the parentheses.
+.P
+The \fIassignment-list\fP can be in several different forms
+yielding different results.
+If \fIassignment-list\fP is simply a list of words, then
+the words are processed as they are with the \f5for\fP command
+and assigned sequentially as an indexed array.
+For example,
+.ce
+\f5foo=( * )\fP
+creates an indexed array \f5foo\fP and assigns the
+file names in the current directory to each index starting
+at zero.
+.P
+The second form for \fIassignment-list\fP is a list of assignments
+of the special form \fB[\fP\fIword\fP\fB]=\fP\fIword\fP.
+No space is permitted before or after the \fB=\fP.
+In this case, the variable given by \fIname\fP becomes
+an associative array with the given arguments as subscripts.
+For example,
+.ce
+\f5bar=( [color]=red [shape]=box )\fP
+creates an associate array named \f5bar\fP whose
+subscripts are \f5color\fP and \f5shape\fP.
+.P
+The third form for \fIassignment-list\fP is a list of
+normal assignments, including compound assignments.
+These assignments cause sub-variables to be assigned
+corresponding to the given assignments.
+In addition to assignments, the \fIassignment-list\fP
+can contain \f5typeset\fP commands.
+In addition to creating sub-variables,
+the effect of a compound assignment is to make
+the value of the original variable be a parenthesized
+assignment list of its components.
+For example, the assignment
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5foo=(
+ left=bar
+ typeset -i count=3
+ point=(
+ x=50
+ y=60
+ )
+ colors=( red green yellow )
+ right=bam
+) \fP
+.ta
+.in
+.fi
+.sp
+is equivalent to the assignments
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5foo.left=bar
+foo.count=3
+foo.point.x=50
+foo.point.y=60
+foo.colors=( red green yellow )
+foo.right=bam\fP
+.ta
+.in
+.fi
+.sp
+In addition, the value of \f5"$foo"\fP is
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5(
+ colors=( red green yellow )
+ left=bar
+ typeset -i count=3
+ point=(
+ y=60
+ x=50
+ )
+ right=bam
+)\fP
+.ta
+.in
+.fi
+.sp
+.H 2 "Substring Generation"
+The expansion of a variable or parameter can be modified so that
+only a portion of the value results.
+It is often necessary to extract a portion of a shell variable or
+a portion of an array.
+There are several parameter expansion operators that can do this.
+One method to generate a substring is with an expansion of
+the form \fB${\fP\fIname\fP\fB:\fP\fIoffset\fP\fB:\fP\fIlength\fP\fB}\fP
+where \fIoffset\^\fP is an arithmetic expression that defines the
+offset of the first character starting from 0, and
+\fIlength\^\fP is an arithmetic expression that defines the
+length of the substring.
+If
+.BI : length\^
+is omitted,
+the length of the value of
+.I name\^
+starting at
+.I offset\^
+is used.
+The
+.BI : offset : length
+operators can also be applied to array expansions and to parameters
+.B *
+and
+.B @
+to generate portions of an array.
+For example, the expansion, \fB${\fP\fIname\fP\fB[@]:\fP\fIoffset\fP\fB:\fP\fIlength\fP\fB}\fP, yields up to \fIlength\fP elements of the array \fIname\fP
+starting at the element \fIoffset\fP.
+.P
+The other parameter expansion modifiers use shell patterns
+to describe portions of the string to modify and delete.
+A description of shell patterns is contained below.
+When these
+modifiers are applied to special parameters
+.B @
+and
+.B *
+or to array parameters given as
+\fIname\fP\fB[@]\fP or \fIname\fP\fB[*]\fP,
+the operation is performed on each element.
+There are four parameter expansion modifiers that
+strip off leading and trailing substrings
+during parameter expansion
+by removing the characters matching a given pattern.
+An expansion of
+the form \fB${\fP\fIname\fP\fB#\fP\fIpattern\fP\fB}\fP
+causes the smallest matching prefix of the value of
+.I name\^
+to be removed.
+The largest prefix matching
+.I pattern\^
+is removed by using
+.B ##
+instead of
+.BR # .
+Similarly,
+an expansion of
+the form \fB${\fP\fIname\fP\fB%\fP\fIpattern\fP\fB}\fP
+causes the smallest matching substring at the end of
+.I name\^
+to be removed.
+Again, using
+.B %%
+instead of
+.BR % ,
+causes the largest matching trailing substring to be deleted.
+For example, if the shell variable
+.B file
+has value
+.BR foo.c ,
+then the expression
+.B ${file%.c}.o
+has value
+.BR foo.o .
+.P
+The value of an expansion can be changed by
+specifying a pattern that matches the part that needs to be changed
+after the
+the parameter expansion modifier
+.BR / .
+An expansion of the form
+\fB${\fP\fIname\fP\fB/\fP\fIpattern\fP\fB/\fP\fIstring\fP\fB}\fP
+replaces the first match of \fIpattern\fP with
+the value of variable \fIname\fP to \fIstring\fP.
+The second
+.B /
+is not necessary when \fIstring\fP is null.
+The expansion
+\fB${\fP\fIname\fP\fB//\fP\fIpattern\fP\fB/\fP\fIstring\fP\fB}\fP
+changes all occurrences of the \fIpattern\fP into \fIstring\fP.
+The parameter expansion modifiers
+.B /#
+and
+.B /%
+cause the matching pattern to be anchored to the beginning and
+end respectively.
+.P
+Finally, there are parameter expansion modifiers that yield
+the name of the variable, the string length of the value, or the number
+of elements of an array.
+\fB${!\fP\fIname\fP\fB}\fP
+yields the name of the variable which will be \fIname\fP itself
+except when \fIname\fP is a reference variable. In this case
+it will yield the name of the variable it refers to.
+When applied to an array variable,
+\fB${!\fP\fIname\fP\fB[@]}\fP and
+\fB${!\fP\fIname\fP\fB[*]}\fP
+generate the names of all subscripts.
+\fB${#\fP\fIname\fP\fB}\fP
+will be the length in bytes of
+\fB$\fP\fIname\fP.
+For an array variable
+\fB${#\fP\fIname\fP\fB[*]}\fP
+gives the number of elements in the array.
+.H 2 "Arithmetic Evaluation"
+.P
+For the most part, the shell is a string processing
+language. However, the need for arithmetic has
+long been obvious.
+Many of the characters that are special to the
+Bourne shell are needed as arithmetic operators.
+To make arithmetic easy to use, and to maintain
+compatibility with the Bourne shell, \f5ksh\fP uses matching
+.B ((
+and
+.B ))
+to delineate arithmetic expressions.
+While single parentheses might have been
+more desirable, these already mean
+.I subshell\^
+so that another notation was required.
+The arithmetic expression
+inside the double parentheses
+follows the same syntax, associativity and precedence
+as the ANSI-C\*(Rf
+.RS
+American National Standard for Information Systems \- Programming
+Language \- C, ANSI X3.159-1989.
+.RF
+programming language.
+The characters between the matching double parentheses
+are processed with the same rules used for double
+quotes so that spaces can be used to aid readability
+without additional quoting.
+.P
+All arithmetic evaluations are performed using
+double precision floating point arithmetic.
+Floating point constants follow the same rules as
+the ANSI-C programming language.
+Integer arithmetic constants are written as
+.ce
+.IB base # number,
+where
+.I base\^
+is a decimal integer between
+two and sixty-four and
+.I number\^
+is any non-negative number.
+Base ten is used
+when no base is specified.
+The digits are represented by the characters
+.BR 0-9a-zA-Z_@ .
+For bases less than or equal to 36,
+upper and lower case characters can
+be used interchangeably to represent the digits
+from 10 thru 35.
+.P
+Arithmetic expressions are made from constants,
+variables, and operators.
+Parentheses may be used for grouping.
+The contents inside the double parentheses
+are processed with the same expansions as occurs in a double quoted string,
+so that all
+.B $
+expansions are performed before the expression is evaluated.
+However, there is usually no need to use the
+.B $
+to get the value of a variable
+because the arithmetic evaluator replaces the name of the variable
+by its value within an arithmetic expression.
+The
+.B $
+cannot be used when the variable is the subject of assignment
+or an increment operation.
+As a rule it is better not to use
+.B $
+in front of variables in an arithmetic expression.
+.P
+An arithmetic command of the form
+.B
+(( ... ))
+.R
+is a command that evaluates the enclosed arithmetic expression.
+For example, the command
+.ce
+\f5(( x++ ))\fP
+can be used to
+increment the variable \f5x\fP,
+assuming that \f5x\fP contains some numerical value.
+The arithmetic command is true (return value 0), when the resulting
+expression is non-zero, and false (return value 1) when the
+expression evaluates to zero.
+This makes the command easy to use with the \f5if\fP and \f5while\fP
+compound commands.
+.P
+The \f5for\fP compound command
+has been extended for use in arithmetic contexts.
+The syntax,
+.ce
+\f5for\fP \fB((\fP \fIexpr1\fP\fB;\fP \fIexpr2\fP \fB;\fP \fIexpr3 \fP\fB))\fP
+can be used as the first line of a \f5for\fP loop with the same semantics
+as the \f5for\fP statement in the ANSI-C programming language.
+.P
+Arithmetic evaluations can also be performed as part of the evaluation
+of a command line.
+The syntax
+.B
+$((\ ...\ ))
+.R
+expands to the value of the enclosed arithmetic expression.
+This expansion can occur wherever parameter expansion is performed.
+For example using the \f5ksh\fP command \f5print\fP (described
+later)
+.ce
+\f5print $((2+2))\fP
+prints the number 4.
+.P
+The following script prints the first
+.I n
+lines of its standard input onto its standard output,
+where
+.I n
+can be supplied as an optional argument whose default value is 20.
+.sp
+.nf
+.in .5i
+.ta 4i
+\f5integer n=${1-20} # set n
+while (( n-- >=0 )) && read -r line # at most n lines
+do print -r -- "$line"
+done\fP
+.fi
+.ta
+.in
+.sp
+.H 2 "Shell Expansions"
+.P
+The commands you enter from the terminal or from a script
+are divided into words and each word undergoes several
+expansions to generate the command name and its arguments.
+This is done in two phases.
+The first phase recognizes reserved words, spaces and operators
+to decide where command boundaries lie.
+Alias substitutions take place during this phase.
+The second phase performs expansions in the following order:
+.BL
+.LI
+Tilde substitution,
+parameter expansion,
+arithmetic expansion,
+and command substitution
+are performed from left to right.
+The option
+.B \-u
+or
+.BR nounset ,
+will cause an error to occur when any variable
+that is not set is expanded.
+.LI
+The characters that result from parameter expansion and
+command substitution above are checked with the characters
+in the
+\fB\s-1IFS\s+1\fP variable
+for possible
+field splitting.
+(See a description of \f5read\fP below to see how
+\fB\s-1IFS\s+1\fP is used.)
+Setting
+\fB\s-1IFS\s+1\fP to a null
+value causes field splitting to be skipped.
+.LI
+Pathname generation (as described below)
+is performed on each of the fields.
+Any field that doesn't match a pathname is left alone.
+The option,
+.B \-f
+or
+.BR noglob ,
+is used to disable pathname generation.
+.LE
+.H 2 "Pattern Matching"
+The shell is primarily a string processing language and uses
+patterns for matching file names as well as for matching strings.
+The characters
+.BR ? ,
+.BR * ,
+and
+.B [
+are processed specially
+by the shell when not quoted.
+These characters are used to form patterns that
+match strings.
+Patterns are used by the shell to match pathnames,
+to specify substrings,
+and for
+.B case
+commands.
+The character
+.B ?
+matches any one character.
+The character
+.B *
+matches zero or more characters.
+The character sequence
+.BR [ ... ]
+defines a character class
+that matches any character contained within
+.BR [\^] .
+A range of characters can be specified by putting a
+.B \-
+between the first and last character of the range.
+An exclamation mark,
+.BR ! ,
+immediately after the
+.BR [ ,
+means match all characters except the characters specified.
+For example, the pattern
+\f5a?c*.[!a-z]\fP
+matches any string beginning with an
+.BR a ,
+whose third character is a
+.BR c ,
+and that ends in
+.B .
+(dot) followed by any character except the lower case letters,
+.BR a\-z .
+The sequence \f5[:alpha:]\fP
+inside a character class, matches any set of characters in
+the ANSI-C
+.B alpha
+class.
+Similarly, \f5[:\fP\fIclass\fP\f5:]\fP matches
+each of the characters in the given \fIclass\fP
+for all the ANSI-C character classes.
+For example, \f5[[:alnum:]_]\fP
+matches any alpha-numeric character or the character
+.BR _ .
+.P
+\f5ksh\fP
+treats
+strings of the form
+.BI ( pattern-list
+.BR ) ,
+where
+.I pattern-list
+is a list of one or more patterns separated by a
+.BR \(bv ,
+specially when preceded by
+.BR * ,
+.BR ? ,
+.BR + ,
+.BR @ ,
+or
+.BR ! .
+A
+.B ?
+preceding
+.BI ( pattern-list )
+means that the pattern list enclosed in
+.B (\^)
+is optional.
+An
+.BI @( pattern-list )
+matches any pattern in the list of patterns enclosed in
+.BR () .
+A
+.BI *( pattern-list )
+matches any string that contains zero or more of each of the enclosed
+patterns,
+whereas
+.BI +( pattern-list )
+requires a match of one or more of any of the given patterns.
+For instance, the pattern
+.B +([0\-9])?(.)
+matches one or more digits optionally followed by a
+.BR . (dot).
+A
+.BI !( pattern-list )
+matches anything except any of the given patterns.
+For example,
+\f5print\ !(*.o)\fP
+displays all file names in the current directory that do not end in
+.BR .o .
+.P
+When patterns are used to generate pathnames when expanding
+commands several other rules apply.
+A separate match is made
+for each file name component of the pathname.
+Read permission is required for
+any portion of the pathname that contains any special
+pattern character.
+Search permission is required for every component except
+possibly the last.
+.P
+By default,
+file names in each directory that begin with \fB\s+2.\s-2\fP
+are skipped when performing a match.
+If the pattern to be matched starts with a leading \fB\s+2.\s-2\fP,
+then only files beginning with a \fB\s+2.\s-2\fP,
+are examined when reading each directory to find matching files.
+If the
+\fB\s-1FIGNORE\s+1\fP variable
+is set,
+then only files that do not match this pattern
+are considered.
+This overrides the special meaning of \fB\s+2.\s-2\fP
+in a pattern and in a file name.
+.P
+If the
+.B markdirs
+option is set,
+each matching pathname that is the name
+of a directory has a trailing
+.B /
+appended to the name.
+.P
+.H 2 "Conditional Expressions"
+The Bourne shell uses the \f5test\fP
+command, or the equivalent \f5[\fP
+command, to test files for attributes
+and to compare strings or numbers.
+The problem with \f5test\fP
+is that the shell has expanded the words of the \f5test\fP
+command and
+split them into arguments before \f5test\fP begins execution.
+\f5test\fP
+cannot distinguish between operators and operands.
+In most cases
+\f5test\ "$1"\fP
+will test whether argument 1 is non-null.
+However,
+if argument 1 is
+.BR \-f ,
+then \f5test\fP
+will treat
+.B \-f
+as an operator and
+yield a syntax error.
+One of the most frequent errors with
+\f5test\fP
+occurs when its operands are not within double quotes.
+In this case, the argument may expand to more than a single
+argument or to no argument at all. In either case this
+will likely cause a syntax error.
+What makes this most insidious is that these errors are frequently
+data dependent. A script that appears to run correctly may abort
+if given unexpected data.
+.P
+To get around these problems,
+\f5ksh\fP
+has a compound command for conditional expression testing
+as part of the language.
+The reserved words
+.B [[
+and
+.B ]]
+delimit the range of the command.
+Because they are reserved words, not operator characters,
+they require spaces to separate them
+from arguments.
+The words between
+.B [[
+and
+.B ]]
+are not processed for field splitting or for pathname generation.
+In addition, since \f5ksh\fP
+determines the operators before parameter expansion,
+expansions that yield no argument cause no problem.
+The operators within
+.BR [[ ... ]]
+are almost the same as those for the \f5test\fP
+command.
+All unary operators are of the form
+.BI \- letter
+and are followed by a single operand.
+Instead of
+.B \-a
+and
+.BR \-o ,
+.BR [[ ... ]]
+uses
+.B &&
+and
+.B \(bv\(bv
+to indicate "and" and "or".
+Parentheses are used without quoting for grouping.
+.P
+The right hand side of the string comparison operators
+.B ==
+and
+.B !=
+takes a pattern and tests whether the left hand operand
+matches this pattern. Quoting the pattern results
+is a string comparison rather than the pattern match.
+The operators
+.B <
+and
+.B >
+within
+.BR [[ ... ]]
+designate lexicographical comparison.
+.P
+In addition there are several other new comparison primitives.
+The binary operators
+.B \-ot
+and
+.B \-nt
+compare the modification times
+of two files to see which file is
+.I "older than"
+or
+.I "newer than"
+the other.
+The binary operator
+.B \-ef
+tests whether two files
+have the same device and i-node number,
+i.\ e., a link to the same file.
+.P
+The unary operator
+.B \-L
+returns true if its operand is a symbolic link.
+The unary operator
+.B \-O
+(\fB\-G\fP)
+returns true if the owner (or group) of the file operand matches
+that of the caller.
+The unary operator
+.B \-o
+returns true when its operand is the name of an option that is
+currently on.
+.P
+The following script illustrates some of the uses of
+.BR [[ ... ]] .
+The reference manual contains the complete list of operators.
+.sp
+.nf
+.in .5i
+.ta 4i
+\f5for i
+do # execute foo for numeric directory
+ if [[ \-d $i && $i == +([0\-9]) ]]
+ then foo
+ # otherwise if writable or executable file and not mine
+ elif [[ (\-w $i\(bv\(bv\-x $i) && ! \-O $i ]]
+ then bar
+ fi
+done\fP
+.fi
+.ta
+.in
+.sp
+.H 2 "Input and Output"
+\f5ksh\fP has
+extended I/O capabilities to enhance the
+use of the shell as a programming language.
+As with the Bourne shell,
+you use the I/O redirection operator,
+.BR < ,
+to control where input comes from,
+and the I/O redirection operator,
+.BR > ,
+to control where output goes to.
+Each of these operators can be preceded with a single digit that
+specifies a file unit number to associate with the file stream.
+Ordinarily you specify these I/O redirection operators with a specific
+command to which it applies.
+However, if you specify I/O redirections with the \f5exec\fP
+command,
+and don't specify arguments to \f5exec\fP,
+then the I/O redirection applies to the current program.
+For example, the command
+\f5exec\ <\ foobar\fP
+opens file \f5foobar\fP
+for reading.
+The \f5exec\fP
+command is also used to close files.
+A file descriptor unit can be opened as a copy of an existing
+file descriptor unit by using either of the
+.B <&
+or
+.B >&
+operators and putting the file descriptor unit of the original file
+after the
+.BR & .
+Thus, \f52>&1\fP means open standard error (file descriptor 2)
+as a copy of standard output (file descriptor 1).
+A file descriptor value of
+.B \-
+after the
+.B &
+indicates that the file should be closed.
+To close file unit 5, specify
+\f5exec\ 5<&-\fP.
+There are two additional redirection operators with \f5ksh\fP
+and the POSIX shell that are not part of the Bourne shell.
+The
+.B >|
+operator overrides the effect of the
+.B noclobber
+option described earlier.
+The
+.B <\^>
+operator causes a file to be opened for both reading and writing.
+.P
+\f5ksh\fP recognizes certain pathnames and treats them
+specially.
+Pathnames of the form
+.BI /dev/fd/ n\^
+are treated as equivalent to the file defined by file descriptor
+.IR n .
+These name can be used as the script argument to \f5ksh\fP
+and in conditional testing as described above.
+On underlying systems that support
+.B /dev/fd
+in the file system, these names can be passed to other commands.
+Pathnames of the form
+.BI /dev/tcp/ hostid / port
+and
+.BI /dev/udp/ hostid / port
+can be used to create
+.B tcp
+and
+.B udp
+connections to services given by the
+.I hostid\^
+number and
+.I port\^
+number.
+The
+.I hostid\^
+cannot use symbolic values. In practice these
+numbers are typically generated by command substitution.
+For example,
+\f5exec\ 5>\ /dev/tcp/$(service\ name)\fP
+would open file descriptor 5 for sending messages
+to hostid and port number defined by the output of \f5service\ name\fP.
+.P
+The Bourne shell has a built-in command \f5read\fP
+for reading lines from standard input (file descriptor 0)
+and splitting it into fields based on the value of the
+.B \s-1IFS\s+1
+variable, and a command \f5echo\fP
+to write strings to standard output.
+(On some systems, \f5echo\fP
+is not a built-in command and incurs considerable overhead to use.)
+Unfortunately, neither of these commands
+is able to perform some very basic tasks.
+For example.
+with the Bourne shell,
+the \f5read\fP
+built-in cannot read a single line that ends in
+.BR \e .
+With \f5ksh\fP
+the \f5read\fP
+built-in has a
+.B \-r
+option to remove the special meaning for
+.B \e
+which allows it to be
+treated as a regular
+character rather than the line continuation character.
+With the Bourne shell,
+there is no simple way to have more than one file open
+at any time for reading.
+\f5ksh\fP has options on the \f5read\fP
+command to specify the file
+descriptor for the input.
+The fields that are read from a line can be stored into an indexed
+array with the
+.B \-A
+option to read.
+This allows a line to be split into an arbitrary number of fields.
+.P
+The way the Bourne shell uses the
+\fB\s-1IFS\s+1\fP variable to
+split lines into fields greatly limits its utility.
+Often data files consist of lines that use a character such
+as
+.B :
+to delimit fields with two adjacent delimiters that denote
+a null field.
+The Bourne shell treats adjacent delimiters as a single
+field delimiter.
+With \f5ksh\fP,
+delimiters that are considered white space characters
+have the behavior of the Bourne shell, but other
+adjacent delimiters separate
+null fields.
+.P
+The \f5read\fP command is often used in scripts that interact
+with the user by prompting the user and then requesting some
+input.
+With the Bourne shell two commands are needed; one to
+prompt the user, the other to read the reply.
+\f5ksh\fP allows these two commands to be combined.
+The first argument of the \f5read\fP
+command can be followed by a
+.B ?
+and a prompt string which is used whenever the input
+device is a terminal.
+Because the prompt is associated with the \f5read\fP built-in,
+the built-in command line editors will be able to re-output
+the prompt whenever the line needs to be refreshed when
+reading from a terminal device.
+.P
+With the Bourne shell,
+there is no way to set a time limit for waiting for the user
+response to read.
+The
+.B \-t
+option to \f5read\fP takes a floating
+point argument that gives the time in seconds,
+or fractions of seconds that the shell should wait for a reply.
+.P
+The version of the \f5echo\fP command in System V
+treats certain sequences beginning with
+.B \e
+as control sequences.
+This makes it hard to output strings without interpretation.
+Most BSD derived systems do not interpret
+.B \e
+control sequences.
+Unfortunately, the BSD versions of \f5echo\fP accepts a
+.B \-n
+option to prevent a trailing new-line, but has no way to
+cause the string
+.B \-n
+to be printed.
+Neither of these versions is adequate. Also, because they
+are incompatible, it is very hard to write portable shell scripts
+using \f5echo\fP.
+The \f5ksh\fP built-in, \f5print\fP,
+outputs characters to the terminal or to a file and
+subsumes the functions of all versions of \f5echo\fP.
+Ordinarily, escape sequences in arguments beginning with
+.B \e
+are processed the same as for the System V \f5echo\fP command.
+However \f5print\fP follows the standard conventions for
+options and has options that make \f5print\fP very versatile.
+The
+.B \-r
+option can be used to output the arguments without any special meaning.
+The
+.B \-n
+option can be used here to suppress the trailing new-line
+that is ordinarily appended.
+As with \f5read\fP, it is possible to specify the file descriptor number
+as an option to the command to avoid having to use
+redirection operators with each occurrence of the command.
+.P
+The IEEE POSIX shell and utilities standard committee was unable
+to reconcile the differences between the System V and BSD
+versions of \f5echo\fP.
+They introduced a new command named \f5printf\fP
+which takes an ANSI-C format string and a list of options
+and outputs the strings using the ANSI-C formatting rules.
+Since \f5ksh\fP is POSIX conforming, it accepts \f5printf\fP.
+However, there is a
+.B \-f
+options to \f5print\fP that can be used to specify
+a format string which processes the arguments the same way that
+\f5printf\fP does.
+.P
+The format processing for \f5print\fP and \f5printf\fP has
+been extended slightly.
+There are three additional formatting directives.
+The
+.B %b
+format causes the
+.B \e
+escape sequences to be expanded as they are with the System V \f5echo\fP
+command.
+The
+.B %q
+format causes quotes to
+be placed on the output as required
+so that it can be used as shell input.
+Special characters in the output of most \f5ksh\fP built-in commands
+and in the output from an execution trace
+are quoted in an equivalent fashion.
+The
+.B %P
+format causes an extended regular expression string to
+be converted into a shell pattern.
+This is useful for writing shell applications that have
+to accept regular expressions as input.
+Finally, the escape sequence
+.B \e\^E
+which expands to the terminal escape character (octal 033)
+has been added.
+.P
+The shell is frequently used as a programming language for
+interactive dialogues.
+The
+\f5select\fP
+statement has been added to the language
+to make it easier to
+present menu selection alternatives to the
+user and evaluate the reply.
+The list of alternatives is numbered and put in columns.
+A user settable prompt,
+\fB\s-1PS3\s+1\fP,
+is issued and if the answer is
+a number corresponding to one of the alternatives,
+the select loop variable is set to this value.
+In any case, the
+.B \s-1REPLY\s+1
+variable is used to store the user entered reply.
+The shell variables
+.B \s-1LINES\s+1
+and
+.B \s-1COLUMNS\s+1
+are used to control the layout of select lists.
+.H 2 "Option Parsing"
+The \f5getopts\fP built-in command can be used
+to process command arguments in a manner consistent
+with the way \f5ksh\fP does for its own built-in commands.
+.P
+The \f5getopts\fP built-in allows users to specify options
+as separate arguments or to group options that do not
+take arguments together. Options that require arguments
+do not require space to separate them from the option argument.
+The
+.B \s-1OPTARG\s+1
+variable stores the value of the option argument
+after finding a variable that takes an argument.
+The
+.B \s-1OPTIND\s+1
+variable holds the index of the current options argument.
+After processing options, the arguments should be
+shifted by
+.B \s-1OPTIND\s+1\-1
+to make the
+remaining arguments be \f5"$@"\fP.
+.P
+The \f5getopts\fP argument description allows additional
+information to be specified along with the options
+that is used to generate \fIusage\fP messages for
+incorrect arguments and for the option argument \fB\-?\fP.
+The example in the APPENDIX uses \f5getopts\fP to process
+its arguments.
+.H 2 "Co-process"
+\f5ksh\fP can spawn a
+.I co-process
+by adding a
+.B "|&"
+after a command.
+This process will be run with its standard input and its
+standard output connected to the shell. The built-in command \f5print\fP
+with the
+.B \-p
+option will write into the standard input of this
+process and
+the built-in command \f5read\fP
+with the
+.B \-p
+option will read from the output of this process.
+.P
+In addition, the I/O redirection operators \fB<&\fP and \fB>&\fP can
+be used to move the input or output pipe of the co-process
+to a numbered file descriptor.
+Use \f5exec\ 3>&\ p\fP to move the input of the co-process
+to file descriptor \fB3\fP.
+After you have connected to file descriptor \fB3\fP, you
+can direct the output of any command to the co-process
+by running \fIcommand\fP\f5\ >&3\fP.
+Also, by moving the input of the co-process to a numbered descriptor,
+it is possible to run a second co-process.
+The output of both co-processes will be the file descriptor
+associated with \f5read\ -p\fP.
+You can use \f5exec\ 4<&\ p\fP to cause the output of these
+co-processes to go to file descriptor \fB4\fP of the shell.
+Once you have moved the pipe to descriptor \fB4\fP, it is possible
+to connect a server to the co-process by running \fIcommand\fP\f5\ 4<&\ p\fP
+or to close the co-process pipe with \f5exec\ 4<&\ -\fP.
+.H 2 "Functions"
+.P
+Function definitions are of the form
+.sp
+.in +.5i
+.nf
+\f5function\fP \fIname\fP
+.br
+.B {
+.br
+ any shell script
+.br
+.B }
+.fi
+.sp
+.in
+A function whose name contains a \fB\s+2.\s-2\fP
+is called a \fIdiscipline\fP function.
+The portion of the name after the last \fB\s+2.\s-2\fP
+is the name of the discipline.
+Discipline functions named \f5get\fP, \f5set\fP, and \f5unset\fP
+can be assigned to any variable to intercept lookups,
+assignments and unsetting of the variable
+defined by the portion of the name before the last \fB\s+2.\s-2\fP.
+Applications can create additional disciplines for variables
+that are created as part of user defined built-ins.
+The portion of the name before the last \fB\s+2.\s-2\fP
+must refer to the name of an existing variable.
+Thus, if \f5p\fP is a reference to \f5PATH\fP, then
+the function name \f5p.get\fP and \f5PATH.get\fP
+refer to the same function.
+.P
+The function is invoked either
+by specifying
+.I name
+as the command name
+and optionally following it with arguments
+or by using it as an option to the \fB\s+2.\s-2\fP
+built-in command.
+Positional parameters are saved before each
+function call and restored when completed.
+The arguments that follow the function name on the calling
+line become positional parameters inside the function.
+The \f5return\fP
+built-in can be used to cause the function to return to
+the statement following
+the point of invocation.
+.P
+Functions can also be defined with the System V notation,
+.sp
+.in +.5i
+.nf
+\fIname\fP \f5()\fP
+.br
+.B {
+.br
+ any shell script
+.br
+.B }
+.fi
+.sp
+.in
+Functions defined with this syntax cannot be used as the first
+argument to a \fB\s+2.\s-2\fP procedure.
+\f5ksh\fP accepts this notation for compatibility only.
+There is no need to use this notation when writing
+\f5ksh\fP scripts.
+.P
+Functions defined with the \f5function\fP\ \fIname\fP syntax
+and invoked by name
+are executed in the current shell environment
+and can share named variables with the calling program.
+Options, other than execution trace
+.BR \-x ,
+set by the calling program are
+passed down to a function.
+The options are
+not shared with
+the function so that any options set within a function are
+restored when the function exits.
+Traps ignored by the caller are ignored within the function
+and cannot be enabled.
+Traps caught by the calling program are reset to their
+default action within the function.
+In most instances, the default action is
+to cause the function to terminate.
+A trap on
+\fB\s-1EXIT\s+1\fP
+defined within a function executes after the function
+completes but
+before the caller resumes.
+Therefore,
+any variable assignments and
+any options set as part of a trap action will be effective
+after the caller resumes.
+.P
+By default, variables are inherited by the function and shared
+by the calling program.
+However,
+for functions defined with the \f5function\fP\ \fIname\fP syntax
+that are invoked by name,
+environment substitutions preceding the function call
+apply only to the scope of the function call.
+Also, variables whose names do not contain a \fB\s+2.\s-2\fP
+that are defined with the \f5typeset\fP
+built-in command are local to the function that they are declared in.
+Thus, for the function defined
+.sp
+.nf
+.in .5i
+\f5function name
+{
+ typeset -i x=10
+ let z=x+y
+ print $z
+}\fP
+.fi
+.ta
+.in
+.sp
+invoked as
+\f5y=13\ name\fP,
+\f5x\fP and \f5y\fP
+are local variables with respect to the function
+\f5name\fP
+while
+\f5z\fP
+is global.
+.P
+Functions defined with the \fIname\fP\f5()\fP syntax,
+and functions invoked as an argument to the \fB\s+2.\s-2\fP
+command,
+share everything other than positional parameters with the caller.
+Assignments that precede the call remain in effect after the
+function completes.
+.P
+Alias and function names are not passed down to shell scripts
+or carried across separate
+invocations of \f5ksh\fP.
+The
+.B $\s-1FPATH\s+1
+variable gives a colon separated list of directories that
+is searched for function definitions when trying to resolve
+the command name.
+Whenever a file name contained in
+.B $\s-1FPATH\s+1
+is found, the complete file is read and all functions
+contained within become defined.
+.P
+Calls that reference functions can be recursive.
+Except for special built-ins,
+function names take precedence over built-in names and names
+of programs when used as command names.
+To write a replacement function that invokes the command that
+you wish to replace,
+you can use the \f5command\fP built-in command.
+The arguments to \f5command\fP are the name and arguments
+of the program you want to execute.
+For example to write a
+.B cd
+function which changes the directory and prints out the directory name,
+you can write
+.sp
+.nf
+.in .5i
+\f5function cd
+{
+ if command cd "$@"
+ then print -r -- $PWD
+ fi
+}\fP
+.fi
+.ta
+.in
+.sp
+.P
+The
+\fB\s-1FPATH\s+1\fP
+variable is a colon separated list that \f5ksh\fP
+uses to search for function definitions.
+When
+\f5ksh\fP
+encounters an autoload function,
+it runs the
+.B .
+command on the script containing the function,
+and then executes the function.
+.P
+For interactive shells,
+function definitions may also be placed in the
+\fB\s-1ENV\s+1\fP
+file.
+However, this
+causes the shell to take longer to begin executing.
+.H 2 "Process Substitution"
+.P
+This feature is only available
+on versions of the UNIX operating system which support the
+.B /dev/fd
+directory for naming open files.
+Each command argument of the form
+\fB<(\fP\fIlist\^\fP\fB)\fP
+or
+\fB>(\fP\fIlist\^\fP\fB)\fP
+will run process
+.I list
+asynchronously connected to some file in the
+.B /dev/fd
+directory.
+The name of this file will become the argument to the command.
+If the form with
+.B >
+is selected then writing on this file will provide input for
+.IR list .
+If
+.B <
+is used,
+then the file passed as an argument will contain the output of the
+.I list
+process.
+For example,
+.sp
+.nf
+.in .5i
+\f5paste <(cut \-f1 \fP\fIfile1\fP\f5) <(cut \-f2 \fP\fIfile2\fP\f5) | tee >(\fP\fIprocess1\fP\f5) >(\fP\fIprocess2\fP\f5)\fP
+.fi
+.ta
+.in
+.sp
+extracts
+fields 1 and 3 from
+the files
+.I file1
+and
+.I file2
+respectively,
+places the
+results side by side, and
+sends it
+to the processes
+.I process1
+and
+.IR process2 ,
+as well as putting it onto the standard output.
+Note that the file which is passed as an argument to the command is
+a UNIX system
+.IR pipe (2)
+so that the programs that expect to
+.IR lseek (2)
+on the file will not work.
+.H 2 "Finding Commands"
+.P
+The addition of aliases, functions,
+and more built-ins
+has made it substantially more difficult to know what
+a given command name really means.
+.P
+Commands that begin with reserved words
+are an integral part of the shell language itself
+and typically define the control flow of the language.
+Some control flow commands are not reserved words in
+the language but are \fIspecial\fP built-ins.
+Special built-ins are built-ins that are considered a
+part of the language rather than user definable commands.
+The best examples of commands that fit this description
+are \f5break\fP and \f5continue\fP.
+Because they are not reserved words, they can be the
+result of shell expansions and are not effected by quoting.
+These commands have the following special properties:
+.BL
+.LI
+Assignments that precede them apply to the current shell process,
+not just to the given command.
+.LI
+An error in the format of these commands cause a shell script
+or function that contains them to abort.
+.LI
+They cannot be overridden by shell functions.
+.LE
+.P
+Other commands are built-in because they perform side effects
+on the current environment that would be nearly impossible
+to implement otherwise.
+Built-ins such as \f5cd\fP and \f5read\fP
+are examples of such built-ins.
+These built-ins are semantically equivalent to commands that
+are not built-in except that they don't take a path search
+to locate.
+.P
+A third reason to have a command built-in is so that
+it will be unaffected by the setting of the
+.B \s-1PATH\s+1
+variable.
+The \f5print\fP command fits this category.
+Scripts that use \f5print\fP will be portable
+to all sites that run \f5ksh\fP.
+.P
+The final reason for having a command be a built-in is
+for performance.
+On most systems it is more than an order of magnitude
+faster to initiate a command that is built-in than
+to create a separate process to run the command.
+Examples that fit this category are \f5test\fP
+and \f5pwd\fP.
+.P
+Given a command name \f5ksh\fP decides what it means using
+the following order:
+.BL
+.LI
+Reserved words define commands that form part of the shell
+grammar.
+They cannot be quoted.
+.LI
+Alias substitutions occur first as part of the reading of commands.
+Using quotes in the command name will prevent alias substitutions.
+.LI
+Special built-ins.
+.LI
+Functions.
+.LI
+Commands that are built-in that are not associated with a pathname
+such as \f5cd\fP and \f5print\fP.
+.LI
+If the command name contains a
+.BR / ,
+the program or script corresponding to the given name is executed.
+.LI
+A path search locates the pathname corresponding to the command.
+If the pathname where it is found matches the pathname associated
+with a built-in command, the built-in command is executed.
+If the directory where the command is found is listed in the
+.B \s-1FPATH\s+1
+variable, the file is read into the shell
+like a dot script, and a function by that name is invoked.
+Once a pathname is found, \f5ksh\fP remembers its location
+and only checks relative directories in \fB\s-1PATH\s+1\fP
+the next time the command name is used.
+Assigning a value to \fB\s-1PATH\s+1\fP
+causes \f5ksh\fP to forget the location of all command names.
+.LI
+The
+.B \s-1FPATH\s+1
+variable is searched and files found are treated as described above.
+.LE
+.P
+The first argument of the \f5command\fP built-in, described earlier,
+skips the checks for reserved words and for function definitions.
+In all other ways, \f5command\fP behaves like a built-in
+that is not associated with a pathname.
+As a result, if the first argument of \f5command\fP is
+a special built-in, the special properties of this built-in
+do not apply.
+For example, whereas, \f5exec\ 3<\ foo\fP will cause a script containing
+it to abort if the open fails, \f5command\ exec\ 3<\ foo\fP
+results in a non-zero exit status but does not abort the script.
+.P
+You can get a complete list of the special built-in commands
+with \f5builtin\ -s\fP.
+In addition \f5builtin\fP without arguments gives a list of
+the current built-ins and the pathname that they are associated with.
+A built-in can be bound to another pathname by giving
+the pathname for the built-in. The basename of this path must
+be the name of an existing built-in for this to succeed.
+Specifying the name of the built-in without a pathname causes
+this built-in to be found before a path search.
+A built-in can be deleted with the \fB\-d\fP option.
+.P
+On systems with run time loading of libraries, built-in commands
+can be added with the \f5builtin\fP command.
+Each command that is to be built-in must be written as a
+C function whose name is of the form \f5b_\fP\fIname\fP, where
+\fIname\fP is the name of the built-in that is to be added.
+The function has the same argument calling convention as
+\f5main\fP. The lower eight bits of the return value become
+the exit status for this built-in.
+Builtins are added by specifying the pathname of the library
+as an argument to the \fB\-f\fP option of \f5builtin\fP.
+.P
+The built-in command,
+\f5whence\fP,
+when used with the
+.B \-v
+option, tells how a given command is bound.
+A line is printed for each argument to \f5whence\fP
+telling what would happen if this argument were used as a command name.
+It reports on reserved words, aliases, built-ins, and
+functions.
+If the command is none of the above,
+it follows the path search rules and prints the full path-name,
+if any, otherwise it prints an error message.
+.H 2 "Symbolic Names"
+To avoid implementation dependencies, \f5ksh\fP
+accepts and generates symbolic names
+for built-ins that use numerical values in the Bourne shell.
+The
+.B \-S
+option of the
+\f5umask\fP built-in command
+accepts and displays
+default file creation permissions
+symbolically.
+It uses the same symbolic notation as the \f5chmod\fP command.
+.P
+The \f5trap\fP and \f5kill\fP built-in commands
+allows the signal names to be given symbolically.
+The names of signals and traps
+corresponding to signals are the same as the signal name with
+the
+.B \s-1SIG\s+1
+prefix removed.
+The trap
+.B 0
+is named
+\fB\s-1EXIT\s+1\fP.
+.H 2 "Additional Variables"
+In addition to the variables discussed earlier, \f5ksh\fP
+has other variables that it handles specially.
+The variable \fB\s-1RANDOM\s+1\fP
+produces a random number in the range 0 to 32767 each time it is referenced.
+Assignment to this variable sets the seed for the
+random number generator.
+.P
+The parameter \fB\s-1PPID\s+1\fP
+is used to generate the process id of the process which invoked this shell.
+.H 2 "Added Traps"
+A new trap named
+\fB\s-1ERR\s+1\fP
+has been added.
+This trap is invoked whenever the shell would exit if the
+.B \-e
+option were set.
+This trap is used by
+Fourth Generation Make\*(Rf
+.RS
+G. S. Fowler,
+.I "The Fourth Generation Make,"
+Proceedings of the Portland USENIX meeting, pp. 159-174, 1985.
+.RF
+which runs \f5ksh\fP
+as a co-process.
+.P
+A trap named
+\fB\s-1DEBUG\s+1\fP
+gets executed after each command.
+This trap can be used for debugging and other purposes.
+.P
+The
+\fB\s-1KEYBD\s+1\fP
+trap was described earlier.
+.H 2 Debugging
+The primary method for debugging Bourne shell scripts is to
+use the
+.B \-x
+option to enable the execution trace.
+After all
+the expansions have been performed,
+but before each command is executed,
+the trace writes to standard error the name and arguments
+of each command preceded by a
+.BR + .
+While the trace is very useful, there is no way
+to find out what line of source a given trace line
+corresponds to.
+With
+\f5ksh\fP
+the
+\fB\s-1PS4\s+1\fP
+variable
+is evaluated for parameter expansion and
+is displayed before each command,
+instead of the
+.BR + .
+.P
+The
+\fB\s-1LINENO\s+1\fP
+variable is set to the current line number relative to the
+beginning of the current script or function.
+It is most useful as part of the
+\fB\s-1PS4\s+1\fP
+prompt.
+.P
+The
+\fB\s-1DEBUG\s+1\fP
+trap can be used to write a break point shell
+debugger in \f5ksh\fP.
+An example of such a debugger is \f5kshdb\fP.\*(Rf
+.RS
+Bill Rosenblatt,
+.IR "Debugging Shell Scripts with \f5kshdb\fP" ,
+Unix World, Volume X, No. 5, 1993.
+.RF
+.H 2 "Timing Commands"
+.P
+Finding the time it takes to execute commands
+has been a serious problem with the Bourne shell.
+Since the \f5time\fP command is not part of the
+language, it is necessary to write a script
+in order to time a \f5for\fP or \f5while\fP loop.
+The extra time in invoking the shell and processing
+the script is accumulated along with the time
+to execute the script.
+.P
+More seriously, the Bourne shell does not give correct
+times for pipelines.
+The reason for this is that the times for some members
+of a pipeline are not counted when computing the time.
+As an extreme example,
+running \f5time\fP on the script
+.ce
+\f5cat < /dev/null | sort -u bigfile | wc\fP
+with the Bourne shell will show very little
+user and system time no matter how
+large \f5bigfile\fP is.
+.P
+To correct these problems,
+a reserved word \f5time\fP
+has been added to replace
+the \f5time\fP
+command.
+Any function, command or pipeline can be preceded by this reserved word
+to obtain information about the elapsed, user, and system times.
+Since I/O redirections bind to the command, not to
+\f5time\fP,
+parentheses should be used to redirect the timing information which
+is normally printed on file descriptor 2.
+.H 1 SECURITY
+There are several documented problems associated with the security of
+shell procedures\*(Rf.
+.RS
+F. T. Grampp and R. H. Morris,
+.I "UNIX Operating System Security,"
+AT&T Bell Labs Tech. Journal, Vol. 63, No. 8, Part 2, pp. 1649-1671, 1984.
+.RF
+These security holes occur primarily because a user can manipulate the
+.I environment
+to subvert the intent of a
+.I setuid
+shell procedure.
+Sometimes, shell procedures are initiated from
+binary programs, without the author's
+awareness, by library routines which invoke shells to carry out
+their tasks.
+When the binary program is run
+.I setuid
+then the shell procedure runs with the permissions afforded to the
+owner of the binary file.
+.P
+In the Bourne shell,
+the
+.B \s-1IFS\s+1
+parameter is used to split each word into separate command arguments.
+If a user knows that some
+.I setuid
+program will run
+\f5sh\ -c\ /bin/pwd\fP
+(or any other command in
+.BR /bin )
+then the user sets and exports
+.BR \s-1IFS\s+1=\^/ .
+Instead of running
+.B /bin/pwd
+the shell will run
+.B bin
+with
+.B pwd
+as an argument.
+The user puts his or her own \f5bin\fP
+program into the current directory.
+This program can
+create a copy of the shell,
+make this shell
+.IR setuid ,
+and then run the \f5/bin/pwd\fP
+program so that the original program continues to run successfully.
+This kind of penetration is not possible with
+\f5ksh\fP
+since the
+.B \s-1IFS\s+1
+parameter only splits arguments that result from command or parameter
+substitution.
+.P
+Some
+.I setuid
+programs run programs using
+.I system()
+without giving the full pathname.
+If the
+user sets the
+.B \s-1PATH\s+1
+variable so that the desired command will be found
+in his or her local bin, then the same technique described above can
+be employed to compromise the security of the system.
+To close up this and other security holes,
+\f5ksh\fP
+resets the effective user id to the real user id and the effective
+group id to the real group id unless the
+.I privileged
+option
+.RB ( \-p\^ )
+is specified at invocation.
+In
+this mode, the
+.B privileged
+mode, the
+.B .profile
+and
+.B \s-1ENV\s+1
+files are not processed.
+Instead, the file
+.B /etc/suid_profile
+is read and executed.
+This gives an administrator control over the
+environment to set the
+.B \s-1PATH\s+1
+variable or to log setuid shell invocations.
+Clearly security of the system is compromised if
+.B /etc
+or this file is publicly writable.
+.P
+Some versions of the UNIX operating system look for the characters
+\f5#!\fP
+as the first two characters of an executable file.
+If these characters are found, then the next word on this line is taken
+as the interpreter to
+invoke
+for this command and the interpreter is
+.IR exec ed
+with the name of the script as argument zero and argument one.
+If the
+.I setuid
+or
+.I setgid
+bits are on for this file, then the interpreter
+is run with the effective uid and/or gid set accordingly.
+This scheme has three major drawbacks.
+First of all,
+putting the pathname of the interpreter into the script
+makes the script less portable since the interpreter
+may be installed in a different directory on another system.
+Secondly, using the
+\f5#!\fP
+notation forces an
+.B exec
+of the interpreter even when the call is invoked from the interpreter
+which it must exec. This is inefficient since
+\f5ksh\fP can handle a failed exec much faster than starting up
+again.
+More importantly,
+.I setuid
+and
+.I setgid
+procedures provide an easy target for intrusion.
+By linking a
+.I setuid
+or
+.I setgid
+procedure to a name beginning with a
+.B \-
+the interpreter is fooled into thinking that it is being invoked with
+a command line option rather than the name of a file.
+When the interpreter is the shell, the user gets a privileged
+interactive shell.
+There is code in
+\f5ksh\fP
+to guard against this simple form of intrusion.
+.P
+A more reliable way to handle
+.I setuid
+and
+.I setgid
+procedures is provided with
+\f5ksh\fP.
+The technique does not require any changes to the operating system
+and provides better security.
+Another advantage to this method is that it also allows scripts which
+have execute permission but no read permission to run. Taking away read
+permission makes scripts more secure.
+.P
+The method relies on a setuid
+.B root
+program to authenticate the
+request and exec the shell with the correct mode bits to carry out
+the task. This shell is invoked with the requested file already open
+for reading. A script which cannot be opened for reading or which
+has its setuid and/or setgid bits turned on causes this setuid
+.B root
+program to get \fBexec\fPed.
+For security reasons, this program is given the full
+pathname
+\f5/etc/suid_exec\fP.
+A description of the implementation of the
+\f5/etc/suid_exec\fP
+program can be found in
+a separate paper\*(Rf.
+.RS
+D. G Korn
+.I "Parlez-vous Kanji?"
+TM-59554-860602-03, 1986.
+.RF
+.H 1 "CODE CHANGES"
+\f5ksh\fP is written in ANSI-C as a reusable library.
+The code can be compiled with C++ and older K&R C as well.
+The code uses the IEEE POSIX 1003.1 and ISO 9945-1 standard\*(Rf
+.RS
+.I "POSIX \- Part 1: System Application Program Interface,"
+IEEE Std 1003.1-1990, ISO/IEC 9945-1:1990.
+.RF
+wherever possible so that \f5ksh\fP should be able to run
+on any POSIX compliant system. In addition, it is possible
+to compile \f5ksh\fP for older systems.
+.P
+Unlike earlier version of the Bourne shell,
+\f5ksh\fP treats eight bit characters transparently
+without stripping off the
+leading bit.
+There is also a compile time switch to enable handling multi-byte
+and multi-width characters sets.
+.P
+On systems with dynamic libraries, it is possible to add built-in
+commands at run time with the built-in command \f5builtin\fP
+described earlier.
+It is also possible to embed \f5ksh\fP in applications in
+a manner analogous to \f5tcl\fP.
+.H 1 "EXAMPLE"
+.P
+An example of a \f5ksh\fP script is included
+in the Appendix.
+This one page program is a variant of the UNIX system
+\f5grep\fP(1) program.
+Pattern matching for this version of \f5grep\fP
+means shell patterns.
+.P
+The first half uses the \f5getopts\fP command to
+find the option flags.
+Nearly all options have been implemented.
+The second half goes through each line of each file
+to look for a pattern match.
+.P
+This program is not intended to serve as a
+replacement for \f5grep\fP
+which has been highly tuned for performance.
+It does
+illustrate the programming power of \f5ksh\fP.
+Note that no auxiliary processes are spawned by this script.
+It was written and debugged in under two hours.
+While performance is acceptable for small files,
+this program runs at only one tenth
+the speed of \f5grep\fP
+for large files.
+.H 1 "PERFORMANCE"
+.P
+\f5ksh\fP executes many scripts faster than the System V Bourne shell;
+in some cases more than 10 times as fast.
+The primary reason for this is that \f5ksh\fP creates fewer
+processes.
+The time to execute a built-in command or a function is one or two
+orders of magnitude faster than performing a \f5fork\fP() and
+\f5exec\fP() to create a separate process.
+Command substitution and commands inside parentheses
+are performed without creating another process, unless necessary
+to preserve correct behavior.
+.P
+Another reason for improved performance is the use of the \fBsfio\fP\*(Rf,
+.RS
+David Korn and Kiem-Phong Vo,
+.IR "SFIO - A Safe/Fast String/File I/O,"
+Proceedings of the Summer Usenix,
+pp. 235-255, 1991.
+.RF
+library for I/O. The \fBsfio\fP library buffers all I/O
+and buffers are flushed only when required.
+The algorithms used in \fBsfio\fP perform better than
+traditional versions of standard I/O so that programs that
+spend most of their time
+formatting output may actually perform better
+than versions written in C.
+.P
+Several of the internal algorithms have been changed
+so that the number of subroutine calls has been
+substantially reduced.
+\f5ksh\fP uses variable sized hash tables for variables.
+Scripts that rely heavily on referencing variables execute faster.
+More processing is performed while reading the script
+so that execution time is saved while running loops.
+These changes are not noticeable for scripts that \f5fork()\fP
+and run processes,
+but they reduce the time that it takes to interpret commands by
+more than a factor of two.
+.P
+Most importantly, \f5ksh\fP provide mechanisms to write applications
+that do not require as many processes.
+The arithmetic provided by the shell eliminates the need for the
+\f5expr\fP command.
+The pattern matching and substring capabilities eliminate the
+need to use \f5sed\fP or \f5awk\fP to process strings.
+.P
+The architecture of \f5ksh\fP makes it easy to make commands
+built-ins without changing the semantics at all.
+Systems that have run-time binding of libraries allow
+applications to be sped up by supplying the critical
+programs as shell built-in commands.
+Implementations on other systems can add built-in commands
+at compile time.
+The procedure for writing built-in commands that can be loaded
+at run time is in a separate document.\*(Rf,
+.RS
+David Korn,
+.IR "Guidelines for writing \f5ksh-93\fP built-in commands,"
+to be published, 1994.
+.RF
+.H 1 "CONCLUSION"
+.P
+The 1988 version of \f5ksh\fP has tens of thousands of regular users
+and is a suitable replacement for the Bourne shell.
+The 1993 version of \f5ksh\fP is essentially upward compatible with
+both the 1988 version of \f5ksh\fP and with the recent IEEE POSIX
+and ISO shell standard.
+The 1993 version offers many advantages for programming applications,
+and it has been rewritten so that it can be used in embedded applications.
+It also offers improved performance.
+.SG dgk \" signature typist initials
+\" .CS 14 24 38 0 0 16 \" cover sheet for TM
+.bp
+.ce
+\fIAPPENDIX\fP
+.nf
+\f5
+.ta .66i 1.33i 2i 2.66i 3.33i 4i 4.66i 5.33i 6i 6.66i 7.33i 8i
+.so grep.mm
+.fi
+\fP
+
+
diff --git a/src/cmd/ksh93/sh/args.c b/src/cmd/ksh93/sh/args.c
new file mode 100644
index 0000000..4d27580
--- /dev/null
+++ b/src/cmd/ksh93/sh/args.c
@@ -0,0 +1,892 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Rewritten by David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "path.h"
+#include "builtins.h"
+#include "terminal.h"
+#include "edit.h"
+#include "FEATURE/poll"
+#if SHOPT_KIA
+# include "shlex.h"
+# include "io.h"
+#endif /* SHOPT_KIA */
+#if SHOPT_PFSH
+# define PFSHOPT "P"
+#else
+# define PFSHOPT
+#endif
+#if SHOPT_BASH
+# define BASHOPT "\374"
+#else
+# define BASHOPT
+#endif
+#if SHOPT_HISTEXPAND
+# define HFLAG "H"
+#else
+# define HFLAG ""
+#endif
+
+#define SORT 1
+#define PRINT 2
+
+static char *null;
+
+/* The following order is determined by sh_optset */
+static const char optksh[] = PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
+static const int flagval[] =
+{
+#if SHOPT_PFSH
+ SH_PFSH,
+#endif
+#if SHOPT_BASH
+ SH_POSIX,
+#endif
+ SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
+ SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
+ SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
+ SH_NOUNSET, SH_VERBOSE, SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER,
+ SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL,
+#if SHOPT_HISTEXPAND
+ SH_HISTEXPAND,
+#endif
+ 0
+};
+
+#define NUM_OPTS (sizeof(flagval)/sizeof(*flagval))
+
+typedef struct _arg_
+{
+ Shell_t *sh;
+ struct dolnod *argfor; /* linked list of blocks to be cleaned up */
+ struct dolnod *dolh;
+ char flagadr[NUM_OPTS+1];
+#if SHOPT_KIA
+ char *kiafile;
+#endif /* SHOPT_KIA */
+} Arg_t;
+
+static int arg_expand(Shell_t*,struct argnod*,struct argnod**,int);
+static void sh_argset(Arg_t*, char *[]);
+
+
+/* ======== option handling ======== */
+
+void *sh_argopen(Shell_t *shp)
+{
+ void *addr = newof(0,Arg_t,1,0);
+ Arg_t *ap = (Arg_t*)addr;
+ ap->sh = shp;
+ return(addr);
+}
+
+static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+#if SHOPT_BASH
+ extern const char sh_bash1[], sh_bash2[];
+ if(strcmp(s,"bash1")==0)
+ {
+ if(sh_isoption(SH_BASH))
+ sfputr(sp,sh_bash1,-1);
+ }
+ else if(strcmp(s,"bash2")==0)
+ {
+ if(sh_isoption(SH_BASH))
+ sfputr(sp,sh_bash2,-1);
+ }
+ else if(*s==':' && sh_isoption(SH_BASH))
+ sfputr(sp,s,-1);
+ else
+#endif
+ if(*s!=':')
+ sfputr(sp,sh_set,-1);
+ return(1);
+}
+
+/*
+ * This routine turns options on and off
+ * The options "PDicr" are illegal from set command.
+ * The -o option is used to set option by name
+ * This routine returns the number of non-option arguments
+ */
+int sh_argopts(int argc,register char *argv[], void *context)
+{
+ Shell_t *shp = (Shell_t*)context;
+ register int n,o;
+ register Arg_t *ap = (Arg_t*)(shp->arg_context);
+ Lex_t *lp = (Lex_t*)(shp->lex_context);
+ Shopt_t newflags;
+ int setflag=0, action=0, trace=(int)sh_isoption(SH_XTRACE);
+ Namval_t *np = NIL(Namval_t*);
+ const char *cp;
+ int verbose,f;
+ Optdisc_t disc;
+ newflags=ap->sh->options;
+ memset(&disc, 0, sizeof(disc));
+ disc.version = OPT_VERSION;
+ disc.infof = infof;
+ opt_info.disc = &disc;
+
+ if(argc>0)
+ setflag = 4;
+ else
+ argc = -argc;
+ while((n = optget(argv,setflag?sh_optset:sh_optksh)))
+ {
+ o=0;
+ f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
+ switch(n)
+ {
+ case 'A':
+ np = nv_open(opt_info.arg,ap->sh->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
+ if(f)
+ nv_unset(np);
+ continue;
+#if SHOPT_BASH
+ case 'O': /* shopt options, only in bash mode */
+ if(!sh_isoption(SH_BASH))
+ errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
+#endif
+ case 'o': /* set options */
+ byname:
+ if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
+ {
+ action = PRINT;
+ /* print style: -O => shopt options
+ * bash => print unset options also, no heading
+ */
+ verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
+ (n=='O'?PRINT_SHOPT:0)|
+ (sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
+ ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
+ continue;
+ }
+ o = sh_lookopt(opt_info.arg,&f);
+ if(o<=0
+ || (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA))
+ || ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))
+
+ || (setflag && (o&SH_COMMANDLINE)))
+ {
+ errormsg(SH_DICT,2, e_option, opt_info.arg);
+ error_info.errors++;
+ }
+ o &= 0xff;
+ if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
+ errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
+ break;
+#if SHOPT_BASH
+ case -1: /* --rcfile */
+ ap->sh->gd->rcfile = opt_info.arg;
+ continue;
+ case -2: /* --noediting */
+ if (!f)
+ {
+ off_option(&newflags,SH_VI);
+ off_option(&newflags,SH_EMACS);
+ off_option(&newflags,SH_GMACS);
+ }
+ continue;
+ case -3: /* --profile */
+ n = 'l';
+ goto skip;
+ case -4: /* --posix */
+ /* mask lower 8 bits to find char in optksh string */
+ n&=0xff;
+ goto skip;
+ case -5: /* --version */
+ sfputr(sfstdout, "ksh bash emulation, version ",-1);
+ np = nv_open("BASH_VERSION",ap->sh->var_tree,0);
+ sfputr(sfstdout, nv_getval(np),-1);
+ np = nv_open("MACHTYPE",ap->sh->var_tree,0);
+ sfprintf(sfstdout, " (%s)\n", nv_getval(np));
+ sh_exit(0);
+#endif
+ case -6: /* --default */
+ {
+ register const Shtable_t *tp;
+ for(tp=shtab_options; o = tp->sh_number; tp++)
+ if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
+ off_option(&newflags,o&0xff);
+ }
+ continue;
+ case -7:
+ f = 0;
+ goto byname;
+ case 'D':
+ on_option(&newflags,SH_NOEXEC);
+ goto skip;
+ case 'T':
+ if (opt_info.num)
+ ap->sh->test |= opt_info.num;
+ else
+ ap->sh->test = 0;
+ continue;
+ case 's':
+ if(setflag)
+ {
+ action = SORT;
+ continue;
+ }
+#if SHOPT_KIA
+ goto skip;
+ case 'R':
+ if(setflag)
+ n = ':';
+ else
+ {
+ ap->kiafile = opt_info.arg;
+ n = 'n';
+ }
+ /*FALLTHROUGH*/
+#endif /* SHOPT_KIA */
+#if SHOPT_REGRESS
+ goto skip;
+ case 'I':
+ continue;
+#endif /* SHOPT_REGRESS */
+ skip:
+ default:
+ if(cp=strchr(optksh,n))
+ o = flagval[cp-optksh];
+ break;
+ case ':':
+ if(opt_info.name[0]=='-'&&opt_info.name[1]=='-')
+ {
+ opt_info.arg = argv[opt_info.index-1] + 2;
+ f = 1;
+ goto byname;
+ }
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(-1);
+ }
+ if(f)
+ {
+ if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
+ {
+ off_option(&newflags,SH_VI);
+ off_option(&newflags,SH_EMACS);
+ off_option(&newflags,SH_GMACS);
+ }
+ on_option(&newflags,o);
+ off_option(&ap->sh->offoptions,o);
+ }
+ else
+ {
+ if(o==SH_XTRACE)
+ trace = 0;
+ off_option(&newflags,o);
+ if(setflag==0)
+ on_option(&ap->sh->offoptions,o);
+ }
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ /* check for '-' or '+' argument */
+ if((cp=argv[opt_info.index]) && cp[1]==0 && (*cp=='+' || *cp=='-') &&
+ strcmp(argv[opt_info.index-1],"--"))
+ {
+ opt_info.index++;
+ off_option(&newflags,SH_XTRACE);
+ off_option(&newflags,SH_VERBOSE);
+ trace = 0;
+ }
+ if(trace)
+ sh_trace(shp,argv,1);
+ argc -= opt_info.index;
+ argv += opt_info.index;
+ if(action==PRINT)
+ sh_printopts(newflags,verbose,0);
+ if(setflag)
+ {
+ if(action==SORT)
+ {
+ if(argc>0)
+ strsort(argv,argc,strcoll);
+ else
+ strsort(ap->sh->st.dolv+1,ap->sh->st.dolc,strcoll);
+ }
+ if(np)
+ {
+ nv_setvec(np,0,argc,argv);
+ nv_close(np);
+ }
+ else if(argc>0 || ((cp=argv[-1]) && strcmp(cp,"--")==0))
+ sh_argset(ap,argv-1);
+ }
+ else if(is_option(&newflags,SH_CFLAG))
+ {
+ if(!(ap->sh->comdiv = *argv++))
+ {
+ errormsg(SH_DICT,2,e_cneedsarg);
+ errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
+ }
+ argc--;
+ }
+ /* handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
+ * sh_applyopts(), so that the code can be reused from b_shopt(), too
+ */
+ sh_applyopts(ap->sh,newflags);
+#if SHOPT_KIA
+ if(ap->kiafile)
+ {
+ if(!argv[0])
+ errormsg(SH_DICT,ERROR_usage(2),"-R requires scriptname");
+ if(!(lp->kiafile=sfopen(NIL(Sfio_t*),ap->kiafile,"w+")))
+ errormsg(SH_DICT,ERROR_system(3),e_create,ap->kiafile);
+ if(!(lp->kiatmp=sftmp(2*SF_BUFSIZE)))
+ errormsg(SH_DICT,ERROR_system(3),e_tmpcreate);
+ sfputr(lp->kiafile,";vdb;CIAO/ksh",'\n');
+ lp->kiabegin = sftell(lp->kiafile);
+ lp->entity_tree = dtopen(&_Nvdisc,Dtbag);
+ lp->scriptname = strdup(sh_fmtq(argv[0]));
+ lp->script=kiaentity(lp,lp->scriptname,-1,'p',-1,0,0,'s',0,"");
+ lp->fscript=kiaentity(lp,lp->scriptname,-1,'f',-1,0,0,'s',0,"");
+ lp->unknown=kiaentity(lp,"<unknown>",-1,'p',-1,0,0,'0',0,"");
+ kiaentity(lp,"<unknown>",-1,'p',0,0,lp->unknown,'0',0,"");
+ lp->current = lp->script;
+ ap->kiafile = 0;
+ }
+#endif /* SHOPT_KIA */
+ return(argc);
+}
+
+/* apply new options */
+
+void sh_applyopts(Shell_t* shp,Shopt_t newflags)
+{
+ /* cannot set -n for interactive shells since there is no way out */
+ if(sh_isoption(SH_INTERACTIVE))
+ off_option(&newflags,SH_NOEXEC);
+ if(is_option(&newflags,SH_PRIVILEGED))
+ on_option(&newflags,SH_NOUSRPROFILE);
+ if(!sh_isstate(SH_INIT) && is_option(&newflags,SH_PRIVILEGED) != sh_isoption(SH_PRIVILEGED) || sh_isstate(SH_INIT) && is_option(&((Arg_t*)shp->arg_context)->sh->offoptions,SH_PRIVILEGED) && shp->gd->userid!=shp->gd->euserid)
+ {
+ if(!is_option(&newflags,SH_PRIVILEGED))
+ {
+ setuid(shp->gd->userid);
+ setgid(shp->gd->groupid);
+ if(shp->gd->euserid==0)
+ {
+ shp->gd->euserid = shp->gd->userid;
+ shp->gd->egroupid = shp->gd->groupid;
+ }
+ }
+ else if((shp->gd->userid!=shp->gd->euserid && setuid(shp->gd->euserid)<0) ||
+ (shp->gd->groupid!=shp->gd->egroupid && setgid(shp->gd->egroupid)<0) ||
+ (shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid))
+ off_option(&newflags,SH_PRIVILEGED);
+ }
+#if SHOPT_BASH
+ on_option(&newflags,SH_CMDHIST);
+ on_option(&newflags,SH_CHECKHASH);
+ on_option(&newflags,SH_EXECFAIL);
+ on_option(&newflags,SH_EXPAND_ALIASES);
+ on_option(&newflags,SH_HISTAPPEND);
+ on_option(&newflags,SH_INTERACTIVE_COMM);
+ on_option(&newflags,SH_LITHIST);
+ on_option(&newflags,SH_NOEMPTYCMDCOMPL);
+
+ if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO))
+ astconf("UNIVERSE", 0, "ucb");
+ if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO))
+ astconf("UNIVERSE", 0, "att");
+ if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL))
+ astconf("PATH_RESOLVE", 0, "metaphysical");
+ if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL))
+ astconf("PATH_RESOLVE", 0, "physical");
+ if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2))
+ {
+ sh_onstate(SH_HISTORY);
+ sh_onoption(SH_HISTORY);
+ }
+ if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2))
+ {
+ sh_offstate(SH_HISTORY);
+ sh_offoption(SH_HISTORY);
+ }
+#endif
+ shp->options = newflags;
+}
+
+/*
+ * returns the value of $-
+ */
+char *sh_argdolminus(void* context)
+{
+ register Arg_t *ap = (Arg_t*)context;
+ register const char *cp=optksh;
+ register char *flagp=ap->flagadr;
+ while(cp< &optksh[NUM_OPTS])
+ {
+ int n = flagval[cp-optksh];
+ if(sh_isoption(n))
+ *flagp++ = *cp;
+ cp++;
+ }
+ *flagp = 0;
+ return(ap->flagadr);
+}
+
+/*
+ * set up positional parameters
+ */
+static void sh_argset(Arg_t *ap,char *argv[])
+{
+ sh_argfree(ap->sh,ap->dolh,0);
+ ap->dolh = sh_argcreate(argv);
+ /* link into chain */
+ ap->dolh->dolnxt = ap->argfor;
+ ap->argfor = ap->dolh;
+ ap->sh->st.dolc = ap->dolh->dolnum-1;
+ ap->sh->st.dolv = ap->dolh->dolval;
+}
+
+/*
+ * free the argument list if the use count is 1
+ * If count is greater than 1 decrement count and return same blk
+ * Free the argument list if the use count is 1 and return next blk
+ * Delete the blk from the argfor chain
+ * If flag is set, then the block dolh is not freed
+ */
+struct dolnod *sh_argfree(Shell_t *shp, struct dolnod *blk,int flag)
+{
+ register struct dolnod* argr=blk;
+ register struct dolnod* argblk;
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ if(argblk=argr)
+ {
+ if((--argblk->dolrefcnt)==0)
+ {
+ argr = argblk->dolnxt;
+ if(flag && argblk==ap->dolh)
+ ap->dolh->dolrefcnt = 1;
+ else
+ {
+ /* delete from chain */
+ if(ap->argfor == argblk)
+ ap->argfor = argblk->dolnxt;
+ else
+ {
+ for(argr=ap->argfor;argr;argr=argr->dolnxt)
+ if(argr->dolnxt==argblk)
+ break;
+ if(!argr)
+ return(NIL(struct dolnod*));
+ argr->dolnxt = argblk->dolnxt;
+ argr = argblk->dolnxt;
+ }
+ free((void*)argblk);
+ }
+ }
+ }
+ return(argr);
+}
+
+/*
+ * grab space for arglist and copy args
+ * The strings are copied after the argment vector
+ */
+struct dolnod *sh_argcreate(register char *argv[])
+{
+ register struct dolnod *dp;
+ register char **pp=argv, *sp;
+ register int size=0,n;
+ /* count args and number of bytes of arglist */
+ while(sp= *pp++)
+ size += strlen(sp);
+ n = (pp - argv)-1;
+ dp=new_of(struct dolnod,n*sizeof(char*)+size+n);
+ dp->dolrefcnt=1; /* use count */
+ dp->dolnum = n;
+ dp->dolnxt = 0;
+ pp = dp->dolval;
+ sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*);
+ while(n--)
+ {
+ *pp++ = sp;
+ sp = strcopy(sp, *argv++) + 1;
+ }
+ *pp = NIL(char*);
+ return(dp);
+}
+
+/*
+ * used to set new arguments for functions
+ */
+struct dolnod *sh_argnew(Shell_t *shp,char *argi[], struct dolnod **savargfor)
+{
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ register struct dolnod *olddolh = ap->dolh;
+ *savargfor = ap->argfor;
+ ap->dolh = 0;
+ ap->argfor = 0;
+ sh_argset(ap,argi);
+ return(olddolh);
+}
+
+/*
+ * reset arguments as they were before function
+ */
+void sh_argreset(Shell_t *shp,struct dolnod *blk, struct dolnod *afor)
+{
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ while(ap->argfor=sh_argfree(shp,ap->argfor,0));
+ ap->argfor = afor;
+ if(ap->dolh = blk)
+ {
+ shp->st.dolc = ap->dolh->dolnum-1;
+ shp->st.dolv = ap->dolh->dolval;
+ }
+}
+
+/*
+ * increase the use count so that an sh_argset will not make it go away
+ */
+struct dolnod *sh_arguse(Shell_t* shp)
+{
+ register struct dolnod *dh;
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ if(dh=ap->dolh)
+ dh->dolrefcnt++;
+ return(dh);
+}
+
+/*
+ * Print option settings on standard output
+ * if mode is inclusive or of PRINT_*
+ * if <mask> is set, only options with this mask value are displayed
+ */
+void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
+{
+ register const Shtable_t *tp;
+ const char *name;
+ int on;
+ int value;
+ if(!(mode&PRINT_NO_HEADER))
+ sfputr(sfstdout,sh_translate(e_heading),'\n');
+ if(mode&PRINT_TABLE)
+ {
+ int w;
+ int c;
+ int r;
+ int i;
+
+ c = 0;
+ for(tp=shtab_options; value=tp->sh_number; tp++)
+ {
+ if(mask && !is_option(mask,value&0xff))
+ continue;
+ name = tp->sh_name;
+ if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
+ name += 2;
+ if(c<(w=strlen(name)))
+ c = w;
+ }
+ c += 4;
+ if((w = ed_window()) < (2*c))
+ w = 2*c;
+ r = w / c;
+ i = 0;
+ for(tp=shtab_options; value=tp->sh_number; tp++)
+ {
+ if(mask && !is_option(mask,value&0xff))
+ continue;
+ on = !!is_option(&oflags,value);
+ value &= 0xff;
+ name = tp->sh_name;
+ if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
+ {
+ name += 2;
+ on = !on;
+ }
+ if(++i>=r)
+ {
+ i = 0;
+ sfprintf(sfstdout, "%s%s\n", on ? "" : "no", name);
+ }
+ else
+ sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c-2), name);
+ }
+ if(i)
+ sfputc(sfstdout,'\n');
+ return;
+ }
+#if SHOPT_RAWONLY
+ on_option(&oflags,SH_VIRAW);
+#endif
+ if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
+ {
+ if(mode&PRINT_SHOPT)
+ sfwrite(sfstdout,"shopt -s",3);
+ else
+ sfwrite(sfstdout,"set --default",13);
+ }
+ for(tp=shtab_options; value=tp->sh_number; tp++)
+ {
+ if(mask && !is_option(mask,value&0xff))
+ continue;
+ if(sh_isoption(SH_BASH))
+ {
+ if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT))
+ continue;
+ }
+ else if (value&(SH_BASHEXTRA|SH_BASHOPT))
+ continue;
+ on = !!is_option(&oflags,value);
+ name = tp->sh_name;
+ if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
+ {
+ name += 2;
+ on = !on;
+ }
+ if(mode&PRINT_VERBOSE)
+ {
+ sfputr(sfstdout,name,' ');
+ sfnputc(sfstdout,' ',24-strlen(name));
+ sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
+ }
+ else if(mode&PRINT_ALL) /* print unset options also */
+ {
+ if(mode&PRINT_SHOPT)
+ sfprintf(sfstdout, "shopt -%c %s\n",
+ on?'s':'u',
+ name);
+ else
+ sfprintf(sfstdout, "set %co %s\n",
+ on?'-':'+',
+ name);
+ }
+ else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff))
+ sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name);
+ }
+ if(!(mode&(PRINT_VERBOSE|PRINT_ALL)))
+ sfputc(sfstdout,'\n');
+}
+
+/*
+ * build an argument list
+ */
+char **sh_argbuild(Shell_t *shp,int *nargs, const struct comnod *comptr,int flag)
+{
+ register struct argnod *argp;
+ struct argnod *arghead=0;
+ shp->xargmin = 0;
+ {
+ register const struct comnod *ac = comptr;
+ register int n;
+ /* see if the arguments have already been expanded */
+ if(!ac->comarg)
+ {
+ *nargs = 0;
+ return(&null);
+ }
+ else if(!(ac->comtyp&COMSCAN))
+ {
+ register struct dolnod *ap = (struct dolnod*)ac->comarg;
+ *nargs = ap->dolnum;
+ return(ap->dolval+ap->dolbot);
+ }
+ shp->lastpath = 0;
+ *nargs = 0;
+ if(ac)
+ {
+ if(ac->comnamp == SYSLET)
+ flag |= ARG_LET;
+ argp = ac->comarg;
+ while(argp)
+ {
+ n = arg_expand(shp,argp,&arghead,flag);
+ if(n>1)
+ {
+ if(shp->xargmin==0)
+ shp->xargmin = *nargs;
+ shp->xargmax = *nargs+n;
+ }
+ *nargs += n;
+ argp = argp->argnxt.ap;
+ }
+ argp = arghead;
+ }
+ }
+ {
+ register char **comargn;
+ register int argn;
+ register char **comargm;
+ argn = *nargs;
+ /* allow room to prepend args */
+ argn += 1;
+
+ comargn=(char**)stkalloc(shp->stk,(unsigned)(argn+1)*sizeof(char*));
+ comargm = comargn += argn;
+ *comargn = NIL(char*);
+ if(!argp)
+ {
+ /* reserve an extra null pointer */
+ *--comargn = 0;
+ return(comargn);
+ }
+ while(argp)
+ {
+ struct argnod *nextarg = argp->argchn.ap;
+ argp->argchn.ap = 0;
+ *--comargn = argp->argval;
+ if(!(argp->argflag&ARG_RAW))
+ sh_trim(*comargn);
+ if(!(argp=nextarg) || (argp->argflag&ARG_MAKE))
+ {
+ if((argn=comargm-comargn)>1)
+ strsort(comargn,argn,strcoll);
+ comargm = comargn;
+ }
+ }
+ shp->last_table = 0;
+ return(comargn);
+ }
+}
+
+#if _pipe_socketpair && !_socketpair_devfd
+# define sh_pipe arg_pipe
+/*
+ * create a real pipe (not a socket) and print message on failure
+ */
+static int arg_pipe(register int pv[])
+{
+ Shell_t *shp = sh_getinterp();
+ int fd[2];
+ if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ pv[0] = sh_iomovefd(pv[0]);
+ pv[1] = sh_iomovefd(pv[1]);
+ shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
+ shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
+ sh_subsavefd(pv[0]);
+ sh_subsavefd(pv[1]);
+ return(0);
+}
+#endif
+
+struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
+{
+ /* argument of the form <(cmd) or >(cmd) */
+ register struct argnod *ap;
+ int monitor, fd, pv[3];
+ int subshell = shp->subshell;
+ ap = (struct argnod*)stkseek(shp->stk,ARGVAL);
+ ap->argflag |= ARG_MAKE;
+ ap->argflag &= ~ARG_RAW;
+ fd = argp->argflag&ARG_RAW;
+ if(fd==0 && shp->subshell)
+ sh_subtmpfile(shp);
+#if SHOPT_DEVFD
+ sfwrite(shp->stk,e_devfdNN,8);
+ pv[2] = 0;
+ sh_pipe(pv);
+#else
+ pv[0] = -1;
+ shp->fifo = pathtemp(0,0,0,"ksh.fifo",0);
+ mkfifo(shp->fifo,S_IRUSR|S_IWUSR);
+ sfputr(shp->stk,shp->fifo,0);
+#endif /* SHOPT_DEVFD */
+ sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
+ ap = (struct argnod*)stkfreeze(shp->stk,0);
+ shp->inpipe = shp->outpipe = 0;
+ if(monitor = (sh_isstate(SH_MONITOR)!=0))
+ sh_offstate(SH_MONITOR);
+ shp->subshell = 0;
+ if(fd)
+ {
+ shp->inpipe = pv;
+ sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
+ }
+ else
+ {
+ shp->outpipe = pv;
+ sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
+ }
+ shp->subshell = subshell;
+ if(monitor)
+ sh_onstate(SH_MONITOR);
+#if SHOPT_DEVFD
+ close(pv[1-fd]);
+ sh_iosave(shp,-pv[fd], shp->topfd, (char*)0);
+#else
+ free(shp->fifo);
+ shp->fifo = 0;
+#endif /* SHOPT_DEVFD */
+ return(ap);
+}
+
+/* Argument expansion */
+static int arg_expand(Shell_t *shp,register struct argnod *argp, struct argnod **argchain,int flag)
+{
+ register int count = 0;
+ argp->argflag &= ~ARG_MAKE;
+ if(*argp->argval==0 && (argp->argflag&ARG_EXP))
+ {
+ struct argnod *ap;
+ ap = sh_argprocsub(shp,argp);
+ ap->argchn.ap = *argchain;
+ *argchain = ap;
+ count++;
+ }
+ else
+ if(!(argp->argflag&ARG_RAW))
+ {
+#if SHOPT_OPTIMIZE
+ struct argnod *ap;
+ sh_stats(STAT_ARGEXPAND);
+ if(flag&ARG_OPTIMIZE)
+ argp->argchn.ap=0;
+ if(ap=argp->argchn.ap)
+ {
+ sh_stats(STAT_ARGHITS);
+ count = 1;
+ ap->argchn.ap = *argchain;
+ ap->argflag |= ARG_RAW;
+ ap->argflag &= ~ARG_EXP;
+ *argchain = ap;
+ }
+ else
+#endif /* SHOPT_OPTIMIZE */
+ count = sh_macexpand(shp,argp,argchain,flag);
+ }
+ else
+ {
+ argp->argchn.ap = *argchain;
+ *argchain = argp;
+ argp->argflag |= ARG_MAKE;
+ count++;
+ }
+ return(count);
+}
+
diff --git a/src/cmd/ksh93/sh/arith.c b/src/cmd/ksh93/sh/arith.c
new file mode 100644
index 0000000..f1814fa
--- /dev/null
+++ b/src/cmd/ksh93/sh/arith.c
@@ -0,0 +1,549 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Shell arithmetic - uses streval library
+ * David Korn
+ * AT&T Labs
+ */
+
+#include "defs.h"
+#include "lexstates.h"
+#include "name.h"
+#include "streval.h"
+#include "variables.h"
+#include "builtins.h"
+
+#ifndef LLONG_MAX
+#define LLONG_MAX LONG_MAX
+#endif
+
+typedef Sfdouble_t (*Math_f)(Sfdouble_t, ...);
+
+extern const Namdisc_t ENUM_disc;
+static Sfdouble_t NaN, Inf, Fun;
+static Namval_t Infnod =
+{
+ { 0 },
+ "Inf",
+ NV_NOFREE|NV_LDOUBLE,NV_RDONLY
+};
+
+static Namval_t NaNnod =
+{
+ { 0 },
+ "NaN",
+ NV_NOFREE|NV_LDOUBLE,NV_RDONLY
+};
+
+static Namval_t FunNode =
+{
+ { 0 },
+ "?",
+ NV_NOFREE|NV_LDOUBLE,NV_RDONLY
+};
+
+static Namval_t *scope(register Namval_t *np,register struct lval *lvalue,int assign)
+{
+ register int flag = lvalue->flag;
+ register char *sub=0, *cp=(char*)np;
+ register Namval_t *mp;
+ Shell_t *shp = lvalue->shp;
+ int flags = HASH_NOSCOPE|HASH_SCOPE|HASH_BUCKET;
+ int c=0,nosub = lvalue->nosub;
+ Dt_t *sdict = (shp->st.real_fun? shp->st.real_fun->sdict:0);
+ Dt_t *nsdict = (shp->namespace?nv_dict(shp->namespace):0);
+ Dt_t *root = shp->var_tree;
+ assign = assign?NV_ASSIGN:NV_NOASSIGN;
+ lvalue->nosub = 0;
+ if(nosub<0 && lvalue->ovalue)
+ return((Namval_t*)lvalue->ovalue);
+ lvalue->ovalue = 0;
+ if(cp>=lvalue->expr && cp < lvalue->expr+lvalue->elen)
+ {
+ int offset;
+ /* do binding to node now */
+ int c = cp[flag];
+ cp[flag] = 0;
+ if((!(np = nv_open(cp,shp->var_tree,assign|NV_VARNAME|NV_NOADD|NV_NOFAIL)) || nv_isnull(np)) && sh_macfun(shp,cp, offset = staktell()))
+ {
+ Fun = sh_arith(shp,sub=stakptr(offset));
+ FunNode.nvalue.ldp = &Fun;
+ cp[flag] = c;
+ return(&FunNode);
+ }
+ if(!np && assign)
+ np = nv_open(cp,shp->var_tree,assign|NV_VARNAME);
+ cp[flag] = c;
+ if(!np)
+ return(0);
+ root = shp->last_root;
+ if(cp[flag+1]=='[')
+ flag++;
+ else
+ flag = 0;
+ cp = (char*)np;
+ }
+ else if(assign==NV_ASSIGN && nv_isnull(np) && !nv_isattr(np, ~(NV_MINIMAL|NV_NOFREE)))
+ flags |= NV_ADD;
+ if((lvalue->emode&ARITH_COMP) && dtvnext(root) && ((sdict && (mp=nv_search(cp,sdict,flags&~NV_ADD))) || (mp=nv_search(cp,root,flags&~(NV_ADD))) || (nsdict && (mp=nv_search(cp,nsdict,flags&~(NV_ADD|HASH_NOSCOPE)))) ))
+ np = mp;
+ while(nv_isref(np))
+ {
+#if SHOPT_FIXEDARRAY
+ int n,dim;
+ dim = nv_refdimen(np);
+ n = nv_refindex(np);
+#endif /* SHOPT_FIXEDARRAY */
+ sub = nv_refsub(np);
+ np = nv_refnode(np);
+#if SHOPT_FIXEDARRAY
+ if(n)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ ap->nelem = dim;
+ nv_putsub(np,(char*)0,n);
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(sub)
+ nv_putsub(np,sub,assign==NV_ASSIGN?ARRAY_ADD:0);
+ }
+ if(!nosub && flag)
+ {
+ int hasdot = 0;
+ cp = (char*)&lvalue->expr[flag];
+ if(sub)
+ {
+ goto skip;
+ }
+ sub = cp;
+ while(1)
+ {
+ Namarr_t *ap;
+ Namval_t *nq;
+ cp = nv_endsubscript(np,cp,0);
+ if(c || *cp=='.')
+ {
+ c = '.';
+ while(*cp=='.')
+ {
+ hasdot=1;
+ cp++;
+ while(c=mbchar(cp),isaname(c));
+ }
+ if(c=='[')
+ continue;
+ }
+ flag = *cp;
+ *cp = 0;
+ if(c || hasdot)
+ {
+ sfprintf(shp->strbuf,"%s%s%c",nv_name(np),sub,0);
+ sub = sfstruse(shp->strbuf);
+ }
+ if(strchr(sub,'$'))
+ sub = sh_mactrim(shp,sub,0);
+ *cp = flag;
+ if(c || hasdot)
+ {
+ np = nv_open(sub,shp->var_tree,NV_VARNAME|assign);
+ return(np);
+ }
+#if SHOPT_FIXEDARRAY
+ ap = nv_arrayptr(np);
+ cp = nv_endsubscript(np,sub,NV_ADD|NV_SUBQUOTE|(ap&&ap->fixed?NV_FARRAY:0));
+#else
+ cp = nv_endsubscript(np,sub,NV_ADD|NV_SUBQUOTE);
+#endif /* SHOPT_FIXEDARRAY */
+ if(*cp!='[')
+ break;
+ skip:
+ if(nq = nv_opensub(np))
+ np = nq;
+ else
+ {
+ ap = nv_arrayptr(np);
+ if(ap && !ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap && ap->table && (nq=nv_search(nv_getsub(np),ap->table,NV_ADD)))
+ nq->nvenv = (char*)np;
+ if(nq && nv_isnull(nq))
+ np = nv_arraychild(np,nq,0);
+ }
+ sub = cp;
+ }
+ }
+ else if(nosub>0)
+ nv_putsub(np,(char*)0,nosub-1);
+ return(np);
+}
+
+static Math_f sh_mathstdfun(const char *fname, size_t fsize, short * nargs)
+{
+ register const struct mathtab *tp;
+ register char c = fname[0];
+ for(tp=shtab_math; *tp->fname; tp++)
+ {
+ if(*tp->fname > c)
+ break;
+ if(tp->fname[1]==c && tp->fname[fsize+1]==0 && strncmp(&tp->fname[1],fname,fsize)==0)
+ {
+ if(nargs)
+ *nargs = *tp->fname;
+ return(tp->fnptr);
+ }
+ }
+ return(0);
+}
+
+int sh_mathstd(const char *name)
+{
+ return(sh_mathstdfun(name,strlen(name),NULL)!=0);
+}
+
+static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdouble_t n)
+{
+ Shell_t *shp = lvalue->shp;
+ register Sfdouble_t r= 0;
+ char *str = (char*)*ptr;
+ register char *cp;
+ switch(type)
+ {
+ case ASSIGN:
+ {
+ register Namval_t *np = (Namval_t*)(lvalue->value);
+ np = scope(np,lvalue,1);
+ nv_putval(np, (char*)&n, NV_LDOUBLE);
+ if(lvalue->eflag)
+ lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
+ lvalue->eflag = 0;
+ r=nv_getnum(np);
+ lvalue->value = (char*)np;
+ break;
+ }
+ case LOOKUP:
+ {
+ register int c = *str;
+ register char *xp=str;
+ lvalue->value = (char*)0;
+ if(c=='.')
+ str++;
+ c = mbchar(str);
+ if(isaletter(c))
+ {
+ register Namval_t *np;
+ int dot=0;
+ while(1)
+ {
+ while(xp=str, c=mbchar(str), isaname(c));
+ str = xp;
+ while(c=='[' && dot==NV_NOADD)
+ {
+ str = nv_endsubscript((Namval_t*)0,str,0);
+ c = *str;
+ }
+ if(c!='.')
+ break;
+ dot=NV_NOADD;
+ if((c = *++str) !='[')
+ continue;
+ str = nv_endsubscript((Namval_t*)0,cp=str,NV_SUBQUOTE)-1;
+ if(sh_checkid(cp+1,(char*)0))
+ str -=2;
+ }
+ if(c=='(')
+ {
+ int off=stktell(shp->stk);
+ int fsize = str- (char*)(*ptr);
+ const struct mathtab *tp;
+ Namval_t *np;
+ c = **ptr;
+ lvalue->fun = 0;
+ sfprintf(shp->stk,".sh.math.%.*s%c",fsize,*ptr,0);
+ stkseek(shp->stk,off);
+ if(np=nv_search(stkptr(shp->stk,off),shp->fun_tree,0))
+ {
+ lvalue->nargs = -np->nvalue.rp->argc;
+ lvalue->fun = (Math_f)np;
+ break;
+ }
+ if(fsize<=(sizeof(tp->fname)-2))
+ lvalue->fun = (Math_f)sh_mathstdfun(*ptr,fsize,&lvalue->nargs);
+ if(lvalue->fun)
+ break;
+ if(lvalue->emode&ARITH_COMP)
+ lvalue->value = (char*)e_function;
+ else
+ lvalue->value = (char*)ERROR_dictionary(e_function);
+ return(r);
+ }
+ if((lvalue->emode&ARITH_COMP) && dot)
+ {
+ lvalue->value = (char*)*ptr;
+ lvalue->flag = str-lvalue->value;
+ break;
+ }
+ *str = 0;
+ if(sh_isoption(SH_NOEXEC))
+ np = L_ARGNOD;
+ else
+ {
+ int offset = staktell();
+ char *saveptr = stakfreeze(0);
+ Dt_t *root = (lvalue->emode&ARITH_COMP)?shp->var_base:shp->var_tree;
+ *str = c;
+ cp = str;
+ while(c=='[' || c=='.')
+ {
+ if(c=='[')
+ {
+ str = nv_endsubscript(np,str,0);
+ if((c= *str)!='[' && c!='.')
+ {
+ str = cp;
+ c = '[';
+ break;
+ }
+ }
+ else
+ {
+ dot = NV_NOADD|NV_NOFAIL;
+ str++;
+ while(xp=str, c=mbchar(str), isaname(c));
+ str = xp;
+ }
+ }
+ *str = 0;
+ cp = (char*)*ptr;
+ if ((cp[0] == 'i' || cp[0] == 'I') && (cp[1] == 'n' || cp[1] == 'N') && (cp[2] == 'f' || cp[2] == 'F') && cp[3] == 0)
+ {
+ Inf = strtold("Inf", NiL);
+ Infnod.nvalue.ldp = &Inf;
+ np = &Infnod;
+ }
+ else if ((cp[0] == 'n' || cp[0] == 'N') && (cp[1] == 'a' || cp[1] == 'A') && (cp[2] == 'n' || cp[2] == 'N') && cp[3] == 0)
+ {
+ NaN = strtold("NaN", NiL);
+ NaNnod.nvalue.ldp = &NaN;
+ np = &NaNnod;
+ }
+ else if(!(np = nv_open(*ptr,root,NV_NOREF|NV_NOASSIGN|NV_VARNAME|dot)))
+ {
+ lvalue->value = (char*)*ptr;
+ lvalue->flag = str-lvalue->value;
+ }
+ if(saveptr != stakptr(0))
+ stakset(saveptr,offset);
+ else
+ stakseek(offset);
+ }
+ *str = c;
+ if(!np && lvalue->value)
+ break;
+ lvalue->value = (char*)np;
+ /* bind subscript later */
+ if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ lvalue->isfloat=1;
+ lvalue->flag = 0;
+ if(c=='[')
+ {
+ lvalue->flag = (str-lvalue->expr);
+ do
+ {
+ while(c=='.')
+ {
+ str++;
+ while(xp=str, c=mbchar(str), isaname(c));
+ c = *(str = xp);
+ }
+ if(c=='[')
+ str = nv_endsubscript(np,str,0);
+ }
+ while((c= *str)=='[' || c=='.');
+ break;
+ }
+ }
+ else
+ {
+ char lastbase=0, *val = xp, oerrno = errno;
+ lvalue->eflag = 0;
+ errno = 0;
+ if(shp->bltindata.bnode==SYSLET && !sh_isoption(SH_LETOCTAL))
+ {
+ while(*val=='0' && isdigit(val[1]))
+ val++;
+ }
+ r = strtonll(val,&str, &lastbase,-1);
+ if(*str=='8' || *str=='9')
+ {
+ lastbase=10;
+ errno = 0;
+ r = strtonll(val,&str, &lastbase,-1);
+ }
+ if(lastbase<=1)
+ lastbase=10;
+ if(*val=='0')
+ {
+ while(*val=='0')
+ val++;
+ if(*val==0 || *val=='.' || *val=='x' || *val=='X')
+ val--;
+ }
+ if(r==LLONG_MAX && errno)
+ c='e';
+ else
+ c = *str;
+ if(c==GETDECIMAL(0) || c=='e' || c == 'E' || lastbase ==
+ 16 && (c == 'p' || c == 'P'))
+ {
+ lvalue->isfloat=1;
+ r = strtold(val,&str);
+ }
+ else if(lastbase==10 && val[1])
+ {
+ if(val[2]=='#')
+ val += 3;
+ if((str-val)>2*sizeof(Sflong_t))
+ {
+ Sfdouble_t rr;
+ rr = strtold(val,&str);
+ if(rr!=r)
+ {
+ r = rr;
+ lvalue->isfloat=1;
+ }
+ }
+ }
+ errno = oerrno;
+ }
+ break;
+ }
+ case VALUE:
+ {
+ register Namval_t *np = (Namval_t*)(lvalue->value);
+ if(sh_isoption(SH_NOEXEC))
+ return(0);
+ np = scope(np,lvalue,0);
+ if(!np)
+ {
+ if(sh_isoption(SH_NOUNSET))
+ {
+ *ptr = lvalue->value;
+ goto skip;
+ }
+ return(0);
+ }
+ lvalue->ovalue = (char*)np;
+ if(lvalue->eflag)
+ lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
+ else if((Namfun_t*)lvalue->ptr && !nv_hasdisc(np,&ENUM_disc) && !nv_isattr(np,NV_INTEGER))
+ {
+ Namval_t *mp,node;
+ mp = ((Namfun_t*)lvalue->ptr)->type;
+ memset(&node,0,sizeof(node));
+ nv_clone(mp,&node,0);
+ nv_offattr(&node,NV_RDONLY|NV_NOFREE);
+ nv_putval(&node,np->nvname,0);
+ if(nv_isattr(&node,NV_NOFREE))
+ return(r=nv_getnum(&node));
+ }
+ lvalue->eflag = 0;
+ if(((lvalue->emode&2) || lvalue->level>1 || sh_isoption(SH_NOUNSET)) && nv_isnull(np) && !nv_isattr(np,NV_INTEGER))
+ {
+ *ptr = nv_name(np);
+ skip:
+ lvalue->value = (char*)ERROR_dictionary(e_notset);
+ lvalue->emode |= 010;
+ return(0);
+ }
+ r = nv_getnum(np);
+ if(nv_isattr(np,NV_INTEGER|NV_BINARY)==(NV_INTEGER|NV_BINARY))
+ lvalue->isfloat= (r!=(Sflong_t)r);
+ else if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ lvalue->isfloat=1;
+ if((lvalue->emode&ARITH_ASSIGNOP) && nv_isarray(np))
+ lvalue->nosub = nv_aindex(np)+1;
+ return(r);
+ }
+
+ case MESSAGE:
+ sfsync(NIL(Sfio_t*));
+#if 0
+ if(warn)
+ errormsg(SH_DICT,ERROR_warn(0),lvalue->value,*ptr);
+ else
+#endif
+ if(lvalue->emode&ARITH_COMP)
+ return(-1);
+
+ errormsg(SH_DICT,ERROR_exit((lvalue->emode&3)!=0),lvalue->value,*ptr);
+ }
+ *ptr = str;
+ return(r);
+}
+
+/*
+ * convert number defined by string to a Sfdouble_t
+ * ptr is set to the last character processed
+ * if mode>0, an error will be fatal with value <mode>
+ */
+
+Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfdouble_t d;
+ char base=(shp->inarith?0:10), *last;
+ if(*str==0)
+ {
+ if(ptr)
+ *ptr = (char*)str;
+ return(0);
+ }
+ errno = 0;
+ d = strtonll(str,&last,&base,-1);
+ if(*last || errno)
+ {
+ if(!last || *last!='.' || last[1]!='.')
+ d = strval(shp,str,&last,arith,mode);
+ if(!ptr && *last && mode>0)
+ errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str);
+ }
+ else if (!d && *str=='-')
+ d = -0.0;
+ if(ptr)
+ *ptr = last;
+ return(d);
+}
+
+Sfdouble_t sh_arith(Shell_t *shp,register const char *str)
+{
+ return(sh_strnum(str, (char**)0, 1));
+}
+
+void *sh_arithcomp(Shell_t *shp,register char *str)
+{
+ const char *ptr = str;
+ Arith_t *ep;
+ ep = arith_compile(shp,str,(char**)&ptr,arith,ARITH_COMP|1);
+ if(*ptr)
+ errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*ptr,str);
+ return((void*)ep);
+}
diff --git a/src/cmd/ksh93/sh/array.c b/src/cmd/ksh93/sh/array.c
new file mode 100644
index 0000000..658d5a2
--- /dev/null
+++ b/src/cmd/ksh93/sh/array.c
@@ -0,0 +1,1843 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Array processing routines
+ *
+ * David Korn
+ * AT&T Labs
+ * dgk@research.att.com
+ *
+ */
+
+#include "defs.h"
+#include <stak.h>
+#include "name.h"
+
+#define NUMSIZE (4+(ARRAY_MAX>999)+(ARRAY_MAX>9999)+(ARRAY_MAX>99999))
+#define is_associative(ap) array_assoc((Namarr_t*)(ap))
+#define array_setbit(cp, n, b) (cp[n] |= (b))
+#define array_clrbit(cp, n, b) (cp[n] &= ~(b))
+#define array_isbit(cp, n, b) (cp[n] & (b))
+#define NV_CHILD NV_EXPORT
+#define ARRAY_CHILD 1
+#define ARRAY_NOFREE 2
+
+struct index_array
+{
+ Namarr_t header;
+ void *xp; /* if set, subscripts will be converted */
+ int cur; /* index of current element */
+ int maxi; /* maximum index for array */
+ unsigned char *bits; /* bit array for child subscripts */
+ union Value val[1]; /* array of value holders */
+};
+
+struct assoc_array
+{
+ Namarr_t header;
+ Namval_t *pos;
+ Namval_t *nextpos;
+ Namval_t *cur;
+};
+
+#if SHOPT_FIXEDARRAY
+ struct fixed_array
+ {
+ unsigned char ndim;
+ unsigned char dim;
+ unsigned char level;
+ unsigned char ptr;
+ short size;
+ int nelem;
+ int curi;
+ int *max;
+ int *incr;
+ int *cur;
+ char *data;
+ };
+# define array_fixed_data(ap) ((ap)?((struct fixed_array*)((ap)->fixed))->data:0)
+ static void array_fixed_setdata(Namval_t*,Namarr_t*,struct fixed_array*);
+#endif /* SHOPT_FIXEDARRAY */
+
+static Namarr_t *array_scope(Namval_t *np, Namarr_t *ap, int flags)
+{
+ Namarr_t *aq;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ struct index_array *ar;
+ size_t size = ap->hdr.dsize;
+ if(size==0)
+ size = ap->hdr.disc->dsize;
+ if(!(aq=newof(NIL(Namarr_t*),Namarr_t,1,size-sizeof(Namarr_t))))
+ return(0);
+ memcpy(aq,ap,size);
+ aq->hdr.nofree &= ~1;
+ aq->hdr.nofree |= (flags&NV_RDONLY)?1:0;
+ if(is_associative(aq))
+ {
+ aq->scope = (void*)dtopen(&_Nvdisc,Dtoset);
+ dtview((Dt_t*)aq->scope,aq->table);
+ aq->table = (Dt_t*)aq->scope;
+ return(aq);
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp = (struct fixed_array*)ap->fixed)
+ {
+ aq->scope = (void*)ap;
+ fp = (struct fixed_array*)(aq+1);
+ aq->fixed = (void*)fp;
+ fp->max = (int*)(fp+1);
+ fp->incr = fp->max+fp->ndim;
+ fp->cur = fp->incr+fp->ndim;
+ return(aq);
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ aq->scope = (void*)ap;
+ ar = (struct index_array*)aq;
+ memset(ar->val, 0, ar->maxi*sizeof(char*));
+ ar->bits = (unsigned char*)&ar->val[ar->maxi];
+ return(aq);
+}
+
+static int array_unscope(Namval_t *np,Namarr_t *ap)
+{
+ Namfun_t *fp;
+ if(!ap->scope)
+ return(0);
+ if(is_associative(ap))
+ (*ap->fun)(np, NIL(char*), NV_AFREE);
+ if((fp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(fp->nofree&1))
+ free((void*)fp);
+ nv_delete(np,(Dt_t*)0,0);
+ return(1);
+}
+
+static void array_syncsub(Namarr_t *ap, Namarr_t *aq)
+{
+ ((struct index_array*)ap)->cur = ((struct index_array*)aq)->cur;
+}
+
+static int array_covered(Namval_t *np, struct index_array *ap)
+{
+ struct index_array *aq = (struct index_array*)ap->header.scope;
+ if(!ap->header.fun && aq)
+#if SHOPT_FIXEDARRAY
+ return (ap->header.fixed || ((ap->cur<aq->maxi) && aq->val[ap->cur].cp));
+#else
+ return ((ap->cur<aq->maxi) && aq->val[ap->cur].cp);
+#endif /* SHOPT_FIXEDARRAY */
+ return(0);
+}
+
+/*
+ * replace discipline with new one
+ */
+static void array_setptr(register Namval_t *np, struct index_array *old, struct index_array *new)
+{
+ register Namfun_t **fp = &np->nvfun;
+ while(*fp && *fp!= &old->header.hdr)
+ fp = &((*fp)->next);
+ if(*fp)
+ {
+ new->header.hdr.next = (*fp)->next;
+ *fp = &new->header.hdr;
+ }
+ else sfprintf(sfstderr,"discipline not replaced\n");
+}
+
+/*
+ * Calculate the amount of space to be allocated to hold an
+ * indexed array into which <maxi> is a legal index. The number of
+ * elements that will actually fit into the array (> <maxi>
+ * but <= ARRAY_MAX) is returned.
+ *
+ */
+static int arsize(struct index_array *ap, register int maxi)
+{
+ if(ap && maxi < 2*ap->maxi)
+ maxi = 2*ap->maxi;
+ maxi = roundof(maxi,ARRAY_INCR);
+ return (maxi>ARRAY_MAX?ARRAY_MAX:maxi);
+}
+
+static struct index_array *array_grow(Namval_t*, struct index_array*,int);
+
+/* return index of highest element of an array */
+int array_maxindex(Namval_t *np)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ register int i = ap->maxi;
+ if(is_associative(ap))
+ return(-1);
+ while(i>0 && ap->val[--i].cp==0);
+ return(i+1);
+}
+
+static union Value *array_getup(Namval_t *np, Namarr_t *arp, int update)
+{
+ register struct index_array *ap = (struct index_array*)arp;
+ register union Value *up;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ int nofree;
+ if(!arp)
+ return(&np->nvalue);
+ if(is_associative(ap))
+ {
+ Namval_t *mp;
+ mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT));
+ if(mp)
+ {
+ nofree = nv_isattr(mp,NV_NOFREE);
+ up = &mp->nvalue;
+ }
+ else
+ return((union Value*)((*arp->fun)(np,NIL(char*),0)));
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp = (struct fixed_array*)arp->fixed)
+ {
+ if(!fp->data)
+ array_fixed_setdata(np,arp,fp);
+ up = &np->nvalue;
+ if(fp->ptr)
+ up->cp = *(((char**)fp->data)+fp->curi);
+ else
+ up->cp = fp->data+fp->size*fp->curi;
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ else
+ {
+ if(ap->cur >= ap->maxi)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np));
+ up = &(ap->val[ap->cur]);
+ nofree = array_isbit(ap->bits,ap->cur,ARRAY_NOFREE);
+ }
+ if(update)
+ {
+ if(nofree)
+ nv_onattr(np,NV_NOFREE);
+ else
+ nv_offattr(np,NV_NOFREE);
+ }
+ return(up);
+}
+
+int nv_arrayisset(Namval_t *np, Namarr_t *arp)
+{
+ register struct index_array *ap = (struct index_array*)arp;
+ union Value *up;
+ if(is_associative(ap))
+ return((np = nv_opensub(np)) && !nv_isnull(np));
+ if(ap->cur >= ap->maxi)
+ return(0);
+ up = &(ap->val[ap->cur]);
+ if(up->cp==Empty)
+ {
+ Namfun_t *fp = &arp->hdr;
+ for(fp=fp->next; fp; fp = fp->next)
+ {
+ if(fp->disc && (fp->disc->getnum || fp->disc->getval))
+ return(1);
+ }
+ }
+ return(up->cp && up->cp!=Empty);
+}
+
+/*
+ * Get the Value pointer for an array.
+ * Delete space as necessary if flag is ARRAY_DELETE
+ * After the lookup is done the last @ or * subscript is incremented
+ */
+static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
+{
+ register struct index_array *ap = (struct index_array*)arp;
+ register union Value *up;
+ Namval_t *mp;
+ int wasundef;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp=(struct fixed_array*)(arp->fixed);
+#endif /* SHOPT_FIXEDARRAY */
+ if(flag&ARRAY_LOOKUP)
+ ap->header.nelem &= ~ARRAY_NOSCOPE;
+ else
+ ap->header.nelem |= ARRAY_NOSCOPE;
+ if(wasundef = ap->header.nelem&ARRAY_UNDEF)
+ {
+ ap->header.nelem &= ~ARRAY_UNDEF;
+ /* delete array is the same as delete array[@] */
+ if(flag&ARRAY_DELETE)
+ {
+#if SHOPT_FIXEDARRAY
+ nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE|(ap->header.fixed?(ARRAY_UNDEF|ARRAY_FIXED):0));
+#else
+ nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE);
+#endif /* SHOPT_FIXEDARRAY */
+ ap->header.nelem |= ARRAY_SCAN;
+ }
+ else /* same as array[0] */
+ {
+ if(is_associative(ap))
+ (*ap->header.fun)(np,"0",flag==ARRAY_ASSIGN?NV_AADD:0);
+#if SHOPT_FIXEDARRAY
+ else if(fp)
+ {
+ int n=fp->ndim;
+ fp->curi = 0;
+ while(--n>=0)
+ fp->cur[n] = 0;
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ else
+ ap->cur = 0;
+ }
+ }
+ if(is_associative(ap))
+ {
+ mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT));
+ if(!mp)
+ up = (union Value*)&mp;
+ else if(nv_isarray(mp))
+ {
+ if(wasundef)
+ nv_putsub(mp,NIL(char*),ARRAY_UNDEF);
+ return(mp);
+ }
+ else
+ {
+ up = &mp->nvalue;
+ if(nv_isvtree(mp))
+ {
+ if(!up->cp && flag==ARRAY_ASSIGN)
+ {
+ nv_arraychild(np,mp,0);
+ ap->header.nelem++;
+ }
+ return(mp);
+ }
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp)
+ {
+ char *data = array_fixed_data((Namarr_t*)ap->header.scope);
+ if(flag==ARRAY_ASSIGN && data==fp->data)
+ {
+ if(data)
+ {
+ fp->data = (char*)malloc(fp->nelem*fp->size);
+ memcpy(fp->data,data,fp->nelem*fp->size);
+ }
+ else
+ array_fixed_setdata(np,&ap->header,fp);
+ }
+ if(fp->ptr)
+ {
+ if(!fp->data)
+ array_fixed_setdata(np,&ap->header,fp);
+ np->nvalue.cp = *(((char**)fp->data)+fp->curi);
+ }
+ else
+ np->nvalue.cp = fp->data+fp->size*fp->curi;
+ return(np);
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ else
+ {
+ if(!(ap->header.nelem&ARRAY_SCAN) && ap->cur >= ap->maxi)
+ ap = array_grow(np, ap, (int)ap->cur);
+ if(ap->cur>=ap->maxi)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np));
+ up = &(ap->val[ap->cur]);
+ if((!up->cp||up->cp==Empty) && nv_type(np) && nv_isvtree(np))
+ {
+ char *cp;
+ if(!ap->header.table)
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ sfprintf(sh.strbuf,"%d",ap->cur);
+ cp = sfstruse(sh.strbuf);
+ mp = nv_search(cp, ap->header.table, NV_ADD);
+ mp->nvenv = (char*)np;
+ nv_arraychild(np,mp,0);
+ }
+ if(up->np && array_isbit(ap->bits,ap->cur,ARRAY_CHILD))
+ {
+ if(wasundef && nv_isarray(up->np))
+ nv_putsub(up->np,NIL(char*),ARRAY_UNDEF);
+ return(up->np);
+ }
+ }
+ np->nvalue.cp = up->cp;
+ if(!up->cp)
+ {
+ char *xp = nv_setdisc(np,"get",np,(Namfun_t*)np);
+ if(flag!=ARRAY_ASSIGN)
+ return(xp && xp!=(char*)np?np:0);
+ if(!array_covered(np,ap))
+ ap->header.nelem++;
+ }
+ return(np);
+}
+
+#if SHOPT_TYPEDEF
+int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags)
+{
+ Namval_t *nq;
+ char *av[2];
+ int rdonly = nv_isattr(np,NV_RDONLY);
+ int xtrace = sh_isoption(SH_XTRACE);
+ Namarr_t *ap = nv_arrayptr(np);
+ av[1] = 0;
+ sh.last_table = 0;
+ if(!ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(nq = nv_search(sub, ap->table, NV_ADD))
+ {
+ if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0)
+ _nv_unset(nq,NV_RDONLY);
+ nv_arraychild(np,nq,0);
+ if(!nv_isattr(tp,NV_BINARY))
+ {
+ sfprintf(sh.strbuf,"%s=%s",nv_name(nq),nv_getval(np));
+ av[0] = strdup(sfstruse(sh.strbuf));
+ }
+ if(!nv_clone(tp,nq,flags|NV_NOFREE))
+ return(0);
+ ap->nelem |= ARRAY_SCAN;
+ if(!rdonly)
+ nv_offattr(nq,NV_RDONLY);
+ if(!nv_isattr(tp,NV_BINARY))
+ {
+ if(xtrace)
+ sh_offoption(SH_XTRACE);
+ ap->nelem &= ~ARRAY_SCAN;
+ sh_eval(sh_sfeval(av),0);
+ ap->nelem |= ARRAY_SCAN;
+ free((void*)av[0]);
+ if(xtrace)
+ sh_onoption(SH_XTRACE);
+ }
+ return(1);
+ }
+ return(0);
+}
+#endif /* SHOPT_TYPEDEF */
+
+
+static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namarr_t *ap = (Namarr_t*)fp;
+ Namval_t *nq, *mq;
+ char *name, *sub=0;
+ int nelem, skipped=0;
+ Dt_t *otable=ap->table;
+ struct index_array *aq = (struct index_array*)ap, *ar;
+ Shell_t *shp = sh_getinterp();
+ if(flags&NV_MOVE)
+ {
+ if((flags&NV_COMVAR) && nv_putsub(np,NIL(char*),ARRAY_SCAN))
+ {
+ do
+ {
+ if(nq=nv_opensub(np))
+ nq->nvenv = (void*)mp;
+ }
+ while(nv_nextsub(np));
+ }
+ return(fp);
+ }
+ nelem = ap->nelem;
+ if(nelem&ARRAY_NOCLONE)
+ return(0);
+ if((flags&NV_TYPE) && !ap->scope)
+ {
+ ap = array_scope(np,ap,flags);
+ return(&ap->hdr);
+ }
+ ap = (Namarr_t*)nv_clone_disc(fp,0);
+ if(flags&NV_COMVAR)
+ {
+ ap->scope = 0;
+ ap->nelem = 0;
+ sh.prev_table = sh.last_table;
+ sh.prev_root = sh.last_root;
+ }
+ if(ap->table)
+ {
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap->scope && !(flags&NV_COMVAR))
+ {
+ ap->scope = ap->table;
+ dtview(ap->table, otable->view);
+ }
+ }
+ mp->nvfun = (Namfun_t*)ap;
+ mp->nvflag &= NV_MINIMAL;
+ mp->nvflag |= (np->nvflag&~(NV_MINIMAL|NV_NOFREE));
+ if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np)))
+ sub = strdup(sub);
+ ar = (struct index_array*)ap;
+ if(!is_associative(ap))
+ ar->bits = (unsigned char*)&ar->val[ar->maxi];
+ if(!nv_putsub(np,NIL(char*),ARRAY_SCAN|((flags&NV_COMVAR)?0:ARRAY_NOSCOPE)))
+ {
+ if(ap->fun)
+ (*ap->fun)(np,(char*)np,0);
+ skipped=1;
+ goto skip;
+ }
+ do
+ {
+ name = nv_getsub(np);
+ nv_putsub(mp,name,ARRAY_ADD|ARRAY_NOSCOPE);
+ mq = 0;
+ if(nq=nv_opensub(np))
+ mq = nv_search(name,ap->table,NV_ADD);
+ if(nq && (((flags&NV_COMVAR) && nv_isvtree(nq)) || nv_isarray(nq)))
+ {
+ mq->nvalue.cp = 0;
+ if(!is_associative(ap))
+ ar->val[ar->cur].np = mq;
+ nv_clone(nq,mq,flags);
+ }
+ else if(flags&NV_ARRAY)
+ {
+ if((flags&NV_NOFREE) && !is_associative(ap))
+ array_setbit(aq->bits,aq->cur,ARRAY_NOFREE);
+ else if(nq && (flags&NV_NOFREE))
+ {
+ mq->nvalue = nq->nvalue;
+ nv_onattr(nq,NV_NOFREE);
+ }
+ }
+ else if(nv_isattr(np,NV_INTEGER))
+ {
+ Sfdouble_t d= nv_getnum(np);
+ if(!is_associative(ap))
+ ar->val[ar->cur].cp = 0;
+ nv_putval(mp,(char*)&d,NV_LDOUBLE);
+ }
+ else
+ {
+ if(!is_associative(ap))
+ ar->val[ar->cur].cp = 0;
+ nv_putval(mp,nv_getval(np),NV_RDONLY);
+ }
+ aq->header.nelem |= ARRAY_NOSCOPE;
+ }
+ while(nv_nextsub(np));
+skip:
+ if(sub)
+ {
+ if(!skipped)
+ nv_putsub(np,sub,0L);
+ free((void*)sub);
+ }
+ aq->header.nelem = ap->nelem = nelem;
+ return(&ap->hdr);
+}
+
+static char *array_getval(Namval_t *np, Namfun_t *disc)
+{
+ register Namarr_t *aq,*ap = (Namarr_t*)disc;
+ register Namval_t *mp;
+ register char *cp=0;
+ if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np)
+ {
+ if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope))
+ {
+ array_syncsub(aq,ap);
+ if((mp=array_find(np,aq,ARRAY_LOOKUP))==np)
+ return(nv_getv(np,&aq->hdr));
+ }
+ if(mp)
+ {
+ cp = nv_getval(mp);
+ nv_offattr(mp,NV_EXPORT);
+ }
+ return(cp);
+ }
+#if SHOPT_FIXEDARRAY
+ if(ap->fixed && nv_isattr(np,NV_INT16P) == NV_INT16)
+ np->nvalue.s = *np->nvalue.sp;
+#endif /* SHOPT_FIXEDARRAY */
+ return(nv_getv(np,&ap->hdr));
+}
+
+static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc)
+{
+ register Namarr_t *aq,*ap = (Namarr_t*)disc;
+ register Namval_t *mp;
+ if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np)
+ {
+ if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope))
+ {
+ array_syncsub(aq,ap);
+ if((mp=array_find(np,aq,ARRAY_LOOKUP))==np)
+ return(nv_getn(np,&aq->hdr));
+ }
+ return(mp?nv_getnum(mp):0);
+ }
+ return(nv_getn(np,&ap->hdr));
+}
+
+static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp)
+{
+ register Namarr_t *ap = (Namarr_t*)dp;
+ register union Value *up;
+ register Namval_t *mp;
+ register struct index_array *aq = (struct index_array*)ap;
+ int scan,nofree = nv_isattr(np,NV_NOFREE);
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ do
+ {
+ int xfree = is_associative(ap)?0:array_isbit(aq->bits,aq->cur,ARRAY_NOFREE);
+ mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE);
+ scan = ap->nelem&ARRAY_SCAN;
+ if(mp && mp!=np)
+ {
+ if(!is_associative(ap) && string && !(flags&NV_APPEND) && !nv_type(np) && nv_isvtree(mp) && !(ap->nelem&ARRAY_TREE))
+
+ {
+ if(!nv_isattr(np,NV_NOFREE))
+ _nv_unset(mp,flags&NV_RDONLY);
+ array_clrbit(aq->bits,aq->cur,ARRAY_CHILD);
+ aq->val[aq->cur].cp = 0;
+ if(!nv_isattr(mp,NV_NOFREE))
+ nv_delete(mp,ap->table,0);
+ goto skip;
+ }
+ if(!xfree)
+ nv_putval(mp, string, flags);
+ if(string)
+ {
+#if SHOPT_TYPEDEF
+ if(ap->hdr.type && ap->hdr.type!=nv_type(mp))
+ nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0);
+#endif /* SHOPT_TYPEDEF */
+ continue;
+ }
+ ap->nelem |= scan;
+ }
+ if(!string)
+ {
+ if(mp)
+ {
+ if(is_associative(ap))
+ {
+ (*ap->fun)(np,NIL(char*),NV_ADELETE);
+ np->nvalue.cp = 0;
+ }
+ else
+ {
+ if(mp!=np)
+ {
+ array_clrbit(aq->bits,aq->cur,ARRAY_CHILD);
+ aq->val[aq->cur].cp = 0;
+ if(!xfree)
+ nv_delete(mp,ap->table,0);
+ }
+ if(!array_covered(np,(struct index_array*)ap))
+ {
+ if(array_elem(ap))
+ ap->nelem--;
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp=(struct fixed_array*)ap->fixed)
+ {
+ char *data = array_fixed_data((Namarr_t*)ap->scope);
+ int n = fp->size*fp->curi;
+ if(data)
+ {
+ memcpy(fp->data+n,data+n,fp->size);
+ continue;
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ }
+ if(array_elem(ap)==0 && (ap->nelem&ARRAY_SCAN))
+ {
+ if(is_associative(ap))
+ (*ap->fun)(np, NIL(char*), NV_AFREE);
+ else if(ap->table)
+ dtclose(ap->table);
+ nv_offattr(np,NV_ARRAY);
+ }
+ if(!mp || mp!=np || is_associative(ap))
+ continue;
+ }
+ skip:
+ /* prevent empty string from being deleted */
+ up = array_getup(np,ap,!nofree);
+ if(up->cp == Empty)
+ up->cp = 0;
+#if SHOPT_FIXEDARRAY
+ if(nv_isarray(np) && !ap->fixed)
+#else
+ if(nv_isarray(np))
+#endif /* SHOPT_FIXEDARRAY */
+ np->nvalue.up = up;
+ nv_putv(np,string,flags,&ap->hdr);
+#if SHOPT_FIXEDARRAY
+ if(fp = (struct fixed_array*)ap->fixed)
+ {
+ if(fp->ptr)
+ {
+ char **cp = (char**)fp->data;
+ cp[fp->curi] = (char*)(np->nvalue.cp?np->nvalue.cp:Empty);
+ }
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(!is_associative(ap))
+ {
+ if(string)
+ array_clrbit(aq->bits,aq->cur,ARRAY_NOFREE);
+ else if(mp==np)
+ aq->val[aq->cur].cp = 0;
+ }
+#if SHOPT_TYPEDEF
+ if(string && ap->hdr.type && nv_isvtree(np))
+ nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0);
+#endif /* SHOPT_TYPEDEF */
+ }
+ while(!string && nv_nextsub(np));
+ if(ap)
+ ap->nelem &= ~ARRAY_NOSCOPE;
+ if(nofree)
+ nv_onattr(np,NV_NOFREE);
+ else
+ nv_offattr(np,NV_NOFREE);
+ if(!string && !nv_isattr(np,NV_ARRAY))
+ {
+ Namfun_t *nfp;
+#if SHOPT_FIXEDARRAY
+ char *data = array_fixed_data((Namarr_t*)ap->scope);
+ fp = (struct fixed_array*)ap->fixed;
+ if(fp && (!ap->scope || data!=fp->data))
+ {
+ if(fp->ptr)
+ {
+ int n = fp->nelem;
+ char **cp = (char**)fp->data;
+ while(n-->0)
+ {
+ if(cp && *cp!=Empty)
+ free(*cp);
+ cp++;
+ }
+ }
+ free((void*)fp->data);
+ if(data)
+ fp->data = data;
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(!is_associative(ap) && aq->xp)
+ {
+ _nv_unset(nv_namptr(aq->xp,0),NV_RDONLY);
+ free((void*)aq->xp);
+ }
+ if((nfp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(nfp->nofree&1))
+ free((void*)nfp);
+ if(!nv_isnull(np))
+ {
+ nv_onattr(np,NV_NOFREE);
+ _nv_unset(np,flags);
+ }
+ else
+ nv_offattr(np,NV_NOFREE);
+ if(np->nvalue.cp==Empty)
+ np->nvalue.cp = 0;
+ }
+ if(!string && (flags&NV_TYPE))
+ array_unscope(np,ap);
+}
+
+static const Namdisc_t array_disc =
+{
+ sizeof(Namarr_t),
+ array_putval,
+ array_getval,
+ array_getnum,
+ 0,
+ 0,
+ array_clone
+};
+
+static void array_copytree(Namval_t *np, Namval_t *mp)
+{
+ Namfun_t *fp = nv_disc(np,NULL,NV_POP);
+ nv_offattr(np,NV_ARRAY);
+ nv_clone(np,mp,0);
+ if(np->nvalue.cp && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvalue.cp);
+ np->nvalue.cp = 0;
+ np->nvalue.up = &mp->nvalue;
+ fp->nofree &= ~1;
+ nv_disc(np,(Namfun_t*)fp, NV_FIRST);
+ fp->nofree |= 1;
+ nv_onattr(np,NV_ARRAY);
+ mp->nvenv = (char*)np;
+}
+
+/*
+ * Increase the size of the indexed array of elements in <arp>
+ * so that <maxi> is a legal index. If <arp> is 0, an array
+ * of the required size is allocated. A pointer to the
+ * allocated Namarr_t structure is returned.
+ * <maxi> becomes the current index of the array.
+ */
+static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi)
+{
+ register struct index_array *ap;
+ register int i;
+ register int newsize = arsize(arp,maxi+1);
+ if (maxi >= ARRAY_MAX)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0));
+ i = (newsize-1)*sizeof(union Value*)+newsize;
+ ap = new_of(struct index_array,i);
+ memset((void*)ap,0,sizeof(*ap)+i);
+ ap->maxi = newsize;
+ ap->cur = maxi;
+ ap->bits = (unsigned char*)&ap->val[newsize];
+ memset(ap->bits, 0, newsize);
+ if(arp)
+ {
+ ap->header = arp->header;
+ ap->header.hdr.dsize = sizeof(*ap) + i;
+ for(i=0;i < arp->maxi;i++)
+ {
+ ap->bits[i] = arp->bits[i];
+ ap->val[i].cp = arp->val[i].cp;
+ }
+ memcpy(ap->bits, arp->bits, arp->maxi);
+ array_setptr(np,arp,ap);
+ free((void*)arp);
+ }
+ else
+ {
+ Namval_t *mp=0;
+ ap->header.hdr.dsize = sizeof(*ap) + i;
+ i = 0;
+ ap->header.fun = 0;
+ if((nv_isnull(np)||np->nvalue.cp==Empty) && nv_isattr(np,NV_NOFREE))
+ {
+ i = ARRAY_TREE;
+ nv_offattr(np,NV_NOFREE);
+ }
+ if(np->nvalue.cp==Empty)
+ np->nvalue.cp=0;
+ if(nv_hasdisc(np,&array_disc) || (nv_type(np) && nv_isvtree(np)))
+ {
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ mp = nv_search("0", ap->header.table,NV_ADD);
+ if(mp && nv_isnull(mp))
+ {
+ Namfun_t *fp;
+ ap->val[0].np = mp;
+ array_setbit(ap->bits,0,ARRAY_CHILD);
+ for(fp=np->nvfun; fp && !fp->disc->readf; fp=fp->next);
+ if(fp && fp->disc && fp->disc->readf)
+ (*fp->disc->readf)(mp,(Sfio_t*)0,0,fp);
+ i++;
+ }
+ }
+ else
+ if((ap->val[0].cp=np->nvalue.cp))
+ i++;
+ else if(nv_isattr(np,NV_INTEGER) && !nv_isnull(np))
+ {
+ Sfdouble_t d= nv_getnum(np);
+ i++;
+ }
+ ap->header.nelem = i;
+ ap->header.hdr.disc = &array_disc;
+ nv_disc(np,(Namfun_t*)ap, NV_FIRST);
+ nv_onattr(np,NV_ARRAY);
+ if(mp)
+ {
+ array_copytree(np,mp);
+ ap->header.hdr.nofree &= ~1;
+ }
+ }
+ for(;i < newsize;i++)
+ ap->val[i].cp = 0;
+ return(ap);
+}
+
+int nv_atypeindex(Namval_t *np, const char *tname)
+{
+ Namval_t *tp;
+ int offset = staktell();
+ int n = strlen(tname)-1;
+ sfprintf(stkstd,"%s.%.*s%c",NV_CLASS,n,tname,0);
+ tp = nv_open(stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME);
+ stakseek(offset);
+ if(tp)
+ {
+ struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ if(!nv_hasdisc(tp,&ENUM_disc))
+ errormsg(SH_DICT,ERROR_exit(1),e_notenum,tp->nvname);
+ if(!ap)
+ ap = array_grow(np,ap,1);
+ ap->xp = calloc(NV_MINSZ,1);
+ np = nv_namptr(ap->xp,0);
+ np->nvname = tp->nvname;
+ nv_onattr(np,NV_MINIMAL);
+ nv_clone(tp,np,NV_NOFREE);
+ nv_offattr(np,NV_RDONLY);
+ return(1);
+ }
+ errormsg(SH_DICT,ERROR_exit(1),e_unknowntype, n,tname);
+ return(0);
+}
+
+Namarr_t *nv_arrayptr(register Namval_t *np)
+{
+ if(nv_isattr(np,NV_ARRAY))
+ return((Namarr_t*)nv_hasdisc(np, &array_disc));
+ return(0);
+}
+
+/*
+ * Verify that argument is an indexed array and convert to associative,
+ * freeing relevant storage
+ */
+static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int))
+{
+ register Namarr_t *ap;
+ char numbuff[NUMSIZE+1];
+ unsigned dot, digit, n;
+ union Value *up;
+ struct index_array *save_ap;
+ register char *string_index=&numbuff[NUMSIZE];
+ numbuff[NUMSIZE]='\0';
+
+ if(!fun || !(ap = nv_arrayptr(np)) || is_associative(ap))
+ return(NIL(Namarr_t*));
+
+ nv_stack(np,&ap->hdr);
+ save_ap = (struct index_array*)nv_stack(np,0);
+ ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT));
+ ap->nelem = 0;
+ ap->fun = fun;
+ nv_onattr(np,NV_ARRAY);
+
+ for(dot = 0; dot < (unsigned)save_ap->maxi; dot++)
+ {
+ if(save_ap->val[dot].cp)
+ {
+ if ((digit = dot)== 0)
+ *--string_index = '0';
+ else while( n = digit )
+ {
+ digit /= 10;
+ *--string_index = '0' + (n-10*digit);
+ }
+ nv_putsub(np, string_index, ARRAY_ADD);
+ up = (union Value*)((*ap->fun)(np,NIL(char*),0));
+ up->cp = save_ap->val[dot].cp;
+ save_ap->val[dot].cp = 0;
+ }
+ string_index = &numbuff[NUMSIZE];
+ }
+ free((void*)save_ap);
+ return(ap);
+}
+
+/*
+ * set the associative array processing method for node <np> to <fun>
+ * The array pointer is returned if sucessful.
+ */
+Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int))
+{
+ register Namarr_t *ap;
+ char *value=0;
+ Namfun_t *fp;
+ int nelem = 0;
+ if(fun && (ap = nv_arrayptr(np)))
+ {
+ /*
+ * if it's already an indexed array, convert to
+ * associative structure
+ */
+ if(!is_associative(ap))
+ ap = nv_changearray(np, fun);
+ return(ap);
+ }
+ if(nv_isnull(np) && nv_isattr(np,NV_NOFREE))
+ {
+ nelem = ARRAY_TREE;
+ nv_offattr(np,NV_NOFREE);
+ }
+ if(!(fp=nv_isvtree(np)))
+ value = nv_getval(np);
+ if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT))))
+ {
+ /* check for preexisting initialization and save */
+ ap->nelem = nelem;
+ ap->fun = fun;
+ nv_onattr(np,NV_ARRAY);
+ if(fp || value)
+ {
+ nv_putsub(np, "0", ARRAY_ADD);
+ if(value)
+ nv_putval(np, value, 0);
+ else
+ {
+ Namval_t *mp = (Namval_t*)((*fun)(np,NIL(char*),NV_ACURRENT));
+ array_copytree(np,mp);
+ }
+ }
+ return(ap);
+ }
+ return(NIL(Namarr_t*));
+}
+
+/*
+ * move parent subscript into child
+ */
+Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c)
+{
+ Namfun_t *fp;
+ register Namarr_t *ap = nv_arrayptr(np);
+ union Value *up;
+ Namval_t *tp;
+ if(!nq)
+ return(ap?array_find(np,ap, ARRAY_LOOKUP):0);
+ if(!ap)
+ {
+ nv_putsub(np, NIL(char*), ARRAY_FILL);
+ ap = nv_arrayptr(np);
+ }
+ if(!(up = array_getup(np,ap,0)))
+ return((Namval_t*)0);
+ np->nvalue.cp = up->cp;
+ if((tp=nv_type(np)) || c)
+ {
+ ap->nelem |= ARRAY_NOCLONE;
+ nq->nvenv = (char*)np;
+ if(c=='t')
+ nv_clone(tp,nq, 0);
+ else
+ nv_clone(np, nq, NV_NODISC);
+ nv_offattr(nq,NV_ARRAY);
+ ap->nelem &= ~ARRAY_NOCLONE;
+ }
+ nq->nvenv = (char*)np;
+ if((fp=nq->nvfun) && fp->disc && fp->disc->setdisc && (fp = nv_disc(nq,fp,NV_POP)))
+ free((void*)fp);
+ if(!ap->fun)
+ {
+ struct index_array *aq = (struct index_array*)ap;
+ array_setbit(aq->bits,aq->cur,ARRAY_CHILD);
+ if(c=='.' && !nq->nvalue.cp)
+ ap->nelem++;
+ up->np = nq;
+ }
+ if(c=='.')
+ nv_setvtree(nq);
+ return(nq);
+}
+
+/*
+ * This routine sets subscript of <np> to the next element, if any.
+ * The return value is zero, if there are no more elements
+ * Otherwise, 1 is returned.
+ */
+int nv_nextsub(Namval_t *np)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ register unsigned dot;
+ struct index_array *aq=0, *ar=0;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!ap || !(ap->header.nelem&ARRAY_SCAN))
+ return(0);
+ if(is_associative(ap))
+ {
+ Namval_t *nq;
+ if(nq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT))
+ {
+ if(nv_isattr(nq,NV_CHILD))
+ nv_putsub(nq->nvalue.np,NIL(char*),ARRAY_UNDEF);
+ return(1);
+ }
+ ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD);
+ return(0);
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp = (struct fixed_array*)ap->header.fixed)
+ {
+ if(ap->header.nelem&ARRAY_FIXED)
+ {
+ while(++fp->curi < fp->nelem)
+ {
+ nv_putsub(np,0,fp->curi|ARRAY_FIXED|ARRAY_SCAN);
+ if(fp->ptr && *(((char**)fp->data)+fp->curi))
+ return(1);
+ }
+ ap->header.nelem &= ~ARRAY_FIXED;
+ return(0);
+ }
+ dot = fp->dim;
+ if((fp->cur[dot]+1) < fp->max[dot])
+ {
+ fp->cur[dot]++;
+ for(fp->curi=0,dot=0; dot < fp->ndim; dot++)
+ fp->curi += fp->incr[dot]*fp->cur[dot];
+ return(1);
+ }
+ if(fp->level)
+ {
+ dot= --fp->dim;
+ while((dot+1) < fp->ndim)
+ fp->cur[++dot] = 0;
+ fp->level--;
+ fp->curi = 0;
+ }
+ else
+ ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD);
+ return(0);
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ if(!(ap->header.nelem&ARRAY_NOSCOPE))
+ ar = (struct index_array*)ap->header.scope;
+ for(dot=ap->cur+1; dot < (unsigned)ap->maxi; dot++)
+ {
+ aq = ap;
+ if(!ap->val[dot].cp && !(ap->header.nelem&ARRAY_NOSCOPE))
+ {
+ if(!(aq=ar) || dot>=(unsigned)aq->maxi)
+ continue;
+ }
+ if(aq->val[dot].cp==Empty && array_elem(&aq->header) < nv_aimax(np)+1) {
+ ap->cur = dot;
+ if(nv_getval(np)==Empty)
+ continue;
+ }
+ if(aq->val[dot].cp)
+ {
+ ap->cur = dot;
+ if(array_isbit(aq->bits, dot,ARRAY_CHILD))
+ {
+ Namval_t *mp = aq->val[dot].np;
+ if((aq->header.nelem&ARRAY_NOCHILD) && nv_isvtree(mp) && !mp->nvfun->dsize)
+ continue;
+ if(nv_isarray(mp))
+ nv_putsub(mp,NIL(char*),ARRAY_SCAN);
+ }
+ return(1);
+ }
+ }
+ ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD);
+ ap->cur = 0;
+ return(0);
+}
+
+/*
+ * Set an array subscript for node <np> given the subscript <sp>
+ * An array is created if necessary.
+ * <mode> can be a number, plus or more of symbolic constants
+ * ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD
+ * The node pointer is returned which can be NULL if <np> is
+ * not already array and the ARRAY_ADD bit of <mode> is not set.
+ * ARRAY_FILL sets the specified subscript to the empty string when
+ * ARRAY_ADD is specified and there is no value or sets all
+ * the elements up to the number specified if ARRAY_ADD is not specified
+ */
+Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ register int size = (mode&ARRAY_MASK);
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+ if(!ap || (!ap->header.fixed && !ap->header.fun))
+#else
+ if(!ap || !ap->header.fun)
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(sp)
+ {
+ Shell_t *shp = sh_getinterp();
+ if(ap && ap->xp && !strmatch(sp,"+([0-9])"))
+ {
+ Namval_t *mp = nv_namptr(ap->xp,0);
+ nv_putval(mp, sp,0);
+ size = nv_getnum(mp);
+ }
+ else
+ size = (int)sh_arith(shp,(char*)sp);
+ }
+ if(size <0 && ap)
+ size += array_maxindex(np);
+ if(size >= ARRAY_MAX || (size < 0))
+ {
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ return(NIL(Namval_t*));
+ }
+ if(!ap || size>=ap->maxi)
+ {
+ if(size==0 && !(mode&ARRAY_FILL))
+ return(NIL(Namval_t*));
+ if(sh.subshell)
+ np = sh_assignok(np,1);
+ ap = array_grow(np, ap,size);
+ }
+ ap->header.nelem &= ~ARRAY_UNDEF;
+ ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE));
+#if 0
+ if(array_isbit(ap->bits,oldsize,ARRAY_CHILD))
+ mp = ap->val[oldsize].np;
+ if(size != oldsize && mp->nvalue.cp)
+ {
+ Namfun_t *nfp;
+ for(nfp=np->nvfun; nfp; nfp=nfp->next)
+ {
+ if(nfp->disc && nfp->disc->readf)
+ {
+ (*nfp->disc->readf)(mp,(Sfio_t*)0,0,nfp);
+ break;
+ }
+ }
+ }
+#endif
+ ap->cur = size;
+ if((mode&ARRAY_SCAN) && (ap->cur--,!nv_nextsub(np)))
+ np = 0;
+ if(mode&(ARRAY_FILL|ARRAY_ADD))
+ {
+ if(!(mode&ARRAY_ADD))
+ {
+ int n;
+ if(mode&ARRAY_SETSUB)
+ {
+ for(n=0; n <= ap->maxi; n++)
+ ap->val[n].cp = 0;
+ ap->header.nelem = 0;
+ }
+ for(n=0; n <= size; n++)
+ {
+ if(!ap->val[n].cp)
+ {
+ ap->val[n].cp = Empty;
+ if(!array_covered(np,ap))
+ ap->header.nelem++;
+ }
+ }
+ if(n=ap->maxi-ap->maxi)
+ memset(&ap->val[size],0,n*sizeof(union Value));
+ }
+ else if(!(sp=(char*)ap->val[size].cp) || sp==Empty)
+ {
+ if(sh.subshell)
+ np = sh_assignok(np,1);
+ if(ap->header.nelem&ARRAY_TREE)
+ {
+ char *cp;
+ Namval_t *mp;
+ if(!ap->header.table)
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ sfprintf(sh.strbuf,"%d",ap->cur);
+ cp = sfstruse(sh.strbuf);
+ mp = nv_search(cp, ap->header.table, NV_ADD);
+ mp->nvenv = (char*)np;
+ nv_arraychild(np,mp,0);
+ nv_setvtree(mp);
+ }
+ else
+ ap->val[size].cp = Empty;
+ if(!sp && !array_covered(np,ap))
+ ap->header.nelem++;
+ }
+ }
+ else if(!(mode&ARRAY_SCAN))
+ {
+ ap->header.nelem &= ~ARRAY_SCAN;
+ if(array_isbit(ap->bits,size,ARRAY_CHILD))
+ nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF);
+ if(sp && !(mode&ARRAY_ADD) && !ap->val[size].cp)
+ np = 0;
+ }
+ return((Namval_t*)np);
+ }
+#if SHOPT_FIXEDARRAY
+ if(fp=(struct fixed_array*)ap->header.fixed)
+ {
+ if(!fp->data)
+ return(np);
+ if(mode&ARRAY_UNDEF)
+ {
+ fp->dim = 0;
+ fp->curi = 0;
+ for(size=fp->ndim;--size>=0;)
+ fp->cur[size] = 0;
+ ap->header.nelem &= ~ARRAY_MASK;
+ if(mode&ARRAY_FIXED)
+ {
+ mode &= ~ARRAY_UNDEF;
+ ap->header.nelem |= (ARRAY_FIXED|fp->nelem);
+ }
+ else
+ ap->header.nelem |= fp->max[0];
+ }
+ else if(mode&ARRAY_FIXED)
+ {
+ size = (mode&ARRAY_MASK)&~(ARRAY_FIXED);
+ fp->curi = size;
+ for(fp->dim=0;size>0 && fp->dim<fp->ndim; fp->dim++)
+ {
+ fp->cur[fp->dim] = size/fp->incr[fp->dim];
+ size -= fp->incr[fp->dim]*fp->cur[fp->dim];
+ }
+ while(fp->dim < fp->ndim)
+ fp->cur[fp->dim++] = 0;
+ fp->dim = ap->header.nelem;
+ ap->header.nelem |= ARRAY_FIXED;
+ }
+ else if(fp->dim< fp->ndim)
+ {
+ fp->curi += (size-fp->cur[fp->dim])*fp->incr[fp->dim];
+ fp->cur[fp->dim] = size;
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ ap->header.nelem &= ~ARRAY_UNDEF;
+ if(!(mode&ARRAY_FILL))
+ ap->header.nelem &= ~ARRAY_SCAN;
+ ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE));
+#if SHOPT_FIXEDARRAY
+ if(fp)
+ return(np);
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(sp)
+ {
+ if(mode&ARRAY_SETSUB)
+ {
+ (*ap->header.fun)(np, sp, NV_ASETSUB);
+ return(np);
+ }
+ (*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0);
+ if(!(mode&(ARRAY_SCAN|ARRAY_ADD)) && !(*ap->header.fun)(np,NIL(char*),NV_ACURRENT))
+ np = 0;
+ }
+ else if(mode&ARRAY_SCAN)
+ (*ap->header.fun)(np,(char*)np,0);
+ else if(mode&ARRAY_UNDEF)
+ (*ap->header.fun)(np, "",0);
+ if((mode&ARRAY_SCAN) && !nv_nextsub(np))
+ np = 0;
+ return(np);
+}
+
+#if SHOPT_FIXEDARRAY
+int nv_arrfixed(Namval_t *np, Sfio_t *out, int flag, char *dim)
+{
+ Namarr_t *ap = nv_arrayptr(np);
+ struct fixed_array *fp = (struct fixed_array*)ap->fixed;
+ int n;
+ if(flag)
+ {
+ if(out)
+ {
+ for(n=0; n < fp->dim; n++)
+ sfprintf(out,"[%d]",fp->cur[n]);
+ }
+ if(dim)
+ *dim = fp->dim;
+ return(fp->curi);
+ }
+ if(out)
+ {
+ for(n=0; n < fp->ndim; n++)
+ sfprintf(out,"[%d]",fp->max[n]);
+ }
+ fp->dim = 0;
+ return(fp->curi);
+}
+
+static void array_fixed_setdata(Namval_t *np,Namarr_t* ap,struct fixed_array* fp)
+{
+ int n = ap->nelem;
+ ap->nelem = 1;
+ fp->size = fp->ptr?sizeof(void*):nv_datasize(np,0);
+ ap->nelem = n;
+ fp->data = (char*)calloc(fp->nelem,fp->size);
+ if(fp->ptr)
+ {
+ char **cp = (char**)fp->data;
+ for(n=fp->nelem; n-->0;)
+ *cp++ = Empty;
+ }
+}
+
+static int array_fixed_init(Namval_t *np, char *sub, char *cp)
+{
+ Shell_t *shp=sh_getinterp();
+ Namarr_t *ap;
+ struct fixed_array *fp;
+ int n=1,sz;
+ char *ep=cp;
+ while(*ep=='[')
+ {
+ ep = nv_endsubscript(np,ep,0);
+ n++;
+ }
+ if(*ep)
+ return(0);
+ sz = sizeof(struct fixed_array)+ 3*n*sizeof(int);
+ if(!(ap=newof(NIL(Namarr_t*),Namarr_t,1,sz)))
+ return(0);
+ ap->hdr.disc = &array_disc;
+ ap->hdr.dsize = sizeof(Namarr_t)+sz;
+ ap->hdr.nofree &= ~1;
+ fp = (struct fixed_array*)(ap+1);
+ ap->fixed = (void*)fp;
+ fp->ndim = n;
+ fp->max = (int*)(fp+1);
+ fp->incr = fp->max+n;
+ fp->cur = fp->incr+n;
+ fp->max[0] = (int)sh_arith(shp,(char*)sub);
+ for(n=1,ep=cp;*ep=='['; ep=cp)
+ {
+ cp = nv_endsubscript(np,ep,0);
+ cp[-1]=0;
+ fp->max[n++] = sz = (int)sh_arith(shp,(char*)ep+1);
+ if(sz<0)
+ {
+ free((void*)ap);
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ }
+ cp[-1] = ']';
+ }
+ nv_disc(np,(Namfun_t*)ap, NV_FIRST);
+ fp->ptr = !np->nvsize;
+ nv_onattr(np,NV_ARRAY|(fp->ptr?0:NV_NOFREE));
+ fp->incr[n=fp->ndim-1] = 1;
+ for(sz=1; --n>=0;)
+ sz = fp->incr[n] = sz*fp->max[n+1];
+ fp->nelem = sz*fp->max[0];
+ ap->nelem = fp->max[0];
+ return(1);
+}
+
+static char *array_fixed(Namval_t *np, char *sub, char *cp,int mode)
+{
+ Shell_t *shp=sh_getinterp();
+ Namarr_t *ap = nv_arrayptr(np);
+ struct fixed_array *fp = (struct fixed_array*)ap->fixed;
+ char *ep;
+ int size,n=0,sz;
+ if(!fp->data)
+ array_fixed_setdata(np,ap,fp);
+ ap->nelem &= ~ARRAY_UNDEF;
+ if(ap->nelem&ARRAY_FIXED)
+ {
+ ap->nelem &= ~ARRAY_FIXED;
+ n = fp->dim;
+ sz = fp->curi;
+ if(*sub==0)
+ goto skip;
+ }
+ else
+ fp->curi = 0;
+ size = (int)sh_arith(shp,(char*)sub);
+ fp->cur[n] = size;
+ if(size >= fp->max[n] || (size < 0))
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ *cp++ = ']';
+ sz = fp->curi + fp->cur[n]*fp->incr[n];
+ for(n++,ep=cp;*ep=='['; ep=cp,n++)
+ {
+ if(n >= fp->ndim)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ cp = nv_endsubscript(np,ep,0);
+ cp[-1]=0;
+ size = (int)sh_arith(shp,(char*)ep+1);
+ if(size >= fp->max[n] || (size < 0))
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ fp->cur[n] = size;
+ cp[-1] = ']';
+ sz += fp->cur[n]*fp->incr[n];
+ }
+skip:
+ fp->dim = n;
+ ap->nelem &= ~ARRAY_MASK;
+ ap->nelem |= fp->max[n];
+ while(n < fp->ndim)
+ fp->cur[n++] = 0;
+ fp->curi = sz;
+ return(cp-1);
+}
+#endif /* SHOPT_FIXEDARRAY */
+
+/*
+ * process an array subscript for node <np> given the subscript <cp>
+ * returns pointer to character after the subscript
+ */
+char *nv_endsubscript(Namval_t *np, register char *cp, int mode)
+{
+ register int count=1, quoted=0, c;
+ register char *sp = cp+1;
+ /* first find matching ']' */
+ while(count>0 && (c= *++cp))
+ {
+ if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@'))
+ {
+ quoted=1;
+ cp++;
+ }
+ else if(c=='[')
+ count++;
+ else if(c==']')
+ count--;
+ }
+ *cp = 0;
+ if(quoted)
+ {
+ /* strip escape characters */
+ count = staktell();
+ stakwrite(sp,1+cp-sp);
+ sh_trim(sp=stakptr(count));
+ }
+ if(mode && np)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ int scan = 0;
+#if SHOPT_FIXEDARRAY
+ if((mode&NV_FARRAY) && !nv_isarray(np))
+ {
+ if(array_fixed_init(np,sp,cp+1))
+ {
+ *cp++ = c;
+ return(strchr(cp,0));
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ if(ap)
+ scan = ap->nelem&ARRAY_SCAN;
+ if((mode&NV_ASSIGN) && (cp[1]=='=' || cp[1]=='+'))
+ mode |= NV_ADD;
+ else if(ap && cp[1]=='.' && (mode&NV_FARRAY))
+ mode |= NV_ADD;
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ cp = array_fixed(np,sp,cp,mode);
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ nv_putsub(np, sp, ((mode&NV_ADD)?ARRAY_ADD:0)|(cp[1]&&(mode&NV_ADD)?ARRAY_FILL:mode&ARRAY_FILL));
+ if(scan)
+ ap->nelem |= scan;
+ }
+ if(quoted)
+ stakseek(count);
+ *cp++ = c;
+ return(cp);
+}
+
+
+Namval_t *nv_opensub(Namval_t* np)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ if(ap)
+ {
+ if(is_associative(ap))
+ return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT)));
+#if SHOPT_FIXEDARRAY
+ else if(!(fp=(struct fixed_array*)ap->header.fixed) && array_isbit(ap->bits,ap->cur,ARRAY_CHILD))
+#else
+ else if(array_isbit(ap->bits,ap->cur,ARRAY_CHILD))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ return(ap->val[ap->cur].np);
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp)
+ {
+ int n = fp->dim;
+ if((fp->dim+1) < fp->ndim)
+ {
+ fp->dim++;
+ if(ap->header.nelem&ARRAY_SCAN)
+ {
+ while(++n < fp->ndim)
+ fp->cur[n] = 0;
+ fp->level++;
+ }
+ return(np);
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ return(NIL(Namval_t*));
+}
+
+char *nv_getsub(Namval_t* np)
+{
+ static char numbuff[NUMSIZE];
+ register struct index_array *ap;
+ register unsigned dot, n;
+ register char *cp = &numbuff[NUMSIZE];
+ if(!np || !(ap = (struct index_array*)nv_arrayptr(np)))
+ return(NIL(char*));
+ if(is_associative(ap))
+ return((char*)((*ap->header.fun)(np,NIL(char*),NV_ANAME)));
+ if(ap->xp)
+ {
+ np = nv_namptr(ap->xp,0);
+ np->nvalue.s = ap->cur;
+ return(nv_getval(np));
+ }
+ if((dot = ap->cur)==0)
+ *--cp = '0';
+ else while(n=dot)
+ {
+ dot /= 10;
+ *--cp = '0' + (n-10*dot);
+ }
+ return(cp);
+}
+
+/*
+ * If <np> is an indexed array node, the current subscript index
+ * returned, otherwise returns -1
+ */
+int nv_aindex(register Namval_t* np)
+{
+ Namarr_t *ap = nv_arrayptr(np);
+ if(!ap)
+ return(0);
+ else if(is_associative(ap))
+ return(-1);
+#if SHOPT_FIXEDARRAY
+ else if(ap->fixed)
+ return(-1);
+#endif /* SHOPT_FIXEDARRAY */
+ return(((struct index_array*)(ap))->cur&ARRAY_MASK);
+}
+
+int nv_arraynsub(register Namarr_t* ap)
+{
+ return(array_elem(ap));
+}
+
+int nv_aimax(register Namval_t* np)
+{
+ struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ int sub = -1;
+#if SHOPT_FIXEDARRAY
+ if(!ap || is_associative(&ap->header) || ap->header.fixed)
+#else
+ if(!ap || is_associative(&ap->header))
+#endif /* SHOPT_FIXEDARRAY */
+ return(-1);
+ sub = ap->maxi;
+ while(--sub>0 && ap->val[sub].cp==0);
+ return(sub);
+}
+
+/*
+ * This is the default implementation for associative arrays
+ */
+void *nv_associative(register Namval_t *np,const char *sp,int mode)
+{
+ register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np);
+ register int type;
+ switch(mode)
+ {
+ case NV_AINIT:
+ if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array)))
+ {
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ ap->cur = 0;
+ ap->pos = 0;
+ ap->header.hdr.disc = &array_disc;
+ nv_disc(np,(Namfun_t*)ap, NV_FIRST);
+ ap->header.hdr.dsize = sizeof(struct assoc_array);
+ ap->header.hdr.nofree &= ~1;
+ }
+ return((void*)ap);
+ case NV_ADELETE:
+ if(ap->cur)
+ {
+ if(!ap->header.scope || (Dt_t*)ap->header.scope==ap->header.table || !nv_search(ap->cur->nvname,(Dt_t*)ap->header.scope,0))
+ ap->header.nelem--;
+ _nv_unset(ap->cur,NV_RDONLY);
+ nv_delete(ap->cur,ap->header.table,0);
+ ap->cur = 0;
+ }
+ return((void*)ap);
+ case NV_AFREE:
+ ap->pos = 0;
+ if(ap->header.scope)
+ {
+ ap->header.table = dtview(ap->header.table,(Dt_t*)0);
+ dtclose(ap->header.scope);
+ ap->header.scope = 0;
+ }
+ else
+ dtclose(ap->header.table);
+ return((void*)ap);
+ case NV_ANEXT:
+ if(!ap->pos)
+ {
+ if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && dtvnext(ap->header.table))
+ {
+ ap->header.scope = dtvnext(ap->header.table);
+ ap->header.table->view = 0;
+ }
+ if(!(ap->pos=ap->cur))
+ ap->pos = (Namval_t*)dtfirst(ap->header.table);
+ }
+ else
+ ap->pos = ap->nextpos;
+ for(;ap->cur=ap->pos; ap->pos=ap->nextpos)
+ {
+ ap->nextpos = (Namval_t*)dtnext(ap->header.table,ap->pos);
+ if(!nv_isnull(ap->cur))
+ {
+ if((ap->header.nelem&ARRAY_NOCHILD) && nv_isattr(ap->cur,NV_CHILD))
+ continue;
+ return((void*)ap);
+ }
+ }
+ if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && !dtvnext(ap->header.table))
+ {
+ ap->header.table->view = (Dt_t*)ap->header.scope;
+ ap->header.scope = ap->header.table;
+ }
+ return(NIL(void*));
+ case NV_ASETSUB:
+ ap->cur = (Namval_t*)sp;
+ return((void*)ap->cur);
+ case NV_ACURRENT:
+ if(ap->cur)
+ ap->cur->nvenv = (char*)np;
+ return((void*)ap->cur);
+ case NV_ANAME:
+ if(ap->cur)
+ {
+ Shell_t *shp = sh_getinterp();
+ if(!shp->instance && nv_isnull(ap->cur))
+ return(NIL(void*));
+ return((void*)ap->cur->nvname);
+ }
+ return(NIL(void*));
+ default:
+ if(sp)
+ {
+ Namval_t *mp=0;
+ ap->cur = 0;
+ if(sp==(char*)np)
+ return(0);
+ type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD|NV_MINIMAL));
+ if(mode)
+ mode = NV_ADD|HASH_NOSCOPE;
+ else if(ap->header.nelem&ARRAY_NOSCOPE)
+ mode = HASH_NOSCOPE;
+ if(*sp==0 && sh_isoption(SH_XTRACE) && (mode&NV_ADD))
+ errormsg(SH_DICT,ERROR_warn(0),"adding empty subscript");
+ if(sh.subshell && (mp=nv_search(sp,ap->header.table,0)) && nv_isnull(mp))
+ ap->cur = mp;
+ if((mp || (mp=nv_search(sp,ap->header.table,mode))) && nv_isnull(mp) && (mode&NV_ADD))
+ {
+ nv_onattr(mp,type);
+ mp->nvenv = (char*)np;
+ if((mode&NV_ADD) && nv_type(np))
+ nv_arraychild(np,mp,0);
+ if(sh.subshell)
+ np = sh_assignok(np,1);
+ if(!ap->header.scope || !nv_search(sp,dtvnext(ap->header.table),0))
+ ap->header.nelem++;
+ if(nv_isnull(mp))
+ {
+ if(ap->header.nelem&ARRAY_TREE)
+ nv_setvtree(mp);
+ mp->nvalue.cp = Empty;
+ }
+ }
+ else if(ap->header.nelem&ARRAY_SCAN)
+ {
+ Namval_t fake;
+ fake.nvname = (char*)sp;
+ ap->pos = mp = (Namval_t*)dtprev(ap->header.table,&fake);
+ ap->nextpos = (Namval_t*)dtnext(ap->header.table,mp);
+ }
+ else if(!mp && *sp && mode==0)
+ mp = nv_search(sp,ap->header.table,NV_ADD|HASH_NOSCOPE);
+ np = mp;
+ if(ap->pos && ap->pos==np)
+ ap->header.nelem |= ARRAY_SCAN;
+ else if(!(ap->header.nelem&ARRAY_SCAN))
+ ap->pos = 0;
+ ap->cur = np;
+ }
+ if(ap->cur)
+ return((void*)(&ap->cur->nvalue));
+ else
+ return((void*)(&ap->cur));
+ }
+}
+
+/*
+ * Assign values to an array
+ */
+void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[])
+{
+ int arg0=0;
+ struct index_array *ap=0,*aq;
+ if(nv_isarray(np))
+ {
+ ap = (struct index_array*)nv_arrayptr(np);
+ if(ap && is_associative(ap))
+ errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associative array %s",nv_name(np));
+ }
+ if(append)
+ {
+ if(ap)
+ {
+ if(!(aq = (struct index_array*)ap->header.scope))
+ aq = ap;
+ arg0 = ap->maxi;
+ while(--arg0>0 && ap->val[arg0].cp==0 && aq->val[arg0].cp==0);
+ arg0++;
+ }
+ else if(!nv_isnull(np))
+ arg0=1;
+ }
+ while(--argc >= 0)
+ {
+ nv_putsub(np,NIL(char*),(long)argc+arg0|ARRAY_FILL|ARRAY_ADD);
+ nv_putval(np,argv[argc],0);
+ }
+}
+
diff --git a/src/cmd/ksh93/sh/bash.c b/src/cmd/ksh93/sh/bash.c
new file mode 100644
index 0000000..fd2f3a1
--- /dev/null
+++ b/src/cmd/ksh93/sh/bash.c
@@ -0,0 +1,423 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * bash specific extensions
+ * originally provided by Karsten Fleischer
+ */
+
+#include "defs.h"
+#include "path.h"
+#include "io.h"
+#include "builtins.h"
+#include "name.h"
+
+#ifndef BASH_MAJOR
+# define BASH_MAJOR "1"
+# define BASH_MINOR "0"
+# define BASH_PATCH "0"
+# define BASH_BUILD "0"
+# define BASH_RELEASE "experimental"
+#endif
+#define BASH_VERSION BASH_MAJOR "." BASH_MINOR "." BASH_PATCH "(" BASH_BUILD ")-" BASH_RELEASE
+
+
+extern const char bash_pre_rc[];
+
+static char *login_files[4];
+
+const char sh_bash1[] =
+ "[B?Enable brace group expansion. This option is only availabe in bash "
+ "compatibility mode. In ksh mode, brace group expansion is always on.]"
+ "[P?Do not follow symbolic links, use physical directory structure "
+ "instead. Only available in bash compatibility mode.]";
+const char sh_bash2[] =
+"[O]:?[shopt_option?\ashopt_option\a is one of the shell options accepted by "
+ "the \bshopt\b builtin. If \ashopt_option\a is present, \b-O\b sets "
+ "the value of that option; \b+O\b unsets it. If \ashopt_option\a is "
+ "not supplied, the names and values of the shell options accepted by "
+ "\bshopt\b are printed on the standard output. If the invocation "
+ "option is \b+O\b, the output is displayed in a format that may be "
+ "reused as input. Only available if invoked as \bbash\b.]"
+"[01:init-file|rcfile]:[file?Execute commands from \afile\a instead of the "
+ "standard personal initialization file ~/.bashrc if the shell is "
+ "interactive. Only available if invoked as \bbash\b.]"
+"[02:editing?For option compatibility with \bbash\b only. Ignored.]"
+"[03:profile?Read either the system-wide startup file or any of the "
+ "personal initialization files. On by default for interactive "
+ "shells. Only available if invoked as \bbash\b.]"
+"[04:posix?If invoked as \bbash\b, turn on POSIX compatibility. \bBash\b in "
+ "POSIX mode is not the same as \bksh\b.]"
+"[05:version?Print version number and exit.]";
+
+const char sh_optshopt[] =
+"+[-1c?\n@(#)$Id: shopt (AT&T Research) 2003-02-13 $\n]"
+"[-author?Karsten Fleischer <K.Fleischer@omnium.de>]"
+USAGE_LICENSE
+"[+NAME?shopt - set/unset variables controlling optional shell behavior]"
+"[+DESCRIPTION?\bshopt\b sets or unsets variables controlling optional shell "
+ "behavior. With no options, or with the \b-p\b option, a list of all "
+ "settable options is displayed, with an indication of whether or not "
+ "each is set.]"
+"[p?Causes output to be displayed in a form that may be reused as input.]"
+"[s?Set each \aoptname\a.]"
+"[u?Unset each \aoptname\a.]"
+"[q?Suppress output (quiet mode). The return status indicates whether the "
+ "\aoptname\a is set or unset. If multiple \aoptname\a arguments are "
+ "given with \b-q\b, the return status is zero if all \aoptname\as are "
+ "enabled; non-zero otherwise.]"
+"[o?Restricts the values of \aoptname\a to be those defined for the \b-o\b "
+ "option to the set builtin.]"
+"[+?If either \b-s\b or \b-u\b is used with no \aoptname\a arguments, the "
+ "display is limited to those options which are set or unset.]"
+"[+?\bshopt\b supports all bash options. Some settings do not have any effect "
+ "or are are always on and cannot be changed.]"
+"[+?The value of \aoptname\a must be one of the following:]{"
+ "[+cdable_vars?If set, arguments to the \bcd\b command are "
+ "assumed to be names of variables whose values are to "
+ "be used if the usual \bcd\b proceeding fails.]"
+ "[+cdspell?Currently ignored.]"
+ "[+checkhash?Always on.]"
+ "[+checkwinsize?Currently ignored.]"
+ "[+cmdhist?Always on.]"
+ "[+dotglob?If set, include filenames beginning with a \b.\b "
+ "in the results of pathname expansion.]"
+ "[+execfail?Always on.]"
+ "[+expand_aliases?Always on.]"
+ "[+extglob?Enable extended pattern matching features.]"
+ "[+histappend?Always on.]"
+ "[+histreedit?If set and an edit mode is selected, the user "
+ "is given the opportunity to re-edit a failed history "
+ "substitution.]"
+ "[+histverify?If set and an edit mode is selected, the result "
+ "of a history substitution will not be executed "
+ "immediately but be placed in the edit buffer for "
+ "further modifications.]"
+ "[+hostcomplete?Currently ignored.]"
+ "[+huponexit?Currently ignored.]"
+ "[+interactive_comments?Always on.]"
+ "[+lithist?Always on.]"
+ "[+login_shell?This option is set if the shell is started as "
+ "a login shell. The value cannot be changed.]"
+ "[+mailwarn?Currently ignored.]"
+ "[+no_empty_cmd_completion?Always on.]"
+ "[+nocaseglob?Match filenames in a case-insensitive fashion "
+ "when performing filename expansion.]"
+ "[+nullglob?Allows filename patterns which match no files to "
+ "expand to a null string, rather than themselves.]"
+ "[+progcomp?Currently ignored.]"
+ "[+promptvars?Currently ignored.]"
+ "[+restricted_shell?This option is set if the shell is started "
+ "as a restricted shell. The value cannot be changed. "
+ "It is not reset during execution of startup files, "
+ "allowing the startup files to determine whether the "
+ "shell is restricted.]"
+ "[+shift_verbose?Currently ignored.]"
+ "[+sourcepath?If set, the \b.\b builtin uses the value of PATH "
+ "to find the directory containing the file supplied "
+ "as an argument.]"
+ "[+xpg_echo?If set, the \becho\b and \bprint\b builtins "
+ "expand backslash-escape sequences.]"
+"}"
+"\n"
+"\n[optname ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+?The return status when listing options is zero if all \aoptnames\a "
+ "are enabled, non-zero otherwise. When setting or unsetting options, "
+ "the return status is zero unless an \aoptname\a is not a valid shell "
+ "option.]"
+"}"
+
+"[+SEE ALSO?\bset\b(1)]"
+;
+
+/* GLOBIGNORE discipline. Turn on SH_DOTGLOB on set, turn off on unset. */
+
+static void put_globignore(register Namval_t* np, const char *val, int flags, Namfun_t *fp)
+{
+ if(val)
+ sh_onoption(SH_DOTGLOB);
+ else
+ sh_offoption(SH_DOTGLOB);
+
+ nv_putv(np,val,flags,fp);
+}
+
+const Namdisc_t SH_GLOBIGNORE_disc = { sizeof(Namfun_t), put_globignore };
+
+/* FUNCNAME discipline */
+
+struct funcname
+{
+ Namfun_t hdr;
+};
+
+static void put_funcname(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ /* bash silently returns with an error when FUNCNAME is set,
+ unsetting FUNCNAME is allowed */
+ if(val && !(flags&NV_RDONLY))
+ error_info.exit(1);
+
+ nv_putv(np,val,flags,fp);
+}
+
+const Namdisc_t SH_FUNCNAME_disc = { sizeof(struct funcname), put_funcname };
+
+#define SET_SET 1
+#define SET_UNSET 2
+#define SET_NOARGS 4
+
+/* shopt builtin */
+
+int b_shopt(int argc,register char *argv[],void *extra)
+{
+ Shell_t *shp = (Shell_t*)extra;
+ int n, f, ret=0;
+ Shopt_t newflags=shp->options, opt;
+ int verbose=PRINT_SHOPT|PRINT_ALL|PRINT_NO_HEADER|PRINT_VERBOSE;
+ int setflag=0, quietflag=0, oflag=0;
+ memset(&opt,0,sizeof(opt));
+#if SHOPT_RAWONLY
+ on_option(&newflags,SH_VIRAW);
+#endif
+ while((n = optget(argv,sh_optshopt)))
+ {
+ switch(n)
+ {
+ case 'p':
+ verbose&=~PRINT_VERBOSE;
+ break;
+ case 's':
+ case 'u':
+ setflag|=n=='s'?SET_SET:SET_UNSET;
+ if(setflag==(SET_SET|SET_UNSET))
+ {
+ errormsg(SH_DICT,ERROR_ERROR,"cannot set and unset options simultaneously");
+ error_info.errors++;
+ }
+ break;
+ case 'q':
+ quietflag=1;
+ break;
+ case 'o':
+ oflag=1;
+ verbose&=~PRINT_SHOPT;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(-1);
+ }
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ argc -= opt_info.index;
+ if(argc==0)
+ {
+ /* no args, -s => mask=current options, -u mask=~(current options)
+ else mask=all bits */
+ if(setflag&SET_SET)
+ opt=newflags;
+ else if(setflag&SET_UNSET)
+ for(n=0;n<4;n++)
+ opt.v[n]=~newflags.v[n];
+ else
+ memset(&opt,0xff,sizeof(opt));
+ setflag=SET_NOARGS;
+ }
+ while(argc>0)
+ {
+ f=1;
+ n=sh_lookopt(argv[opt_info.index],&f);
+ if(n<=0||(setflag
+ && (is_option(&opt,SH_INTERACTIVE)
+ || is_option(&opt,SH_RESTRICTED)
+ || is_option(&opt,SH_RESTRICTED2)
+ || is_option(&opt,SH_BASH)
+ || is_option(&opt,SH_LOGIN_SHELL)))
+ ||(oflag&&(n&SH_BASHOPT)))
+ {
+ errormsg(SH_DICT,ERROR_ERROR, e_option, argv[opt_info.index]);
+ error_info.errors++;
+ ret=1;
+ }
+ else if(f)
+ on_option(&opt,n&0xff);
+ else
+ off_option(&opt,n&0xff);
+ opt_info.index++;
+ argc--;
+ }
+ if(setflag&(SET_SET|SET_UNSET))
+ {
+ if(setflag&SET_SET)
+ {
+ if(sh_isoption(SH_INTERACTIVE))
+ off_option(&opt,SH_NOEXEC);
+ if(is_option(&opt,SH_VI)||is_option(&opt,SH_EMACS)||is_option(&opt,SH_GMACS))
+ {
+ off_option(&newflags,SH_VI);
+ off_option(&newflags,SH_EMACS);
+ off_option(&newflags,SH_GMACS);
+ }
+ for(n=0;n<4;n++)
+ newflags.v[n] |= opt.v[n];
+ }
+ else if(setflag&SET_UNSET)
+ for(n=0;n<4;n++)
+ newflags.v[n] &= ~opt.v[n];
+ sh_applyopts(shp,newflags);
+ shp->options = newflags;
+ if(is_option(&newflags,SH_XTRACE))
+ sh_trace(shp,argv,1);
+ }
+ else if(!(setflag&SET_NOARGS)) /* no -s,-u but args, ret=0 if opt&mask==mask */
+ {
+ for(n=0;n<4;n++)
+ ret+=((newflags.v[n]&opt.v[n])!=opt.v[n]);
+ }
+ if(!quietflag&&!(setflag&(SET_SET|SET_UNSET)))
+ sh_printopts(newflags,verbose,&opt);
+ return(ret);
+}
+
+/* mode = 0: init, called two times
+ before parsing shell args with SH_PREINIT state turned on
+ second time after sh_init() is through and with SH_PREINIT state turned off
+ mode > 1: re-init
+ mode < 0: shutdown
+*/
+
+void bash_init(Shell_t *shp,int mode)
+{
+ Sfio_t *iop;
+ Namval_t *np;
+ int n=0,xtrace,verbose;
+ if(mode>0)
+ goto reinit;
+ if(mode < 0)
+ {
+ /* termination code */
+ if(sh_isoption(SH_LOGIN_SHELL) && !sh_isoption(SH_POSIX))
+ sh_source(shp, NiL, sh_mactry(shp,(char*)e_bash_logout));
+ return;
+ }
+
+ if(sh_isstate(SH_PREINIT))
+ { /* pre-init stage */
+ if(sh_isoption(SH_RESTRICTED))
+ sh_onoption(SH_RESTRICTED2);
+ sh_onoption(SH_HISTORY2);
+ sh_onoption(SH_INTERACTIVE_COMM);
+ sh_onoption(SH_SOURCEPATH);
+ sh_onoption(SH_HISTAPPEND);
+ sh_onoption(SH_CMDHIST);
+ sh_onoption(SH_LITHIST);
+ sh_onoption(SH_NOEMPTYCMDCOMPL);
+ if(shp->login_sh==2)
+ sh_onoption(SH_LOGIN_SHELL);
+ if(strcmp(astconf("CONFORMANCE",0,0),"standard")==0)
+ sh_onoption(SH_POSIX);
+ if(strcmp(astconf("UNIVERSE",0,0),"att")==0)
+ sh_onoption(SH_XPG_ECHO);
+ else
+ sh_offoption(SH_XPG_ECHO);
+ if(strcmp(astconf("PATH_RESOLVE",0,0),"physical")==0)
+ sh_onoption(SH_PHYSICAL);
+ else
+ sh_offoption(SH_PHYSICAL);
+
+ /* add builtins */
+ sh_addbuiltin("shopt", b_shopt, &sh);
+
+ /* set up some variables needed for --version
+ * needs to go here because --version option is parsed before the init script.
+ */
+ if(np=nv_open("HOSTTYPE",shp->var_tree,0))
+ nv_putval(np, BASH_HOSTTYPE, NV_NOFREE);
+ if(np=nv_open("MACHTYPE",shp->var_tree,0))
+ nv_putval(np, BASH_MACHTYPE, NV_NOFREE);
+ if(np=nv_open("BASH_VERSION",shp->var_tree,0))
+ nv_putval(np, BASH_VERSION, NV_NOFREE);
+ if(np=nv_open("BASH_VERSINFO",shp->var_tree,0))
+ {
+ char *argv[7];
+ argv[0] = BASH_MAJOR;
+ argv[1] = BASH_MINOR;
+ argv[2] = BASH_PATCH;
+ argv[3] = BASH_BUILD;
+ argv[4] = BASH_RELEASE;
+ argv[5] = BASH_MACHTYPE;
+ argv[6] = 0;
+ nv_setvec(np, 0, 6, argv);
+ nv_onattr(np,NV_RDONLY);
+ }
+ return;
+ }
+
+ /* rest of init stage */
+
+ /* restrict BASH_ENV */
+ if(np=nv_open("BASH_ENV",shp->var_tree,0))
+ {
+ const Namdisc_t *dp = nv_discfun(NV_DCRESTRICT);
+ Namfun_t *fp = calloc(dp->dsize,1);
+ fp->disc = dp;
+ nv_disc(np, fp, 0);
+ }
+
+ /* open GLOBIGNORE node */
+ if(np=nv_open("GLOBIGNORE",shp->var_tree,0))
+ {
+ const Namdisc_t *dp = &SH_GLOBIGNORE_disc;
+ Namfun_t *fp = calloc(dp->dsize,1);
+ fp->disc = dp;
+ nv_disc(np, fp, 0);
+ }
+
+ /* set startup files */
+ n=0;
+ if(sh_isoption(SH_LOGIN_SHELL))
+ {
+ if(!sh_isoption(SH_POSIX))
+ {
+ login_files[n++] = (char*)e_bash_profile;
+ login_files[n++] = (char*)e_bash_login;
+ }
+ login_files[n++] = (char*)e_profile;
+ }
+ shp->login_files = login_files;
+reinit:
+ xtrace = sh_isoption(SH_XTRACE);
+ sh_offoption(SH_XTRACE);
+ verbose = sh_isoption(SH_VERBOSE);
+ sh_offoption(SH_VERBOSE);
+ if(np = nv_open("SHELLOPTS", shp->var_tree, NV_NOADD))
+ nv_offattr(np,NV_RDONLY);
+ iop = sfopen(NULL, bash_pre_rc, "s");
+ sh_eval(iop,0);
+ if(xtrace)
+ sh_offoption(SH_XTRACE);
+ if(verbose)
+ sh_offoption(SH_VERBOSE);
+}
diff --git a/src/cmd/ksh93/sh/defs.c b/src/cmd/ksh93/sh/defs.c
new file mode 100644
index 0000000..308ce22
--- /dev/null
+++ b/src/cmd/ksh93/sh/defs.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * Ksh - AT&T Labs
+ * Written by David Korn
+ * This file defines all the read/write shell global variables
+ */
+
+#include "defs.h"
+#include "jobs.h"
+#include "shlex.h"
+#include "edit.h"
+#include "timeout.h"
+
+Shell_t sh = {0};
+struct shared *shgd;
+#ifdef __IMPORT__
+ Shell_t *_imp__sh = &sh;
+#endif
+
+Dtdisc_t _Nvdisc =
+{
+ offsetof(Namval_t,nvname), -1 , 0, 0, 0, nv_compare
+};
+
+/* reserve room for writable state table */
+char *sh_lexstates[ST_NONE] = {0};
+
+struct jobs job = {0};
+int32_t sh_mailchk = 600;
+
diff --git a/src/cmd/ksh93/sh/deparse.c b/src/cmd/ksh93/sh/deparse.c
new file mode 100644
index 0000000..d7736a4
--- /dev/null
+++ b/src/cmd/ksh93/sh/deparse.c
@@ -0,0 +1,603 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell deparser
+ *
+ */
+
+#include "defs.h"
+#include "shnodes.h"
+#include "test.h"
+
+
+#define HUGE_INT (((unsigned)-1)>>1)
+#define BEGIN 0
+#define MIDDLE 1
+#define END 2
+#define PRE 1
+#define POST 2
+
+
+/* flags that can be specified with p_tree() */
+#define NO_NEWLINE 1
+#define NEED_BRACE 2
+#define NO_BRACKET 4
+
+static void p_comlist(const struct dolnod*,int);
+static void p_arg(const struct argnod*, int endchar, int opts);
+static void p_comarg(const struct comnod*);
+static void p_keyword(const char*,int);
+static void p_redirect(const struct ionod*);
+static void p_switch(const struct regnod*);
+static void here_body(const struct ionod*);
+static void p_tree(const Shnode_t*,int);
+
+static int level;
+static int begin_line;
+static int end_line;
+static char io_op[7];
+static char un_op[3] = "-?";
+static const struct ionod *here_doc;
+static Sfio_t *outfile;
+static const char *forinit = "";
+
+extern void sh_deparse(Sfio_t*, const Shnode_t*,int);
+
+void sh_deparse(Sfio_t *out, const Shnode_t *t,int tflags)
+{
+ outfile = out;
+ p_tree(t,tflags);
+}
+/*
+ * print script corresponding to shell tree <t>
+ */
+static void p_tree(register const Shnode_t *t,register int tflags)
+{
+ register char *cp;
+ int save = end_line;
+ int needbrace = (tflags&NEED_BRACE);
+ tflags &= ~NEED_BRACE;
+ if(tflags&NO_NEWLINE)
+ end_line = ' ';
+ else
+ end_line = '\n';
+ switch(t->tre.tretyp&COMMSK)
+ {
+ case TTIME:
+ if(t->tre.tretyp&COMSCAN)
+ p_keyword("!",BEGIN);
+ else
+ p_keyword("time",BEGIN);
+ if(t->par.partre)
+ p_tree(t->par.partre,tflags);
+ level--;
+ break;
+
+ case TCOM:
+ if(begin_line && level>0)
+ sfnputc(outfile,'\t',level);
+ begin_line = 0;
+ p_comarg((struct comnod*)t);
+ break;
+
+ case TSETIO:
+ if(t->tre.tretyp&FPCL)
+ tflags |= NEED_BRACE;
+ else
+ tflags = NO_NEWLINE|NEED_BRACE;
+ p_tree(t->fork.forktre,tflags);
+ p_redirect(t->fork.forkio);
+ break;
+
+ case TFORK:
+ if(needbrace)
+ tflags |= NEED_BRACE;
+ if(t->tre.tretyp&(FAMP|FCOOP))
+ {
+ tflags = NEED_BRACE|NO_NEWLINE;
+ end_line = ' ';
+ }
+ else if(t->fork.forkio)
+ tflags = NO_NEWLINE;
+ p_tree(t->fork.forktre,tflags);
+ if(t->fork.forkio)
+ p_redirect(t->fork.forkio);
+ if(t->tre.tretyp&FCOOP)
+ {
+ sfputr(outfile,"|&",'\n');
+ begin_line = 1;
+ }
+ else if(t->tre.tretyp&FAMP)
+ {
+ sfputr(outfile,"&",'\n');
+ begin_line = 1;
+ }
+ break;
+
+ case TIF:
+ p_keyword("if",BEGIN);
+ p_tree(t->if_.iftre,0);
+ p_keyword("then",MIDDLE);
+ p_tree(t->if_.thtre,0);
+ if(t->if_.eltre)
+ {
+ p_keyword("else",MIDDLE);
+ p_tree(t->if_.eltre,0);
+ }
+ p_keyword("fi",END);
+ break;
+
+ case TWH:
+ if(t->wh.whinc)
+ cp = "for";
+ else if(t->tre.tretyp&COMSCAN)
+ cp = "until";
+ else
+ cp = "while";
+ p_keyword(cp,BEGIN);
+ if(t->wh.whinc)
+ {
+ struct argnod *arg = (t->wh.whtre)->ar.arexpr;
+ sfprintf(outfile,"(( %s; ",forinit);
+ forinit = "";
+ sfputr(outfile,arg->argval,';');
+ arg = (t->wh.whinc)->arexpr;
+ sfprintf(outfile," %s))\n",arg->argval);
+ }
+ else
+ p_tree(t->wh.whtre,0);
+ t = t->wh.dotre;
+ goto dolist;
+
+ case TLST:
+ {
+ Shnode_t *tr = t->lst.lstrit;
+ if(tr->tre.tretyp==TWH && tr->wh.whinc && t->lst.lstlef->tre.tretyp==TARITH)
+ {
+ /* arithmetic for statement */
+ struct argnod *init = (t->lst.lstlef)->ar.arexpr;
+ forinit= init->argval;
+ p_tree(t->lst.lstrit,tflags);
+ break;
+ }
+ if(needbrace)
+ p_keyword("{",BEGIN);
+ p_tree(t->lst.lstlef,0);
+ if(needbrace)
+ tflags = 0;
+ p_tree(t->lst.lstrit,tflags);
+ if(needbrace)
+ p_keyword("}",END);
+ break;
+ }
+
+ case TAND:
+ cp = "&&";
+ goto andor;
+ case TORF:
+ cp = "||";
+ goto andor;
+ case TFIL:
+ cp = "|";
+ andor:
+ {
+ int bracket = 0;
+ if(t->tre.tretyp&TTEST)
+ {
+ tflags |= NO_NEWLINE;
+ if(!(tflags&NO_BRACKET))
+ {
+ p_keyword("[[",BEGIN);
+ tflags |= NO_BRACKET;
+ bracket=1;
+ }
+ }
+ p_tree(t->lst.lstlef,NEED_BRACE|NO_NEWLINE|(tflags&NO_BRACKET));
+ if(tflags&FALTPIPE)
+ {
+ Shnode_t *tt = t->lst.lstrit;
+ if(tt->tre.tretyp!=TFIL || !(tt->lst.lstlef->tre.tretyp&FALTPIPE))
+ {
+ sfputc(outfile,'\n');
+ return;
+ }
+ }
+ sfputr(outfile,cp,here_doc?'\n':' ');
+ if(here_doc)
+ {
+ here_body(here_doc);
+ here_doc = 0;
+ }
+ level++;
+ p_tree(t->lst.lstrit,tflags|NEED_BRACE);
+ if(bracket)
+ p_keyword("]]",END);
+ level--;
+ break;
+ }
+
+ case TPAR:
+ p_keyword("(",BEGIN);
+ p_tree(t->par.partre,0);
+ p_keyword(")",END);
+ break;
+
+ case TARITH:
+ {
+ register struct argnod *ap = t->ar.arexpr;
+ if(begin_line && level)
+ sfnputc(outfile,'\t',level);
+ sfprintf(outfile,"(( %s ))%c",ap->argval,end_line);
+ if(!(tflags&NO_NEWLINE))
+ begin_line=1;
+ break;
+ }
+
+ case TFOR:
+ cp = ((t->tre.tretyp&COMSCAN)?"select":"for");
+ p_keyword(cp,BEGIN);
+ sfputr(outfile,t->for_.fornam,' ');
+ if(t->for_.forlst)
+ {
+ sfputr(outfile,"in",' ');
+ tflags = end_line;
+ end_line = '\n';
+ p_comarg(t->for_.forlst);
+ end_line = tflags;
+ }
+ else
+ sfputc(outfile,'\n');
+ begin_line = 1;
+ t = t->for_.fortre;
+ dolist:
+ p_keyword("do",MIDDLE);
+ p_tree(t,0);
+ p_keyword("done",END);
+ break;
+
+ case TSW:
+ p_keyword("case",BEGIN);
+ p_arg(t->sw.swarg,' ',0);
+ if(t->sw.swlst)
+ {
+ begin_line = 1;
+ sfputr(outfile,"in",'\n');
+ tflags = end_line;
+ end_line = '\n';
+ p_switch(t->sw.swlst);
+ end_line = tflags;
+ }
+ p_keyword("esac",END);
+ break;
+
+ case TFUN:
+ if(t->tre.tretyp&FPOSIX)
+ {
+ sfprintf(outfile,"%s",t->funct.functnam);
+ p_keyword("()\n",BEGIN);
+ }
+ else
+ {
+ p_keyword("function",BEGIN);
+ tflags = (t->funct.functargs?' ':'\n');
+ sfputr(outfile,t->funct.functnam,tflags);
+ if(t->funct.functargs)
+ {
+ tflags = end_line;
+ end_line = '\n';
+ p_comarg(t->funct.functargs);
+ end_line = tflags;
+ }
+ }
+ begin_line = 1;
+ p_keyword("{\n",MIDDLE);
+ begin_line = 1;
+ p_tree(t->funct.functtre,0);
+ p_keyword("}",END);
+ break;
+ /* new test compound command */
+ case TTST:
+ if(!(tflags&NO_BRACKET))
+ p_keyword("[[",BEGIN);
+ if((t->tre.tretyp&TPAREN)==TPAREN)
+ {
+ p_keyword("(",BEGIN);
+ p_tree(t->lst.lstlef,NO_BRACKET|NO_NEWLINE);
+ p_keyword(")",END);
+ }
+ else
+ {
+ int flags = (t->tre.tretyp)>>TSHIFT;
+ if(t->tre.tretyp&TNEGATE)
+ sfputr(outfile,"!",' ');
+ if(t->tre.tretyp&TUNARY)
+ {
+ un_op[1] = flags;
+ sfputr(outfile,un_op,' ');
+ }
+ else
+ cp = ((char*)(shtab_testops+(flags&037)-1)->sh_name);
+ p_arg(&(t->lst.lstlef->arg),' ',0);
+ if(t->tre.tretyp&TBINARY)
+ {
+ sfputr(outfile,cp,' ');
+ p_arg(&(t->lst.lstrit->arg),' ',0);
+ }
+ }
+ if(!(tflags&NO_BRACKET))
+ p_keyword("]]",END);
+ }
+ while(begin_line && here_doc)
+ {
+ here_body(here_doc);
+ here_doc = 0;
+ }
+ end_line = save;
+ return;
+}
+
+/*
+ * print a keyword
+ * increment indent level for flag==BEGIN
+ * decrement indent level for flag==END
+ */
+static void p_keyword(const char *word,int flag)
+{
+ register int sep;
+ if(flag==END)
+ sep = end_line;
+ else if(*word=='[' || *word=='(')
+ sep = ' ';
+ else
+ sep = '\t';
+ if(flag!=BEGIN)
+ level--;
+ if(begin_line && level)
+ sfnputc(outfile,'\t',level);
+ sfputr(outfile,word,sep);
+ if(sep=='\n')
+ begin_line=1;
+ else
+ begin_line=0;
+ if(flag!=END)
+ level++;
+}
+
+static void p_arg(register const struct argnod *arg,register int endchar,int opts)
+{
+ register const char *cp;
+ register int flag;
+ do
+ {
+ if(!arg->argnxt.ap)
+ flag = endchar;
+ else if(opts&PRE)
+ {
+ /* case alternation lists in reverse order */
+ p_arg(arg->argnxt.ap,'|',opts);
+ flag = endchar;
+ }
+ else if(opts)
+ flag = ' ';
+ cp = arg->argval;
+ if(*cp==0 && (arg->argflag&ARG_EXP) && arg->argchn.ap)
+ {
+ int c = (arg->argflag&ARG_RAW)?'>':'<';
+ sfputc(outfile,c);
+ sfputc(outfile,'(');
+ p_tree((Shnode_t*)arg->argchn.ap,0);
+ sfputc(outfile,')');
+ }
+ else if(*cp==0 && opts==POST && arg->argchn.ap)
+ {
+ /* compound assignment */
+ struct fornod *fp=(struct fornod*)arg->argchn.ap;
+ sfprintf(outfile,"%s=(\n",fp->fornam);
+ sfnputc(outfile,'\t',++level);
+ p_tree(fp->fortre,0);
+ if(--level)
+ sfnputc(outfile,'\t',level);
+ sfputc(outfile,')');
+ }
+ else if((arg->argflag&ARG_RAW) && (cp[1] || (*cp!='[' && *cp!=']')))
+ cp = sh_fmtq(cp);
+ sfputr(outfile,cp,flag);
+ if(flag=='\n')
+ begin_line = 1;
+ arg = arg->argnxt.ap;
+ }
+ while((opts&POST) && arg);
+ return;
+}
+
+static void p_redirect(register const struct ionod *iop)
+{
+ register char *cp;
+ register int iof,iof2;
+ for(;iop;iop=iop->ionxt)
+ {
+ iof=iop->iofile;
+ cp = io_op;
+ if(iop->iovname)
+ {
+ sfwrite(outfile,"(;",2);
+ sfputr(outfile,iop->iovname,')');
+ cp++;
+ }
+ else
+ *cp = '0'+(iof&IOUFD);
+ if(iof&IOPUT)
+ {
+ if(*cp == '1' && !iop->iovname)
+ cp++;
+ io_op[1] = '>';
+ }
+ else
+ {
+ if(*cp == '0' && !iop->iovname)
+ cp++;
+ io_op[1] = '<';
+ }
+ io_op[2] = 0;
+ io_op[3] = 0;
+ if(iof&IOLSEEK)
+ {
+ io_op[1] = '#';
+ if(iof&IOARITH)
+ strcpy(&io_op[3]," ((");
+ }
+ else if(iof&IOMOV)
+ io_op[2] = '&';
+ else if(iof&(IORDW|IOAPP))
+ io_op[2] = '>';
+ else if(iof&IOCLOB)
+ io_op[2] = '|';
+ if(iop->iodelim)
+ {
+ /* here document */
+#ifdef xxx
+ iop->iolink = (char*)here_doc;
+#endif
+ here_doc = iop;
+ io_op[2] = '<';
+#ifdef future
+ if(iof&IOSTRIP)
+ io_op[3] = '-';
+#endif
+ }
+ sfputr(outfile,cp,' ');
+ if(iop->ionxt)
+ iof = ' ';
+ else
+ {
+ if((iof=end_line)=='\n')
+ begin_line = 1;
+ }
+ if((iof&IOLSEEK) && (iof&IOARITH))
+ iof2 = iof, iof = ' ';
+ if(iop->iodelim)
+ {
+ if(!(iop->iofile&IODOC))
+ sfwrite(outfile,"''",2);
+ sfputr(outfile,sh_fmtq(iop->iodelim),iof);
+ }
+ else if(iop->iofile&IORAW)
+ sfputr(outfile,sh_fmtq(iop->ioname),iof);
+ else
+ sfputr(outfile,iop->ioname,iof);
+ if((iof&IOLSEEK) && (iof&IOARITH))
+ sfputr(outfile, "))", iof2);
+ }
+ return;
+}
+
+static void p_comarg(register const struct comnod *com)
+{
+ register int flag = end_line;
+ if(com->comtyp&FAMP)
+ sfwrite(outfile,"& ",2);
+ if(com->comarg || com->comio)
+ flag = ' ';
+ if(com->comset)
+ p_arg(com->comset,flag,POST);
+ if(com->comarg)
+ {
+ if(!com->comio)
+ flag = end_line;
+ if(com->comtyp&COMSCAN)
+ p_arg(com->comarg,flag,POST);
+ else
+ p_comlist((struct dolnod*)com->comarg,flag);
+ }
+ if(com->comio)
+ p_redirect(com->comio);
+ return;
+}
+
+static void p_comlist(const struct dolnod *dol,int endchar)
+{
+ register char *cp, *const*argv;
+ register int flag = ' ', special;
+ argv = dol->dolval+ARG_SPARE;
+ cp = *argv;
+ special = (*cp=='[' && cp[1]==0);
+ do
+ {
+ if(cp)
+ argv++;
+ else
+ cp = "";
+ if(*argv==0)
+ {
+ if((flag=endchar)=='\n')
+ begin_line = 1;
+ special = (*cp==']' && cp[1]==0);
+ }
+ sfputr(outfile,special?cp:sh_fmtq(cp),flag);
+ special = 0;
+ }
+ while(cp = *argv);
+ return;
+}
+
+static void p_switch(register const struct regnod *reg)
+{
+ if(level>1)
+ sfnputc(outfile,'\t',level-1);
+ p_arg(reg->regptr,')',PRE);
+ begin_line = 0;
+ sfputc(outfile,'\t');
+ if(reg->regcom)
+ p_tree(reg->regcom,0);
+ level++;
+ if(reg->regflag)
+ p_keyword(";&",END);
+ else
+ p_keyword(";;",END);
+ if(reg->regnxt)
+ p_switch(reg->regnxt);
+ return;
+}
+
+/*
+ * output here documents
+ */
+static void here_body(register const struct ionod *iop)
+{
+ Sfio_t *infile;
+#ifdef xxx
+ if(iop->iolink)
+ here_body((struct inode*)iop->iolink);
+ iop->iolink = 0;
+#endif
+ if(iop->iofile&IOSTRG)
+ infile = sfnew((Sfio_t*)0,iop->ioname,iop->iosize,-1,SF_STRING|SF_READ);
+ else
+ sfseek(infile=sh.heredocs,iop->iooffset,SEEK_SET);
+ sfmove(infile,outfile,iop->iosize,-1);
+ if(iop->iofile&IOSTRG)
+ sfclose(infile);
+ sfputr(outfile,iop->iodelim,'\n');
+}
+
diff --git a/src/cmd/ksh93/sh/env.c b/src/cmd/ksh93/sh/env.c
new file mode 100644
index 0000000..717c8b8
--- /dev/null
+++ b/src/cmd/ksh93/sh/env.c
@@ -0,0 +1,255 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <cdt.h>
+
+#define env_change() (++ast.env_serial)
+
+typedef struct _venv_ Evar_t;
+struct _venv_
+{
+ union
+ {
+ Evar_t *next;
+ char *ptr;
+ } un;
+ Dtlink_t link;
+ int index;
+};
+
+typedef struct _env_
+{
+ Dt_t *dt;
+ Evar_t *freelist;
+ char **env;
+ int count;
+ int extra;
+ int max;
+ int flags;
+} Env_t;
+
+#define _BLD_env 1
+#include <env.h>
+
+#define ENV_VALID 2 /* set if env is valid */
+#define ENV_PMALLOC 1 /* set if Evar_t->un.ptr *s malloced */
+#define ENV_VMALLOC 2 /* set of Evar_t was malloced */
+#define ENV_BITS 3
+
+/*
+ * Compares the name portion of name=... only.
+ */
+static int compare(Dt_t *dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc)
+{
+ register int c,d;
+ const unsigned char *s1=(unsigned const char*)key1;
+ const unsigned char *s2=(unsigned const char*)key2;
+ while((c= *s1++) && c!='=' && c==*s2)
+ s2++;
+ if(c=='=')
+ c = 0;
+ if((d=*s2)=='=')
+ d = 0;
+ return(c-d);
+}
+
+static Dtdisc_t env_disc =
+{
+ 0, -1,
+ sizeof(char*),
+ 0,
+ 0,
+ compare
+};
+
+/*
+ * return a pointer to the environment in sorted order
+ * NULL is returned if there if there is nospace
+ */
+char **env_get(Env_t* ep)
+{
+ register Evar_t *vp;
+ register int n=ep->extra;
+ if(ep->flags&ENV_VALID)
+ return(ep->env+n);
+ if(ep->count > ep->max)
+ {
+ if(ep->flags&ENV_MALLOCED)
+ free((void*)ep->env);
+ if(!(ep->env = (char**)malloc(sizeof(char*)*(ep->count+1))))
+ return(0);
+ ep->flags |= ENV_MALLOCED;
+ ep->max = ep->count;
+ }
+ for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=(Evar_t*)dtnext(ep->dt,vp))
+ {
+ vp->index = (n<<ENV_BITS) | (vp->index&((1<<ENV_BITS)-1));
+ ep->env[n++] = vp->un.ptr;
+ }
+ ep->env[n] = 0;
+ ep->flags |= ENV_VALID;
+ environ = ep->env+ep->extra;
+ return(ep->env+ep->extra);
+}
+
+/*
+ * add name=value pair given by <str> to <ep>
+ * if malloced is set, the variable will be freed when reassigned
+ * The environment list may become invalidated
+ * Returns 1 for success, 0 for failure
+ */
+int env_add(Env_t *ep, const char *str, int flags)
+{
+ Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
+ if(vp && strcmp(str,vp->un.ptr)==0)
+ return(1);
+ if(flags&ENV_STRDUP)
+ str = strdup(str);
+ if(vp)
+ {
+ if(vp->index&ENV_PMALLOC)
+ free((void*)vp->un.ptr);
+ vp->un.ptr = (char*)str;
+ if(ep->env && (ep->flags&ENV_VALID))
+ ep->env[vp->index>>ENV_BITS] = vp->un.ptr;
+ }
+ else
+ {
+ ep->flags &= ~ENV_VALID;
+ if(vp = ep->freelist)
+ ep->freelist = vp->un.next;
+ else if(vp = newof((Evar_t*)0,Evar_t,2,0))
+ {
+ vp->index = ENV_VMALLOC;
+ ep->freelist = (vp+1);
+ ep->freelist->un.next = 0;
+ }
+ else
+ return(0);
+ vp->un.ptr = (void*)str;
+ if(!(vp=dtinsert(ep->dt,vp)))
+ return(0);
+ ep->count++;
+ }
+ if(flags)
+ vp->index |= ENV_PMALLOC;
+ else
+ vp->index &= ~ENV_PMALLOC;
+ env_change();
+ return(1);
+}
+
+/*
+ * delete name from <ep>
+ * The environment list may become invalidated
+ * Returns 1 for success, 0 for if name is not present
+ */
+int env_delete(Env_t *ep, const char *str)
+{
+ Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
+ if(!vp)
+ return(0);
+ ep->flags &= ~ENV_VALID;
+ if(vp->index&ENV_PMALLOC)
+ free((void*)vp->un.ptr);
+ dtdelete(ep->dt,vp);
+ vp->un.next = ep->freelist;
+ ep->freelist = vp;
+ env_change();
+ return(1);
+}
+
+/*
+ * open up a structure to support environment variables
+ * initialize with environment give by <envp>
+ * If <extra> > 0, <extra> slots will be left at beginning of
+ * environment list when env_get() is involed.
+ * If <extra>==ENV_USABLE, then the original environ can be
+ * used and returned. Otherwise, a new one will be returned
+ */
+Env_t *env_open(char **envp, int extra)
+{
+ char **env;
+ Env_t *ep;
+ Evar_t *vp;
+ int n=2;
+ if(!(ep = newof((Env_t*)0,Env_t,1,0)))
+ return(0);
+ if(!(ep->dt = dtopen(&env_disc,Dtoset)))
+ return(0);
+ if(env=envp)
+ {
+ while(*env++);
+ n = (env+2)-envp;
+ }
+ if(extra==ENV_STABLE)
+ {
+ ep->env = envp;
+ ep->max = n-1;
+ }
+ else
+ ep->count = ep->extra = extra;
+ ep->freelist = vp = newof((Evar_t*)0,Evar_t,n,0);
+ vp->index = ENV_VMALLOC;
+ while(--n>0)
+ {
+ vp->un.next = (vp+1);
+ vp++;
+ }
+ vp->un.next = 0;
+ if(env)
+ {
+ for(env=envp; *env; env++)
+ env_add(ep,*env,0);
+ }
+ return(ep);
+}
+
+/*
+ * close <ep> and free up all space used by it
+ */
+void env_close(Env_t *ep)
+{
+ Evar_t *vp, *vpnext,*top;
+ if(ep->env && (ep->flags&ENV_MALLOCED))
+ free((void*)ep->env);
+ for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=vpnext)
+ {
+ vpnext = (Evar_t*)dtnext(ep->dt,vp);
+ env_delete(ep,vp->un.ptr);
+ }
+ for(top=0,vp = ep->freelist; vp; vp = vpnext)
+ {
+ vpnext = vp->un.next;
+ if(vp->index&ENV_VMALLOC)
+ {
+ vp->un.next = top;
+ top = vp;
+ }
+ }
+ for(vp=top; vp; vp = vpnext)
+ {
+ vpnext = vp->un.next;
+ free((void*)vp);
+ }
+ dtclose(ep->dt);
+}
diff --git a/src/cmd/ksh93/sh/expand.c b/src/cmd/ksh93/sh/expand.c
new file mode 100644
index 0000000..40c3dd1
--- /dev/null
+++ b/src/cmd/ksh93/sh/expand.c
@@ -0,0 +1,468 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * File name expansion
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#if KSHELL
+# include "defs.h"
+# include "variables.h"
+# include "test.h"
+#else
+# include <ast.h>
+# include <ctype.h>
+# include <setjmp.h>
+#endif /* KSHELL */
+#include <glob.h>
+#include <ls.h>
+#include <stak.h>
+#include <ast_dir.h>
+#include "io.h"
+#include "path.h"
+
+#if !SHOPT_BRACEPAT
+# define SHOPT_BRACEPAT 0
+#endif
+
+#if KSHELL
+# define argbegin argnxt.cp
+ static const char *sufstr;
+ static int suflen;
+ static int scantree(Dt_t*,const char*, struct argnod**);
+#else
+# define sh_sigcheck(sig) (0)
+# define sh_access access
+# define suflen 0
+#endif /* KSHELL */
+
+
+/*
+ * This routine builds a list of files that match a given pathname
+ * Uses external routine strgrpmatch() to match each component
+ * A leading . must match explicitly
+ *
+ */
+
+#ifndef GLOB_AUGMENTED
+# define GLOB_AUGMENTED 0
+#endif
+
+#define GLOB_RESCAN 1
+#define globptr() ((struct glob*)membase)
+
+static struct glob *membase;
+
+#if GLOB_VERSION >= 20010916L
+static char *nextdir(glob_t *gp, char *dir)
+{
+ Shell_t *shp = sh_getinterp();
+ Pathcomp_t *pp = (Pathcomp_t*)gp->gl_handle;
+ if(!dir)
+ pp = path_get(shp,"");
+ else
+ pp = pp->next;
+ gp->gl_handle = (void*)pp;
+ if(pp)
+ return(pp->name);
+ return(0);
+}
+#endif
+
+int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
+{
+ glob_t gdata;
+ register struct argnod *ap;
+ register glob_t *gp= &gdata;
+ register int flags,extra=0;
+#if SHOPT_BASH
+ register int off;
+ register char *sp, *cp, *cp2;
+#endif
+ sh_stats(STAT_GLOBS);
+ memset(gp,0,sizeof(gdata));
+ flags = GLOB_GROUP|GLOB_AUGMENTED|GLOB_NOCHECK|GLOB_NOSORT|GLOB_STACK|GLOB_LIST|GLOB_DISC;
+ if(sh_isoption(SH_MARKDIRS))
+ flags |= GLOB_MARK;
+ if(sh_isoption(SH_GLOBSTARS))
+ flags |= GLOB_STARSTAR;
+#if SHOPT_BASH
+#if 0
+ if(sh_isoption(SH_BASH) && !sh_isoption(SH_EXTGLOB))
+ flags &= ~GLOB_AUGMENTED;
+#endif
+ if(sh_isoption(SH_NULLGLOB))
+ flags &= ~GLOB_NOCHECK;
+ if(sh_isoption(SH_NOCASEGLOB))
+ flags |= GLOB_ICASE;
+#endif
+ if(sh_isstate(SH_COMPLETE))
+ {
+#if KSHELL
+ extra += scantree(shp->alias_tree,pattern,arghead);
+ extra += scantree(shp->fun_tree,pattern,arghead);
+# if GLOB_VERSION >= 20010916L
+ gp->gl_nextdir = nextdir;
+# endif
+#endif /* KSHELL */
+ flags |= GLOB_COMPLETE;
+ flags &= ~GLOB_NOCHECK;
+ }
+#if SHOPT_BASH
+ if(off = staktell())
+ sp = stakfreeze(0);
+ if(sh_isoption(SH_BASH))
+ {
+ /*
+ * For bash, FIGNORE is a colon separated list of suffixes to
+ * ignore when doing filename/command completion.
+ * GLOBIGNORE is similar to ksh FIGNORE, but colon separated
+ * instead of being an augmented shell pattern.
+ * Generate shell patterns out of those here.
+ */
+ if(sh_isstate(SH_FCOMPLETE))
+ cp=nv_getval(sh_scoped(shp,FIGNORENOD));
+ else
+ {
+ static Namval_t *GLOBIGNORENOD;
+ if(!GLOBIGNORENOD)
+ GLOBIGNORENOD = nv_open("GLOBIGNORE",shp->var_tree,0);
+ cp=nv_getval(sh_scoped(shp,GLOBIGNORENOD));
+ }
+ if(cp)
+ {
+ flags |= GLOB_AUGMENTED;
+ stakputs("@(");
+ if(!sh_isstate(SH_FCOMPLETE))
+ {
+ stakputs(cp);
+ for(cp=stakptr(off); *cp; cp++)
+ if(*cp == ':')
+ *cp='|';
+ }
+ else
+ {
+ cp2 = strtok(cp, ":");
+ if(!cp2)
+ cp2=cp;
+ do
+ {
+ stakputc('*');
+ stakputs(cp2);
+ if(cp2 = strtok(NULL, ":"))
+ {
+ *(cp2-1)=':';
+ stakputc('|');
+ }
+ } while(cp2);
+ }
+ stakputc(')');
+ gp->gl_fignore = stakfreeze(1);
+ }
+ else if(!sh_isstate(SH_FCOMPLETE) && sh_isoption(SH_DOTGLOB))
+ gp->gl_fignore = "";
+ }
+ else
+#endif
+ gp->gl_fignore = nv_getval(sh_scoped(shp,FIGNORENOD));
+ if(suflen)
+ gp->gl_suffix = sufstr;
+ gp->gl_intr = &shp->trapnote;
+ suflen = 0;
+ if(memcmp(pattern,"~(N",3)==0)
+ flags &= ~GLOB_NOCHECK;
+ glob(pattern, flags, 0, gp);
+#if SHOPT_BASH
+ if(off)
+ stakset(sp,off);
+ else
+ stakseek(0);
+#endif
+ sh_sigcheck(shp);
+ for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap)
+ {
+ ap->argchn.ap = ap->argnxt.ap;
+ if(!ap->argnxt.ap)
+ ap->argchn.ap = *arghead;
+ }
+ if(gp->gl_list)
+ *arghead = (struct argnod*)gp->gl_list;
+ return(gp->gl_pathc+extra);
+}
+
+#if KSHELL
+
+/*
+ * scan tree and add each name that matches the given pattern
+ */
+static int scantree(Dt_t *tree, const char *pattern, struct argnod **arghead)
+{
+ register Namval_t *np;
+ register struct argnod *ap;
+ register int nmatch=0;
+ register char *cp;
+ np = (Namval_t*)dtfirst(tree);
+ for(;np && !nv_isnull(np);(np = (Namval_t*)dtnext(tree,np)))
+ {
+ if(strmatch(cp=nv_name(np),pattern))
+ {
+ ap = (struct argnod*)stakseek(ARGVAL);
+ stakputs(cp);
+ ap = (struct argnod*)stakfreeze(1);
+ ap->argbegin = NIL(char*);
+ ap->argchn.ap = *arghead;
+ ap->argflag = ARG_RAW|ARG_MAKE;
+ *arghead = ap;
+ nmatch++;
+ }
+ }
+ return(nmatch);
+}
+
+/*
+ * file name completion
+ * generate the list of files found by adding an suffix to end of name
+ * The number of matches is returned
+ */
+
+int path_complete(Shell_t *shp,const char *name,register const char *suffix, struct argnod **arghead)
+{
+ sufstr = suffix;
+ suflen = strlen(suffix);
+ return(path_expand(shp,name,arghead));
+}
+
+#endif
+
+#if SHOPT_BRACEPAT
+
+static int checkfmt(Sfio_t* sp, void* vp, Sffmt_t* fp)
+{
+ return -1;
+}
+
+int path_generate(Shell_t *shp,struct argnod *todo, struct argnod **arghead)
+/*@
+ assume todo!=0;
+ return count satisfying count>=1;
+@*/
+{
+ register char *cp;
+ register int brace;
+ register struct argnod *ap;
+ struct argnod *top = 0;
+ struct argnod *apin;
+ char *pat, *rescan;
+ char *format;
+ char comma, range=0;
+ int first, last, incr, count = 0;
+ char tmp[32], end[1];
+ todo->argchn.ap = 0;
+again:
+ apin = ap = todo;
+ todo = ap->argchn.ap;
+ cp = ap->argval;
+ range = comma = brace = 0;
+ /* first search for {...,...} */
+ while(1) switch(*cp++)
+ {
+ case '{':
+ if(brace++==0)
+ pat = cp;
+ break;
+ case '}':
+ if(--brace>0)
+ break;
+ if(brace==0 && comma && *cp!='(')
+ goto endloop1;
+ comma = brace = 0;
+ break;
+ case '.':
+ if(brace==1 && *cp=='.')
+ {
+ char *endc;
+ incr = 1;
+ if(isdigit(*pat) || *pat=='+' || *pat=='-')
+ {
+ first = strtol(pat,&endc,0);
+ if(endc==(cp-1))
+ {
+ last = strtol(cp+1,&endc,0);
+ if(*endc=='.' && endc[1]=='.')
+ incr = strtol(endc+2,&endc,0);
+ else if(last<first)
+ incr = -1;
+ if(incr)
+ {
+ if(*endc=='%')
+ {
+ Sffmt_t fmt;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.version = SFIO_VERSION;
+ fmt.form = endc;
+ fmt.extf = checkfmt;
+ sfprintf(sfstdout, "%!", &fmt);
+ if(!(fmt.flags&(SFFMT_LLONG|SFFMT_LDOUBLE)))
+ switch (fmt.fmt)
+ {
+ case 'c':
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ format = endc;
+ endc = fmt.form;
+ break;
+ }
+ }
+ else
+ format = "%d";
+ if(*endc=='}')
+ {
+ cp = endc+1;
+ range = 2;
+ goto endloop1;
+ }
+ }
+ }
+ }
+ else if((cp[2]=='}' || cp[2]=='.' && cp[3]=='.') && ((*pat>='a' && *pat<='z' && cp[1]>='a' && cp[1]<='z') || (*pat>='A' && *pat<='Z' && cp[1]>='A' && cp[1]<='Z')))
+ {
+ first = *pat;
+ last = cp[1];
+ cp += 2;
+ if(*cp=='.')
+ {
+ incr = strtol(cp+2,&endc,0);
+ cp = endc;
+ }
+ else if(first>last)
+ incr = -1;
+ if(incr && *cp=='}')
+ {
+ cp++;
+ range = 1;
+ goto endloop1;
+ }
+ }
+ cp++;
+ }
+ break;
+ case ',':
+ if(brace==1)
+ comma = 1;
+ break;
+ case '\\':
+ cp++;
+ break;
+ case 0:
+ /* insert on stack */
+ ap->argchn.ap = top;
+ top = ap;
+ if(todo)
+ goto again;
+ for(; ap; ap=apin)
+ {
+ apin = ap->argchn.ap;
+ if(!sh_isoption(SH_NOGLOB))
+ brace=path_expand(shp,ap->argval,arghead);
+ else
+ {
+ ap->argchn.ap = *arghead;
+ *arghead = ap;
+ brace=1;
+ }
+ if(brace)
+ {
+ count += brace;
+ (*arghead)->argflag |= ARG_MAKE;
+ }
+ }
+ return(count);
+ }
+endloop1:
+ rescan = cp;
+ cp = pat-1;
+ *cp = 0;
+ while(1)
+ {
+ brace = 0;
+ if(range)
+ {
+ if(range==1)
+ {
+ pat[0] = first;
+ cp = &pat[1];
+ }
+ else
+ {
+ *(rescan - 1) = 0;
+ sfsprintf(pat=tmp,sizeof(tmp),format,first);
+ *(rescan - 1) = '}';
+ *(cp = end) = 0;
+ }
+ if(incr*(first+incr) > last*incr)
+ *cp = '}';
+ else
+ first += incr;
+ }
+ /* generate each pattern and put on the todo list */
+ else while(1) switch(*++cp)
+ {
+ case '\\':
+ cp++;
+ break;
+ case '{':
+ brace++;
+ break;
+ case ',':
+ if(brace==0)
+ goto endloop2;
+ break;
+ case '}':
+ if(--brace<0)
+ goto endloop2;
+ }
+ endloop2:
+ brace = *cp;
+ *cp = 0;
+ sh_sigcheck(shp);
+ ap = (struct argnod*)stakseek(ARGVAL);
+ ap->argflag = ARG_RAW;
+ ap->argchn.ap = todo;
+ stakputs(apin->argval);
+ stakputs(pat);
+ stakputs(rescan);
+ todo = ap = (struct argnod*)stakfreeze(1);
+ if(brace == '}')
+ break;
+ if(!range)
+ pat = cp+1;
+ }
+ goto again;
+}
+
+#endif /* SHOPT_BRACEPAT */
diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c
new file mode 100644
index 0000000..2d22e42
--- /dev/null
+++ b/src/cmd/ksh93/sh/fault.c
@@ -0,0 +1,672 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Fault handling routines
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include "io.h"
+#include "history.h"
+#include "shlex.h"
+#include "variables.h"
+#include "jobs.h"
+#include "path.h"
+#include "builtins.h"
+#include "ulimit.h"
+
+#define abortsig(sig) (sig==SIGABRT || sig==SIGBUS || sig==SIGILL || sig==SIGSEGV)
+
+static char indone;
+static int cursig = -1;
+
+#if !_std_malloc
+# include <vmalloc.h>
+#endif
+#if defined(VMFL) && (VMALLOC_VERSION>=20031205L)
+ /*
+ * This exception handler is called after vmalloc() unlocks the region
+ */
+ static int malloc_done(Vmalloc_t* vm, int type, Void_t* val, Vmdisc_t* dp)
+ {
+ dp->exceptf = 0;
+ sh_exit(SH_EXITSIG);
+ return(0);
+ }
+#endif
+
+/*
+ * Most signals caught or ignored by the shell come here
+*/
+void sh_fault(register int sig)
+{
+ register Shell_t *shp = sh_getinterp();
+ register int flag=0;
+ register char *trap;
+ register struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ int action=0;
+ /* reset handler */
+ if(!(sig&SH_TRAP))
+ signal(sig, sh_fault);
+ sig &= ~SH_TRAP;
+#ifdef SIGWINCH
+ if(sig==SIGWINCH)
+ {
+ int rows=0, cols=0;
+ int32_t v;
+ astwinsize(2,&rows,&cols);
+ if(v = cols)
+ nv_putval(COLUMNS, (char*)&v, NV_INT32|NV_RDONLY);
+ if(v = rows)
+ nv_putval(LINES, (char*)&v, NV_INT32|NV_RDONLY);
+ shp->winch++;
+ }
+#endif /* SIGWINCH */
+ trap = shp->st.trapcom[sig];
+ if(shp->savesig)
+ {
+ /* critical region, save and process later */
+ if(!(shp->sigflag[sig]&SH_SIGIGNORE))
+ shp->savesig = sig;
+ return;
+ }
+ if(sig==SIGALRM && shp->bltinfun==b_sleep)
+ {
+ if(trap && *trap)
+ {
+ shp->trapnote |= SH_SIGTRAP;
+ shp->sigflag[sig] |= SH_SIGTRAP;
+ }
+ return;
+ }
+ if(shp->subshell && trap && sig!=SIGINT && sig!=SIGQUIT && sig!=SIGWINCH && sig!=SIGCONT)
+ {
+ shp->exitval = SH_EXITSIG|sig;
+ sh_subfork();
+ shp->exitval = 0;
+ return;
+ }
+ /* handle ignored signals */
+ if(trap && *trap==0)
+ return;
+ flag = shp->sigflag[sig]&~SH_SIGOFF;
+ if(!trap)
+ {
+ if(sig==SIGINT && (shp->trapnote&SH_SIGIGNORE))
+ return;
+ if(flag&SH_SIGIGNORE)
+ {
+ if(shp->subshell)
+ shp->ignsig = sig;
+ sigrelease(sig);
+ return;
+ }
+ if(flag&SH_SIGDONE)
+ {
+ void *ptr=0;
+ if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! shp->subshell)
+ {
+ /* check for TERM signal between fork/exec */
+ if(sig==SIGTERM && job.in_critical)
+ shp->trapnote |= SH_SIGTERM;
+ return;
+ }
+ shp->lastsig = sig;
+ sigrelease(sig);
+ if(pp->mode != SH_JMPSUB)
+ {
+ if(pp->mode < SH_JMPSUB)
+ pp->mode = shp->subshell?SH_JMPSUB:SH_JMPFUN;
+ else
+ pp->mode = SH_JMPEXIT;
+ }
+ if(shp->subshell)
+ sh_exit(SH_EXITSIG);
+ if(sig==SIGABRT || (abortsig(sig) && (ptr = malloc(1))))
+ {
+ if(ptr)
+ free(ptr);
+ sh_done(shp,sig);
+ }
+ /* mark signal and continue */
+ shp->trapnote |= SH_SIGSET;
+ if(sig <= shp->gd->sigmax)
+ shp->sigflag[sig] |= SH_SIGSET;
+#if defined(VMFL) && (VMALLOC_VERSION>=20031205L)
+ if(abortsig(sig))
+ {
+ /* abort inside malloc, process when malloc returns */
+ /* VMFL defined when using vmalloc() */
+ Vmdisc_t* dp = vmdisc(Vmregion,0);
+ if(dp)
+ dp->exceptf = malloc_done;
+ }
+#endif
+ return;
+ }
+ }
+ errno = 0;
+ if(pp->mode==SH_JMPCMD || (pp->mode==1 && shp->bltinfun) && !(flag&SH_SIGIGNORE))
+ shp->lastsig = sig;
+ if(trap)
+ {
+ /*
+ * propogate signal to foreground group
+ */
+ if(sig==SIGHUP && job.curpgid)
+ killpg(job.curpgid,SIGHUP);
+ flag = SH_SIGTRAP;
+ }
+ else
+ {
+ shp->lastsig = sig;
+ flag = SH_SIGSET;
+#ifdef SIGTSTP
+ if(sig==SIGTSTP)
+ {
+ shp->trapnote |= SH_SIGTSTP;
+ if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
+ {
+ sigrelease(sig);
+ sh_exit(SH_EXITSIG);
+ flag = 0;
+ }
+ }
+#endif /* SIGTSTP */
+ }
+#ifdef ERROR_NOTIFY
+ if((error_info.flags&ERROR_NOTIFY) && shp->bltinfun)
+ action = (*shp->bltinfun)(-sig,(char**)0,(void*)0);
+ if(action>0)
+ return;
+#endif
+ if(shp->bltinfun && shp->bltindata.notify)
+ {
+ shp->bltindata.sigset = 1;
+ return;
+ }
+ shp->trapnote |= flag;
+ if(sig <= shp->gd->sigmax)
+ shp->sigflag[sig] |= flag;
+ if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
+ {
+ if(action<0)
+ return;
+ sigrelease(sig);
+ sh_exit(SH_EXITSIG);
+ }
+}
+
+/*
+ * initialize signal handling
+ */
+void sh_siginit(void *ptr)
+{
+ Shell_t *shp = (Shell_t*)ptr;
+ register int sig, n;
+ register const struct shtable2 *tp = shtab_signals;
+ sig_begin();
+ /* find the largest signal number in the table */
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ if ((n = SIGRTMIN) > 0 && (sig = SIGRTMAX) > n && sig < SH_TRAP)
+ {
+ shp->gd->sigruntime[SH_SIGRTMIN] = n;
+ shp->gd->sigruntime[SH_SIGRTMAX] = sig;
+ }
+#endif /* SIGRTMIN && SIGRTMAX */
+ n = SIGTERM;
+ while(*tp->sh_name)
+ {
+ sig = (tp->sh_number&((1<<SH_SIGBITS)-1));
+ if (!(sig-- & SH_TRAP))
+ {
+ if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME)
+ sig = shp->gd->sigruntime[sig];
+ if(sig>n && sig<SH_TRAP)
+ n = sig;
+ }
+ tp++;
+ }
+ shp->gd->sigmax = n++;
+ shp->st.trapcom = (char**)calloc(n,sizeof(char*));
+ shp->sigflag = (unsigned char*)calloc(n,1);
+ shp->gd->sigmsg = (char**)calloc(n,sizeof(char*));
+ for(tp=shtab_signals; sig=tp->sh_number; tp++)
+ {
+ n = (sig>>SH_SIGBITS);
+ if((sig &= ((1<<SH_SIGBITS)-1)) > (shp->gd->sigmax+1))
+ continue;
+ sig--;
+ if(n&SH_SIGRUNTIME)
+ sig = shp->gd->sigruntime[sig];
+ if(sig>=0)
+ {
+ shp->sigflag[sig] = n;
+ if(*tp->sh_name)
+ shp->gd->sigmsg[sig] = (char*)tp->sh_value;
+ }
+ }
+}
+
+/*
+ * Turn on trap handler for signal <sig>
+ */
+void sh_sigtrap(register int sig)
+{
+ register int flag;
+ void (*fun)(int);
+ sh.st.otrapcom = 0;
+ if(sig==0)
+ sh_sigdone();
+ else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF)))
+ {
+ /* don't set signal if already set or off by parent */
+ if((fun=signal(sig,sh_fault))==SIG_IGN)
+ {
+ signal(sig,SIG_IGN);
+ flag |= SH_SIGOFF;
+ }
+ else
+ {
+ flag |= SH_SIGFAULT;
+ if(sig==SIGALRM && fun!=SIG_DFL && fun!=sh_fault)
+ signal(sig,fun);
+ }
+ flag &= ~(SH_SIGSET|SH_SIGTRAP);
+ sh.sigflag[sig] = flag;
+ }
+}
+
+/*
+ * set signal handler so sh_done is called for all caught signals
+ */
+void sh_sigdone(void)
+{
+ register int flag, sig = shgd->sigmax;
+ sh.sigflag[0] |= SH_SIGFAULT;
+ for(sig=shgd->sigmax; sig>0; sig--)
+ {
+ flag = sh.sigflag[sig];
+ if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF)))
+ sh_sigtrap(sig);
+ }
+}
+
+/*
+ * Restore to default signals
+ * Free the trap strings if mode is non-zero
+ * If mode>1 then ignored traps cause signal to be ignored
+ */
+void sh_sigreset(register int mode)
+{
+ register char *trap;
+ register int flag, sig=sh.st.trapmax;
+ while(sig-- > 0)
+ {
+ if(trap=sh.st.trapcom[sig])
+ {
+ flag = sh.sigflag[sig]&~(SH_SIGTRAP|SH_SIGSET);
+ if(*trap)
+ {
+ if(mode)
+ free(trap);
+ sh.st.trapcom[sig] = 0;
+ }
+ else if(sig && mode>1)
+ {
+ if(sig!=SIGCHLD)
+ signal(sig,SIG_IGN);
+ flag &= ~SH_SIGFAULT;
+ flag |= SH_SIGOFF;
+ }
+ sh.sigflag[sig] = flag;
+ }
+ }
+ for(sig=SH_DEBUGTRAP-1;sig>=0;sig--)
+ {
+ if(trap=sh.st.trap[sig])
+ {
+ if(mode)
+ free(trap);
+ sh.st.trap[sig] = 0;
+ }
+
+ }
+ sh.st.trapcom[0] = 0;
+ if(mode)
+ sh.st.trapmax = 0;
+ sh.trapnote=0;
+}
+
+/*
+ * free up trap if set and restore signal handler if modified
+ */
+void sh_sigclear(register int sig)
+{
+ register int flag = sh.sigflag[sig];
+ register char *trap;
+ sh.st.otrapcom=0;
+ if(!(flag&SH_SIGFAULT))
+ return;
+ flag &= ~(SH_SIGTRAP|SH_SIGSET);
+ if(trap=sh.st.trapcom[sig])
+ {
+ if(!sh.subshell)
+ free(trap);
+ sh.st.trapcom[sig]=0;
+ }
+ sh.sigflag[sig] = flag;
+}
+
+/*
+ * check for traps
+ */
+
+void sh_chktrap(Shell_t* shp)
+{
+ register int sig=shp->st.trapmax;
+ register char *trap;
+ if(!(shp->trapnote&~SH_SIGIGNORE))
+ sig=0;
+ shp->trapnote &= ~SH_SIGTRAP;
+ /* execute errexit trap first */
+ if(sh_isstate(SH_ERREXIT) && shp->exitval)
+ {
+ int sav_trapnote = shp->trapnote;
+ shp->trapnote &= ~SH_SIGSET;
+ if(shp->st.trap[SH_ERRTRAP])
+ {
+ trap = shp->st.trap[SH_ERRTRAP];
+ shp->st.trap[SH_ERRTRAP] = 0;
+ sh_trap(trap,0);
+ shp->st.trap[SH_ERRTRAP] = trap;
+ }
+ shp->trapnote = sav_trapnote;
+ if(sh_isoption(SH_ERREXIT))
+ {
+ struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ pp->mode = SH_JMPEXIT;
+ sh_exit(shp->exitval);
+ }
+ }
+ if(shp->sigflag[SIGALRM]&SH_SIGALRM)
+ sh_timetraps(shp);
+#ifdef SHOPT_BGX
+ if((shp->sigflag[SIGCHLD]&SH_SIGTRAP) && shp->st.trapcom[SIGCHLD])
+ job_chldtrap(shp,shp->st.trapcom[SIGCHLD],1);
+#endif /* SHOPT_BGX */
+ while(--sig>=0)
+ {
+ if(sig==cursig)
+ continue;
+#ifdef SHOPT_BGX
+ if(sig==SIGCHLD)
+ continue;
+#endif /* SHOPT_BGX */
+ if(shp->sigflag[sig]&SH_SIGTRAP)
+ {
+ shp->sigflag[sig] &= ~SH_SIGTRAP;
+ if(trap=shp->st.trapcom[sig])
+ {
+ cursig = sig;
+ sh_trap(trap,0);
+ cursig = -1;
+ }
+ }
+ }
+}
+
+
+/*
+ * parse and execute the given trap string, stream or tree depending on mode
+ * mode==0 for string, mode==1 for stream, mode==2 for parse tree
+ */
+int sh_trap(const char *trap, int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ int jmpval, savxit = shp->exitval;
+ int was_history = sh_isstate(SH_HISTORY);
+ int was_verbose = sh_isstate(SH_VERBOSE);
+ int staktop = staktell();
+ char *savptr = stakfreeze(0);
+ char ifstable[256];
+ struct checkpt buff;
+ Fcin_t savefc;
+ fcsave(&savefc);
+ memcpy(ifstable,shp->ifstable,sizeof(ifstable));
+ sh_offstate(SH_HISTORY);
+ sh_offstate(SH_VERBOSE);
+ shp->intrap++;
+ sh_pushcontext(shp,&buff,SH_JMPTRAP);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval == 0)
+ {
+ if(mode==2)
+ sh_exec((Shnode_t*)trap,sh_isstate(SH_ERREXIT));
+ else
+ {
+ Sfio_t *sp;
+ if(mode)
+ sp = (Sfio_t*)trap;
+ else
+ sp = sfopen(NIL(Sfio_t*),trap,"s");
+ sh_eval(sp,0);
+ }
+ }
+ else if(indone)
+ {
+ if(jmpval==SH_JMPSCRIPT)
+ indone=0;
+ else
+ {
+ if(jmpval==SH_JMPEXIT)
+ savxit = shp->exitval;
+ jmpval=SH_JMPTRAP;
+ }
+ }
+ sh_popcontext(shp,&buff);
+ shp->intrap--;
+ sfsync(shp->outpool);
+ if(!shp->indebug && jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
+ shp->exitval=savxit;
+ stakset(savptr,staktop);
+ fcrestore(&savefc);
+ memcpy(shp->ifstable,ifstable,sizeof(ifstable));
+ if(was_history)
+ sh_onstate(SH_HISTORY);
+ if(was_verbose)
+ sh_onstate(SH_VERBOSE);
+ exitset();
+ if(jmpval>SH_JMPTRAP && (((struct checkpt*)shp->jmpbuffer)->prev || ((struct checkpt*)shp->jmpbuffer)->mode==SH_JMPSCRIPT))
+ siglongjmp(*shp->jmplist,jmpval);
+ return(shp->exitval);
+}
+
+/*
+ * exit the current scope and jump to an earlier one based on pp->mode
+ */
+void sh_exit(register int xno)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ register int sig=0;
+ register Sfio_t* pool;
+ shp->exitval=xno;
+ if(xno==SH_EXITSIG)
+ shp->exitval |= (sig=shp->lastsig);
+ if(pp && pp->mode>1)
+ cursig = -1;
+#ifdef SIGTSTP
+ if(shp->trapnote&SH_SIGTSTP)
+ {
+ /* ^Z detected by the shell */
+ shp->trapnote = 0;
+ shp->sigflag[SIGTSTP] = 0;
+ if(!shp->subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK))
+ return;
+ if(sh_isstate(SH_TIMING))
+ return;
+ /* Handles ^Z for shell builtins, subshells, and functs */
+ shp->lastsig = 0;
+ sh_onstate(SH_MONITOR);
+ sh_offstate(SH_STOPOK);
+ shp->trapnote = 0;
+ if(!shp->subshell && (sig=sh_fork(shp,0,NIL(int*))))
+ {
+ job.curpgid = 0;
+ job.parent = (pid_t)-1;
+ job_wait(sig);
+ job.parent = 0;
+ shp->sigflag[SIGTSTP] = 0;
+ /* wait for child to stop */
+ shp->exitval = (SH_EXITSIG|SIGTSTP);
+ /* return to prompt mode */
+ pp->mode = SH_JMPERREXIT;
+ }
+ else
+ {
+ if(shp->subshell)
+ sh_subfork();
+ /* child process, put to sleep */
+ sh_offstate(SH_STOPOK);
+ sh_offstate(SH_MONITOR);
+ shp->sigflag[SIGTSTP] = 0;
+ /* stop child job */
+ killpg(job.curpgid,SIGTSTP);
+ /* child resumes */
+ job_clear();
+ shp->forked = 1;
+ shp->exitval = (xno&SH_EXITMASK);
+ return;
+ }
+ }
+#endif /* SIGTSTP */
+ /* unlock output pool */
+ sh_offstate(SH_NOTRACK);
+ if(!(pool=sfpool(NIL(Sfio_t*),shp->outpool,SF_WRITE)))
+ pool = shp->outpool; /* can't happen? */
+ sfclrlock(pool);
+#ifdef SIGPIPE
+ if(shp->lastsig==SIGPIPE)
+ sfpurge(pool);
+#endif /* SIGPIPE */
+ sfclrlock(sfstdin);
+ if(!pp)
+ sh_done(shp,sig);
+ shp->prefix = 0;
+#if SHOPT_TYPEDEF
+ shp->mktype = 0;
+#endif /* SHOPT_TYPEDEF*/
+ if(job.in_critical)
+ job_unlock();
+ if(pp->mode == SH_JMPSCRIPT && !pp->prev)
+ sh_done(shp,sig);
+ if(pp->mode)
+ siglongjmp(pp->buff,pp->mode);
+}
+
+static void array_notify(Namval_t *np, void *data)
+{
+ Namarr_t *ap = nv_arrayptr(np);
+ NOT_USED(data);
+ if(ap && ap->fun)
+ (*ap->fun)(np, 0, NV_AFREE);
+}
+
+/*
+ * This is the exit routine for the shell
+ */
+
+void sh_done(void *ptr, register int sig)
+{
+ Shell_t *shp = (Shell_t*)ptr;
+ register char *t;
+ register int savxit = shp->exitval;
+ shp->trapnote = 0;
+ indone=1;
+ if(sig)
+ savxit = SH_EXITSIG|sig;
+ if(shp->userinit)
+ (*shp->userinit)(shp, -1);
+ if(t=shp->st.trapcom[0])
+ {
+ shp->st.trapcom[0]=0; /*should free but not long */
+ shp->oldexit = savxit;
+ sh_trap(t,0);
+ savxit = shp->exitval;
+ }
+ else
+ {
+ /* avoid recursive call for set -e */
+ sh_offstate(SH_ERREXIT);
+ sh_chktrap(shp);
+ }
+ nv_scan(shp->var_tree,array_notify,(void*)0,NV_ARRAY,NV_ARRAY);
+ sh_freeup(shp);
+#if SHOPT_ACCT
+ sh_accend();
+#endif /* SHOPT_ACCT */
+#if SHOPT_VSH || SHOPT_ESH
+ if(mbwide()||sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS))
+ tty_cooked(-1);
+#endif
+#ifdef JOBS
+ if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
+ job_walk(sfstderr,job_terminate,SIGHUP,NIL(char**));
+#endif /* JOBS */
+ job_close(shp);
+ if(nv_search("VMTRACE", shp->var_tree,0))
+ strmatch((char*)0,(char*)0);
+ sfsync((Sfio_t*)sfstdin);
+ sfsync((Sfio_t*)shp->outpool);
+ sfsync((Sfio_t*)sfstdout);
+ if(savxit&SH_EXITSIG)
+ sig = savxit&SH_EXITMASK;
+ if(sig)
+ {
+ /* generate fault termination code */
+ if(RLIMIT_CORE!=RLIMIT_UNKNOWN)
+ {
+#ifdef _lib_getrlimit
+ struct rlimit rlp;
+ getrlimit(RLIMIT_CORE,&rlp);
+ rlp.rlim_cur = 0;
+ setrlimit(RLIMIT_CORE,&rlp);
+#else
+ vlimit(RLIMIT_CORE,0);
+#endif
+ }
+ signal(sig,SIG_DFL);
+ sigrelease(sig);
+ kill(getpid(),sig);
+ pause();
+ }
+#if SHOPT_KIA
+ if(sh_isoption(SH_NOEXEC))
+ kiaclose((Lex_t*)shp->lex_context);
+#endif /* SHOPT_KIA */
+ exit(savxit&SH_EXITMASK);
+}
+
diff --git a/src/cmd/ksh93/sh/fcin.c b/src/cmd/ksh93/sh/fcin.c
new file mode 100644
index 0000000..ea6ea6b
--- /dev/null
+++ b/src/cmd/ksh93/sh/fcin.c
@@ -0,0 +1,214 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Routines to implement fast character input
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include <fcin.h>
+
+Fcin_t _Fcin = {0};
+
+/*
+ * open stream <f> for fast character input
+ */
+int fcfopen(register Sfio_t* f)
+{
+ register int n;
+ char *buff;
+ Fcin_t save;
+ errno = 0;
+ _Fcin.fcbuff = _Fcin.fcptr;
+ _Fcin._fcfile = f;
+ fcsave(&save);
+ if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR)))
+ {
+ fcrestore(&save);
+ _Fcin.fcchar = 0;
+ _Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar;
+ _Fcin.fclast = 0;
+ _Fcin._fcfile = (Sfio_t*)0;
+ return(EOF);
+ }
+ n = sfvalue(f);
+ fcrestore(&save);
+ sfread(f,buff,0);
+ _Fcin.fcoff = sftell(f);;
+ buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR);
+ _Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n;
+ if(sffileno(f) >= 0)
+ *_Fcin.fclast = 0;
+ return(n);
+}
+
+
+/*
+ * With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and
+ * If _Fcin.fclast!=0, performs an sfreserve() for the next buffer.
+ * If a notify function has been set, it is called
+ * If last is non-zero, and the stream is a file, 0 is returned when
+ * the previous character is a 0 byte.
+ */
+int fcfill(void)
+{
+ register int n;
+ register Sfio_t *f;
+ register unsigned char *last=_Fcin.fclast, *ptr=_Fcin.fcptr;
+ if(!(f=fcfile()))
+ {
+ /* see whether pointer has passed null byte */
+ if(ptr>_Fcin.fcbuff && *--ptr==0)
+ _Fcin.fcptr=ptr;
+ else
+ _Fcin.fcoff = 0;
+ return(0);
+ }
+ if(last)
+ {
+ if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0)
+ return(0);
+ if(_Fcin.fcchar)
+ *last = _Fcin.fcchar;
+ if(ptr > last)
+ _Fcin.fcptr = ptr = last;
+ }
+ if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun)
+ (*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n,_Fcin.context);
+ sfread(f, (char*)_Fcin.fcbuff, n);
+ _Fcin.fcoff +=n;
+ _Fcin._fcfile = 0;
+ if(!last)
+ return(0);
+ else if(fcfopen(f) < 0)
+ return(EOF);
+ return(*_Fcin.fcptr++);
+}
+
+/*
+ * Synchronize and close the current stream
+ */
+int fcclose(void)
+{
+ register unsigned char *ptr;
+ if(_Fcin.fclast==0)
+ return(0);
+ if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0)
+ _Fcin.fcptr--;
+ if(_Fcin.fcchar)
+ *_Fcin.fclast = _Fcin.fcchar;
+ _Fcin.fclast = 0;
+ _Fcin.fcleft = 0;
+ return(fcfill());
+}
+
+/*
+ * Set the notify function that is called for each fcfill()
+ */
+void fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context)
+{
+ _Fcin.fcfun = fun;
+ _Fcin.context = context;
+}
+
+#ifdef __EXPORT__
+# define extern __EXPORT__
+#endif
+
+#undef fcsave
+extern void fcsave(Fcin_t *fp)
+{
+ *fp = _Fcin;
+}
+
+#undef fcrestore
+extern void fcrestore(Fcin_t *fp)
+{
+ _Fcin = *fp;
+}
+
+/* for testing purposes with small buffers */
+#if defined(IOBSIZE) && (IOBSIZE < 2*MB_LEN_MAX)
+# undef MB_LEN_MAX
+# define MB_LEN_MAX (IOBSIZE/2)
+#endif
+
+struct Extra
+{
+ unsigned char buff[2*MB_LEN_MAX];
+ unsigned char *next;
+};
+
+int _fcmbget(short *len)
+{
+ static struct Extra extra;
+ register int i, c, n;
+ if(_Fcin.fcleft)
+ {
+ if((c = mbsize(extra.next)) < 0)
+ c = 1;
+ if((_Fcin.fcleft -= c) <=0)
+ {
+ _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft;
+ _Fcin.fcleft = 0;
+ }
+ *len = c;
+ if(c==1)
+ c = *extra.next++;
+ else if(c==0)
+ _Fcin.fcleft = 0;
+ else
+ c = mbchar(extra.next);
+ return(c);
+ }
+ switch(*len = mbsize(_Fcin.fcptr))
+ {
+ case -1:
+ if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX)
+ {
+ memcpy(extra.buff, _Fcin.fcptr, n);
+ _Fcin.fcptr = _Fcin.fclast;
+ for(i=n; i < MB_LEN_MAX+n; i++)
+ {
+ if((extra.buff[i] = fcgetc(c))==0)
+ break;
+ }
+ _Fcin.fcleft = n;
+ extra.next = extra.buff;
+ return(fcmbget(len));
+ }
+ *len = 1;
+ /* fall through */
+ case 0:
+ case 1:
+ c=fcget();
+ break;
+ default:
+ c = mbchar(_Fcin.fcptr);
+ }
+ return(c);
+}
+
diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c
new file mode 100644
index 0000000..16e30df
--- /dev/null
+++ b/src/cmd/ksh93/sh/init.c
@@ -0,0 +1,2238 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ *
+ * Shell initialization
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <stak.h>
+#include <ccode.h>
+#include <pwd.h>
+#include <tmx.h>
+#include "variables.h"
+#include "path.h"
+#include "fault.h"
+#include "name.h"
+#include "edit.h"
+#include "jobs.h"
+#include "io.h"
+#include "shlex.h"
+#include "builtins.h"
+#include "FEATURE/time"
+#include "FEATURE/dynamic"
+#include "FEATURE/externs"
+#include "lexstates.h"
+#include "version.h"
+
+#if _hdr_wctype
+#include <ast_wchar.h>
+#include <wctype.h>
+#endif
+#if !_typ_wctrans_t
+#undef wctrans_t
+#define wctrans_t sh_wctrans_t
+typedef long wctrans_t;
+#endif
+#if !_lib_wctrans
+#undef wctrans
+#define wctrans sh_wctrans
+static wctrans_t wctrans(const char *name)
+{
+ if(strcmp(name,e_tolower)==0)
+ return(1);
+ else if(strcmp(name,e_toupper)==0)
+ return(2);
+ return(0);
+}
+#endif
+#if !_lib_towctrans
+#undef towctrans
+#define towctrans sh_towctrans
+static int towctrans(int c, wctrans_t t)
+{
+ if(t==1 && isupper(c))
+ c = tolower(c);
+ else if(t==2 && islower(c))
+ c = toupper(c);
+ return(c);
+}
+#endif
+
+char e_version[] = "\n@(#)$Id: Version "
+#if SHOPT_AUDIT
+#define ATTRS 1
+ "A"
+#endif
+#if SHOPT_BASH
+#define ATTRS 1
+ "B"
+#endif
+#if SHOPT_COSHELL
+#define ATTRS 1
+ "J"
+#else
+#if SHOPT_BGX
+#define ATTRS 1
+ "j"
+#endif
+#endif
+#if SHOPT_ACCT
+#define ATTRS 1
+ "L"
+#endif
+#if SHOPT_MULTIBYTE
+#define ATTRS 1
+ "M"
+#endif
+#if SHOPT_PFSH && _hdr_exec_attr
+#define ATTRS 1
+ "P"
+#endif
+#if SHOPT_REGRESS
+#define ATTRS 1
+ "R"
+#endif
+#if ATTRS
+ " "
+#endif
+ SH_RELEASE " $\0\n";
+
+#if SHOPT_BASH
+ extern void bash_init(Shell_t*,int);
+#endif
+
+#define RANDMASK 0x7fff
+
+#ifndef ARG_MAX
+# define ARG_MAX (1*1024*1024)
+#endif
+#ifndef CHILD_MAX
+# define CHILD_MAX (1*1024)
+#endif
+#ifndef CLK_TCK
+# define CLK_TCK 60
+#endif /* CLK_TCK */
+
+#ifndef environ
+ extern char **environ;
+#endif
+
+#undef getconf
+#define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0)
+
+struct seconds
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+};
+
+struct rand
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+ int32_t rand_last;
+};
+
+struct ifs
+{
+ Namfun_t hdr;
+ Namval_t *ifsnp;
+};
+
+struct match
+{
+ Namfun_t hdr;
+ const char *v;
+ char *val;
+ char *rval[2];
+ int *match;
+ char node[NV_MINSZ+sizeof(char*)];
+ int first;
+ int vsize;
+ int nmatch;
+ int index;
+ int lastsub[2];
+};
+
+typedef struct _init_
+{
+ Shell_t *sh;
+#if SHOPT_FS_3D
+ Namfun_t VPATH_init;
+#endif /* SHOPT_FS_3D */
+ struct ifs IFS_init;
+ Namfun_t PATH_init;
+ Namfun_t FPATH_init;
+ Namfun_t CDPATH_init;
+ Namfun_t SHELL_init;
+ Namfun_t ENV_init;
+ Namfun_t VISUAL_init;
+ Namfun_t EDITOR_init;
+ Namfun_t HISTFILE_init;
+ Namfun_t HISTSIZE_init;
+ Namfun_t OPTINDEX_init;
+ struct seconds SECONDS_init;
+ struct rand RAND_init;
+ Namfun_t LINENO_init;
+ Namfun_t L_ARG_init;
+ Namfun_t SH_VERSION_init;
+ struct match SH_MATCH_init;
+ Namfun_t SH_MATH_init;
+#if SHOPT_COSHELL
+ Namfun_t SH_JOBPOOL_init;
+#endif /* SHOPT_COSHELL */
+#ifdef _hdr_locale
+ Namfun_t LC_TYPE_init;
+ Namfun_t LC_NUM_init;
+ Namfun_t LC_COLL_init;
+ Namfun_t LC_MSG_init;
+ Namfun_t LC_ALL_init;
+ Namfun_t LANG_init;
+#endif /* _hdr_locale */
+} Init_t;
+
+static Init_t *ip;
+static int lctype;
+static int nbltins;
+static void env_init(Shell_t*);
+static Init_t *nv_init(Shell_t*);
+static Dt_t *inittree(Shell_t*,const struct shtable2*);
+static int shlvl;
+
+#ifdef _WINIX
+# define EXE "?(.exe)"
+#else
+# define EXE
+#endif
+
+static int rand_shift;
+
+
+/*
+ * Invalidate all path name bindings
+ */
+static void rehash(register Namval_t *np,void *data)
+{
+ NOT_USED(data);
+ nv_onattr(np,NV_NOALIAS);
+}
+
+/*
+ * out of memory routine for stak routines
+ */
+static char *nospace(int unused)
+{
+ NOT_USED(unused);
+ errormsg(SH_DICT,ERROR_exit(3),e_nospace);
+ return(NIL(char*));
+}
+
+/* Trap for VISUAL and EDITOR variables */
+static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ register const char *cp, *name=nv_name(np);
+ register int newopt=0;
+ Shell_t *shp = nv_shell(np);
+ if(*name=='E' && nv_getval(sh_scoped(shp,VISINOD)))
+ goto done;
+ if(!(cp=val) && (*name=='E' || !(cp=nv_getval(sh_scoped(shp,EDITNOD)))))
+ goto done;
+ /* turn on vi or emacs option if editor name is either*/
+ cp = path_basename(cp);
+ if(strmatch(cp,"*[Vv][Ii]*"))
+ newopt=SH_VI;
+ else if(strmatch(cp,"*gmacs*"))
+ newopt=SH_GMACS;
+ else if(strmatch(cp,"*macs*"))
+ newopt=SH_EMACS;
+ if(newopt)
+ {
+ sh_offoption(SH_VI);
+ sh_offoption(SH_EMACS);
+ sh_offoption(SH_GMACS);
+ sh_onoption(newopt);
+ }
+done:
+ nv_putv(np, val, flags, fp);
+}
+
+/* Trap for HISTFILE and HISTSIZE variables */
+static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ void *histopen = shp->gd->hist_ptr;
+ char *cp;
+ if(val && histopen)
+ {
+ if(np==HISTFILE && (cp=nv_getval(np)) && strcmp(val,cp)==0)
+ return;
+ if(np==HISTSIZE && sh_arith(shp,val)==nv_getnum(HISTSIZE))
+ return;
+ hist_close(shp->gd->hist_ptr);
+ }
+ nv_putv(np, val, flags, fp);
+ if(histopen)
+ {
+ if(val)
+ sh_histinit(shp);
+ else
+ hist_close(histopen);
+ }
+}
+
+/* Trap for OPTINDEX */
+static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ shp->st.opterror = shp->st.optchar = 0;
+ nv_putv(np, val, flags, fp);
+ if(!val)
+ nv_disc(np,fp,NV_POP);
+}
+
+static Sfdouble_t nget_optindex(register Namval_t* np, Namfun_t *fp)
+{
+ return((Sfdouble_t)*np->nvalue.lp);
+}
+
+static Namfun_t *clone_optindex(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namfun_t *dp = (Namfun_t*)malloc(sizeof(Namfun_t));
+ memcpy((void*)dp,(void*)fp,sizeof(Namfun_t));
+ mp->nvalue.lp = np->nvalue.lp;
+ dp->nofree = 0;
+ return(dp);
+}
+
+
+/* Trap for restricted variables FPATH, PATH, SHELL, ENV */
+static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ int path_scoped = 0, fpath_scoped=0;
+ Pathcomp_t *pp;
+ char *name = nv_name(np);
+ if(!(flags&NV_RDONLY) && sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
+ if(np==PATHNOD || (path_scoped=(strcmp(name,PATHNOD->nvname)==0)))
+ {
+ nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
+ if(path_scoped && !val)
+ val = PATHNOD->nvalue.cp;
+ }
+ if(val && !(flags&NV_RDONLY) && np->nvalue.cp && strcmp(val,np->nvalue.cp)==0)
+ return;
+ if(np==FPATHNOD || (fpath_scoped=(strcmp(name,FPATHNOD->nvname)==0)))
+ shp->pathlist = (void*)path_unsetfpath(shp);
+ nv_putv(np, val, flags, fp);
+ shp->universe = 0;
+ if(shp->pathlist)
+ {
+ val = np->nvalue.cp;
+ if(np==PATHNOD || path_scoped)
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_PATH);
+ else if(val && (np==FPATHNOD || fpath_scoped))
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
+ else
+ return;
+ if(shp->pathlist = (void*)pp)
+ pp->shp = shp;
+ if(!val && (flags&NV_NOSCOPE))
+ {
+ Namval_t *mp = dtsearch(shp->var_tree,np);
+ if(mp && (val=nv_getval(mp)))
+ nv_putval(mp,val,NV_RDONLY);
+ }
+#if 0
+sfprintf(sfstderr,"%d: name=%s val=%s\n",getpid(),name,val);
+path_dump((Pathcomp_t*)shp->pathlist);
+#endif
+ }
+}
+
+static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Pathcomp_t *pp;
+ Shell_t *shp = nv_shell(np);
+ nv_putv(np, val, flags, fp);
+ if(!shp->cdpathlist)
+ return;
+ val = np->nvalue.cp;
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->cdpathlist,val,PATH_CDPATH);
+ if(shp->cdpathlist = (void*)pp)
+ pp->shp = shp;
+}
+
+#ifdef _hdr_locale
+ /*
+ * This function needs to be modified to handle international
+ * error message translations
+ */
+#if ERROR_VERSION >= 20000101L
+ static char* msg_translate(const char* catalog, const char* message)
+ {
+ NOT_USED(catalog);
+ return((char*)message);
+ }
+#else
+ static char* msg_translate(const char* message, int type)
+ {
+ NOT_USED(type);
+ return((char*)message);
+ }
+#endif
+
+ /* Trap for LC_ALL, LC_CTYPE, LC_MESSAGES, LC_COLLATE and LANG */
+ static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+ {
+ Shell_t *shp = nv_shell(np);
+ int type;
+ char *name = nv_name(np);
+ if(name==(LCALLNOD)->nvname)
+ type = LC_ALL;
+ else if(name==(LCTYPENOD)->nvname)
+ type = LC_CTYPE;
+ else if(name==(LCMSGNOD)->nvname)
+ type = LC_MESSAGES;
+ else if(name==(LCCOLLNOD)->nvname)
+ type = LC_COLLATE;
+ else if(name==(LCNUMNOD)->nvname)
+ type = LC_NUMERIC;
+#ifdef LC_LANG
+ else if(name==(LANGNOD)->nvname)
+ type = LC_LANG;
+#else
+#define LC_LANG LC_ALL
+ else if(name==(LANGNOD)->nvname && (!(name=nv_getval(LCALLNOD)) || !*name))
+ type = LC_LANG;
+#endif
+ else
+ type= -1;
+ if(!sh_isstate(SH_INIT) && (type>=0 || type==LC_ALL || type==LC_LANG))
+ {
+ char* r;
+#ifdef AST_LC_setenv
+ ast.locale.set |= AST_LC_setenv;
+#endif
+ r = setlocale(type,val?val:"");
+#ifdef AST_LC_setenv
+ ast.locale.set ^= AST_LC_setenv;
+#endif
+ if(!r && val)
+ {
+ if(!sh_isstate(SH_INIT) || shp->login_sh==0)
+ errormsg(SH_DICT,0,e_badlocale,val);
+ return;
+ }
+ }
+ nv_putv(np, val, flags, fp);
+ if(CC_NATIVE!=CC_ASCII && (type==LC_ALL || type==LC_LANG || type==LC_CTYPE))
+ {
+ if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN])
+ free((void*)sh_lexstates[ST_BEGIN]);
+ lctype++;
+ if(ast.locale.set&(1<<AST_LC_CTYPE))
+ {
+ register int c;
+ char *state[4];
+ sh_lexstates[ST_BEGIN] = state[0] = (char*)malloc(4*(1<<CHAR_BIT));
+ memcpy(state[0],sh_lexrstates[ST_BEGIN],(1<<CHAR_BIT));
+ sh_lexstates[ST_NAME] = state[1] = state[0] + (1<<CHAR_BIT);
+ memcpy(state[1],sh_lexrstates[ST_NAME],(1<<CHAR_BIT));
+ sh_lexstates[ST_DOL] = state[2] = state[1] + (1<<CHAR_BIT);
+ memcpy(state[2],sh_lexrstates[ST_DOL],(1<<CHAR_BIT));
+ sh_lexstates[ST_BRACE] = state[3] = state[2] + (1<<CHAR_BIT);
+ memcpy(state[3],sh_lexrstates[ST_BRACE],(1<<CHAR_BIT));
+ for(c=0; c<(1<<CHAR_BIT); c++)
+ {
+ if(state[0][c]!=S_REG)
+ continue;
+ if(state[2][c]!=S_ERR)
+ continue;
+ if(isblank(c))
+ {
+ state[0][c]=0;
+ state[1][c]=S_BREAK;
+ state[2][c]=S_BREAK;
+ continue;
+ }
+ if(!isalpha(c))
+ continue;
+ state[0][c]=S_NAME;
+ if(state[1][c]==S_REG)
+ state[1][c]=0;
+ state[2][c]=S_ALP;
+ if(state[3][c]==S_ERR)
+ state[3][c]=0;
+ }
+ }
+ else
+ {
+ sh_lexstates[ST_BEGIN]=(char*)sh_lexrstates[ST_BEGIN];
+ sh_lexstates[ST_NAME]=(char*)sh_lexrstates[ST_NAME];
+ sh_lexstates[ST_DOL]=(char*)sh_lexrstates[ST_DOL];
+ sh_lexstates[ST_BRACE]=(char*)sh_lexrstates[ST_BRACE];
+ }
+ }
+#if ERROR_VERSION < 20000101L
+ if(type==LC_ALL || type==LC_MESSAGES)
+ error_info.translate = msg_translate;
+#endif
+ }
+#endif /* _hdr_locale */
+
+/* Trap for IFS assignment and invalidates state table */
+static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ register struct ifs *ip = (struct ifs*)fp;
+ ip->ifsnp = 0;
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ {
+ free((void*)fp);
+ fp = 0;
+ }
+ }
+ if(val != np->nvalue.cp)
+ nv_putv(np, val, flags, fp);
+ if(!val)
+ {
+ if(fp)
+ fp->next = np->nvfun;
+ np->nvfun = fp;
+ }
+}
+
+/*
+ * This is the lookup function for IFS
+ * It keeps the sh.ifstable up to date
+ */
+static char* get_ifs(register Namval_t* np, Namfun_t *fp)
+{
+ register struct ifs *ip = (struct ifs*)fp;
+ register char *cp, *value;
+ register int c,n;
+ register Shell_t *shp = nv_shell(np);
+ value = nv_getv(np,fp);
+ if(np!=ip->ifsnp)
+ {
+ ip->ifsnp = np;
+ memset(shp->ifstable,0,(1<<CHAR_BIT));
+ if(cp=value)
+ {
+#if SHOPT_MULTIBYTE
+ while(n=mbsize(cp),c= *(unsigned char*)cp)
+#else
+ while(c= *(unsigned char*)cp++)
+#endif /* SHOPT_MULTIBYTE */
+ {
+#if SHOPT_MULTIBYTE
+ cp++;
+ if(n>1)
+ {
+ cp += (n-1);
+ shp->ifstable[c] = S_MBYTE;
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ n = S_DELIM;
+ if(c== *cp)
+ cp++;
+ else if(c=='\n')
+ n = S_NL;
+ else if(isspace(c))
+ n = S_SPACE;
+ shp->ifstable[c] = n;
+ }
+ }
+ else
+ {
+ shp->ifstable[' '] = shp->ifstable['\t'] = S_SPACE;
+ shp->ifstable['\n'] = S_NL;
+ }
+ }
+ return(value);
+}
+
+/*
+ * these functions are used to get and set the SECONDS variable
+ */
+#ifdef timeofday
+# define dtime(tp) ((double)((tp)->tv_sec)+1e-6*((double)((tp)->tv_usec)))
+# define tms timeval
+#else
+# define dtime(tp) (((double)times(tp))/shgd->lim.clk_tck)
+# define timeofday(a)
+#endif
+
+static void put_seconds(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ double d;
+ struct tms tp;
+ if(!val)
+ {
+ nv_putv(np, val, flags, fp);
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ return;
+ }
+ if(!np->nvalue.dp)
+ {
+ nv_setsize(np,3);
+ nv_onattr(np,NV_DOUBLE);
+ np->nvalue.dp = new_of(double,0);
+ }
+ nv_putv(np, val, flags, fp);
+ d = *np->nvalue.dp;
+ timeofday(&tp);
+ *np->nvalue.dp = dtime(&tp)-d;
+}
+
+static char* get_seconds(register Namval_t* np, Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ register int places = nv_size(np);
+ struct tms tp;
+ double d, offset = (np->nvalue.dp?*np->nvalue.dp:0);
+ NOT_USED(fp);
+ timeofday(&tp);
+ d = dtime(&tp)- offset;
+ sfprintf(shp->strbuf,"%.*f",places,d);
+ return(sfstruse(shp->strbuf));
+}
+
+static Sfdouble_t nget_seconds(register Namval_t* np, Namfun_t *fp)
+{
+ struct tms tp;
+ double offset = (np->nvalue.dp?*np->nvalue.dp:0);
+ NOT_USED(fp);
+ timeofday(&tp);
+ return(dtime(&tp)- offset);
+}
+
+/*
+ * These three functions are used to get and set the RANDOM variable
+ */
+static void put_rand(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct rand *rp = (struct rand*)fp;
+ register long n;
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ _nv_unset(np,0);
+ return;
+ }
+ if(flags&NV_INTEGER)
+ n = *(double*)val;
+ else
+ n = sh_arith(rp->sh,val);
+ srand((int)(n&RANDMASK));
+ rp->rand_last = -1;
+ if(!np->nvalue.lp)
+ np->nvalue.lp = &rp->rand_last;
+}
+
+/*
+ * get random number in range of 0 - 2**15
+ * never pick same number twice in a row
+ */
+static Sfdouble_t nget_rand(register Namval_t* np, Namfun_t *fp)
+{
+ register long cur, last= *np->nvalue.lp;
+ NOT_USED(fp);
+ do
+ cur = (rand()>>rand_shift)&RANDMASK;
+ while(cur==last);
+ *np->nvalue.lp = cur;
+ return((Sfdouble_t)cur);
+}
+
+static char* get_rand(register Namval_t* np, Namfun_t *fp)
+{
+ register long n = nget_rand(np,fp);
+ return(fmtbase(n, 10, 0));
+}
+
+/*
+ * These three routines are for LINENO
+ */
+static Sfdouble_t nget_lineno(Namval_t* np, Namfun_t *fp)
+{
+ double d=1;
+ if(error_info.line >0)
+ d = error_info.line;
+ else if(error_info.context && error_info.context->line>0)
+ d = error_info.context->line;
+ NOT_USED(np);
+ NOT_USED(fp);
+ return(d);
+}
+
+static void put_lineno(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ register long n;
+ Shell_t *shp = nv_shell(np);
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ _nv_unset(np,0);
+ return;
+ }
+ if(flags&NV_INTEGER)
+ n = *(double*)val;
+ else
+ n = sh_arith(shp,val);
+ shp->st.firstline += nget_lineno(np,fp)+1-n;
+}
+
+static char* get_lineno(register Namval_t* np, Namfun_t *fp)
+{
+ register long n = nget_lineno(np,fp);
+ return(fmtbase(n, 10, 0));
+}
+
+static char* get_lastarg(Namval_t* np, Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ char *cp;
+ int pid;
+ if(sh_isstate(SH_INIT) && (cp=shp->lastarg) && *cp=='*' && (pid=strtol(cp+1,&cp,10)) && *cp=='*')
+ nv_putval(np,(pid==shp->gd->ppid?cp+1:0),0);
+ return(shp->lastarg);
+}
+
+static void put_lastarg(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ if(flags&NV_INTEGER)
+ {
+ sfprintf(shp->strbuf,"%.*g",12,*((double*)val));
+ val = sfstruse(shp->strbuf);
+ }
+ if(val)
+ val = strdup(val);
+ if(shp->lastarg && !nv_isattr(np,NV_NOFREE))
+ free((void*)shp->lastarg);
+ else
+ nv_offattr(np,NV_NOFREE);
+ shp->lastarg = (char*)val;
+ nv_offattr(np,NV_EXPORT);
+ np->nvenv = 0;
+}
+
+static int hasgetdisc(register Namfun_t *fp)
+{
+ while(fp && !fp->disc->getnum && !fp->disc->getval)
+ fp = fp->next;
+ return(fp!=0);
+}
+
+/*
+ * store the most recent value for use in .sh.match
+ * treat .sh.match as a two dimensional array
+ */
+void sh_setmatch(Shell_t *shp,const char *v, int vsize, int nmatch, int match[],int index)
+{
+ struct match *mp = &ip->SH_MATCH_init;
+ Namval_t *np = nv_namptr(mp->node,0);
+ register int i,n,x, savesub=shp->subshell;
+ Namarr_t *ap = nv_arrayptr(SH_MATCHNOD);
+ shp->subshell = 0;
+#ifndef SHOPT_2DMATCH
+ index = 0;
+#else
+ if(index==0)
+#endif /* SHOPT_2DMATCH */
+ {
+ if(ap->hdr.next != &mp->hdr)
+ {
+ free((void*)ap);
+ ap = nv_arrayptr(np);
+ SH_MATCHNOD->nvfun = &ap->hdr;
+ }
+ if(ap)
+ {
+ ap->nelem &= ~ARRAY_SCAN;
+ i = array_elem(ap);
+ ap->nelem++;
+ while(--i>= 0)
+ {
+ nv_putsub(SH_MATCHNOD, (char*)0,i);
+ _nv_unset(SH_MATCHNOD,NV_RDONLY);
+ }
+ ap->nelem--;
+ }
+ if(!nv_hasdisc(SH_MATCHNOD,mp->hdr.disc))
+ nv_disc(SH_MATCHNOD,&mp->hdr,NV_LAST);
+ if(nmatch)
+ nv_putsub(SH_MATCHNOD, NIL(char*), (nmatch-1)|ARRAY_FILL|ARRAY_SETSUB);
+ ap = nv_arrayptr(SH_MATCHNOD);
+ ap->nelem = mp->nmatch = nmatch;
+ mp->v = v;
+ mp->first = match[0];
+ }
+#ifdef SHOPT_2DMATCH
+ else
+ {
+ if(index==1)
+ {
+ np->nvalue.cp = Empty;
+ np->nvfun = SH_MATCHNOD->nvfun;
+ nv_onattr(np,NV_NOFREE|NV_ARRAY);
+ SH_MATCHNOD->nvfun = 0;
+ for(i=0; i < mp->nmatch; i++)
+ {
+ nv_putsub(SH_MATCHNOD, (char*)0, i);
+ nv_arraychild(SH_MATCHNOD, np,0);
+ }
+ if(ap = nv_arrayptr(SH_MATCHNOD))
+ ap->nelem = mp->nmatch;
+ }
+ ap = nv_arrayptr(np);
+ nv_putsub(np, NIL(char*), index|ARRAY_FILL|ARRAY_SETSUB);
+ }
+#endif /* SHOPT_2DMATCH */
+ shp->subshell = savesub;
+ index *= 2*mp->nmatch;
+ if(mp->nmatch)
+ {
+ for(n=mp->first+(mp->v-v),vsize=0,i=0; i < 2*nmatch; i++)
+ {
+ if(match[i]>=0 && (match[i] - n) > vsize)
+ vsize = match[i] -n;
+ }
+ i = (index+2*mp->nmatch)*sizeof(match[0]);
+ if((i+vsize) >= mp->vsize)
+ {
+ if(mp->vsize)
+ mp->match = (int*)realloc(mp->match,i+vsize+1);
+ else
+ mp->match = (int*)malloc(i+vsize+1);
+ mp->vsize = i+vsize+1;
+ }
+ mp->val = ((char*)mp->match)+i;
+ memcpy(mp->match+index,match,nmatch*2*sizeof(match[0]));
+ for(x=0,i=0; i < 2*nmatch; i++)
+ {
+ if(match[i]>=0)
+ mp->match[index+i] -= n;
+ else
+ x=1;
+
+ }
+ ap->nelem -= x;
+ while(i < 2*mp->nmatch)
+ mp->match[index+i++] = -1;
+ memcpy(mp->val,v+n,vsize);
+ mp->val[vsize] = 0;
+ mp->lastsub[0] = mp->lastsub[1] = -1;
+ }
+}
+
+#define array_scan(np) ((nv_arrayptr(np)->nelem&ARRAY_SCAN))
+
+static char* get_match(register Namval_t* np, Namfun_t *fp)
+{
+ struct match *mp = (struct match*)fp;
+ int sub,sub2=0,n,i =!mp->index;
+ char *val;
+ sub = nv_aindex(SH_MATCHNOD);
+ if(np!=SH_MATCHNOD)
+ sub2 = nv_aindex(np);
+ if(sub>=mp->nmatch)
+ return(0);
+ if(sub2>0)
+ sub += sub2*mp->nmatch;
+ if(sub==mp->lastsub[!i])
+ return(mp->rval[!i]);
+ else if(sub==mp->lastsub[i])
+ return(mp->rval[i]);
+ n = mp->match[2*sub+1]-mp->match[2*sub];
+ if(n<=0)
+ return(mp->match[2*sub]<0?Empty:"");
+ val = mp->val+mp->match[2*sub];
+ if(mp->val[mp->match[2*sub+1]]==0)
+ return(val);
+ mp->index = i;
+ if(mp->rval[i])
+ {
+ free((void*)mp->rval[i]);
+ mp->rval[i] = 0;
+ }
+ mp->rval[i] = (char*)malloc(n+1);
+ mp->lastsub[i] = sub;
+ memcpy(mp->rval[i],val,n);
+ mp->rval[i][n] = 0;
+ return(mp->rval[i]);
+}
+
+static const Namdisc_t SH_MATCH_disc = { sizeof(struct match), 0, get_match };
+
+static char* get_version(register Namval_t* np, Namfun_t *fp)
+{
+ return(nv_getv(np,fp));
+}
+
+static Sfdouble_t nget_version(register Namval_t* np, Namfun_t *fp)
+{
+ register const char *cp = e_version + strlen(e_version)-10;
+ register int c;
+ Sflong_t t = 0;
+ NOT_USED(fp);
+
+ while (c = *cp++)
+ if (c >= '0' && c <= '9')
+ {
+ t *= 10;
+ t += c - '0';
+ }
+ return((Sfdouble_t)t);
+}
+
+static const Namdisc_t SH_VERSION_disc = { 0, 0, get_version, nget_version };
+
+#if SHOPT_FS_3D
+ /*
+ * set or unset the mappings given a colon separated list of directories
+ */
+ static void vpath_set(char *str, int mode)
+ {
+ register char *lastp, *oldp=str, *newp=strchr(oldp,':');
+ if(!shgd->lim.fs3d)
+ return;
+ while(newp)
+ {
+ *newp++ = 0;
+ if(lastp=strchr(newp,':'))
+ *lastp = 0;
+ mount((mode?newp:""),oldp,FS3D_VIEW,0);
+ newp[-1] = ':';
+ oldp = newp;
+ newp=lastp;
+ }
+ }
+
+ /* catch vpath assignments */
+ static void put_vpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+ {
+ register char *cp;
+ if(cp = nv_getval(np))
+ vpath_set(cp,0);
+ if(val)
+ vpath_set((char*)val,1);
+ nv_putv(np,val,flags,fp);
+ }
+ static const Namdisc_t VPATH_disc = { 0, put_vpath };
+ static Namfun_t VPATH_init = { &VPATH_disc, 1 };
+#endif /* SHOPT_FS_3D */
+
+
+static const Namdisc_t IFS_disc = { sizeof(struct ifs), put_ifs, get_ifs };
+const Namdisc_t RESTRICTED_disc = { sizeof(Namfun_t), put_restricted };
+static const Namdisc_t CDPATH_disc = { sizeof(Namfun_t), put_cdpath };
+static const Namdisc_t EDITOR_disc = { sizeof(Namfun_t), put_ed };
+static const Namdisc_t HISTFILE_disc = { sizeof(Namfun_t), put_history };
+static const Namdisc_t OPTINDEX_disc = { sizeof(Namfun_t), put_optindex, 0, nget_optindex, 0, 0, clone_optindex };
+static const Namdisc_t SECONDS_disc = { sizeof(struct seconds), put_seconds, get_seconds, nget_seconds };
+static const Namdisc_t RAND_disc = { sizeof(struct rand), put_rand, get_rand, nget_rand };
+static const Namdisc_t LINENO_disc = { sizeof(Namfun_t), put_lineno, get_lineno, nget_lineno };
+static const Namdisc_t L_ARG_disc = { sizeof(Namfun_t), put_lastarg, get_lastarg };
+
+
+#define MAX_MATH_ARGS 3
+
+static char *name_math(Namval_t *np, Namfun_t *fp)
+{
+ Shell_t *shp = sh_getinterp();
+ sfprintf(shp->strbuf,".sh.math.%s",np->nvname);
+ return(sfstruse(shp->strbuf));
+}
+
+static const Namdisc_t math_child_disc =
+{
+ 0,0,0,0,0,0,0,
+ name_math
+};
+
+static Namfun_t math_child_fun =
+{
+ &math_child_disc, 1, 0, sizeof(Namfun_t)
+};
+
+static void math_init(Shell_t *shp)
+{
+ Namval_t *np;
+ char *name;
+ int i;
+ shp->mathnodes = (char*)calloc(1,MAX_MATH_ARGS*(NV_MINSZ+5));
+ name = shp->mathnodes+MAX_MATH_ARGS*NV_MINSZ;
+ for(i=0; i < MAX_MATH_ARGS; i++)
+ {
+ np = nv_namptr(shp->mathnodes,i);
+ np->nvfun = &math_child_fun;
+ memcpy(name,"arg",3);
+ name[3] = '1'+i;
+ np->nvname = name;
+ name+=5;
+ nv_onattr(np,NV_MINIMAL|NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
+ }
+}
+
+static Namval_t *create_math(Namval_t *np,const char *name,int flag,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ if(!name)
+ return(SH_MATHNOD);
+ if(name[0]!='a' || name[1]!='r' || name[2]!='g' || name[4] || !isdigit(name[3]) || (name[3]=='0' || (name[3]-'0')>MAX_MATH_ARGS))
+ return(0);
+ fp->last = (char*)&name[4];
+ return(nv_namptr(shp->mathnodes,name[3]-'1'));
+}
+
+static char* get_math(register Namval_t* np, Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ Namval_t *mp,fake;
+ char *val;
+ int first=0;
+ fake.nvname = ".sh.math.";
+ mp = (Namval_t*)dtprev(shp->fun_tree,&fake);
+ while(mp=(Namval_t*)dtnext(shp->fun_tree,mp))
+ {
+ if(memcmp(mp->nvname,".sh.math.",9))
+ break;
+ if(first++)
+ sfputc(shp->strbuf,' ');
+ sfputr(shp->strbuf,mp->nvname+9,-1);
+ }
+ val = sfstruse(shp->strbuf);
+ return(val);
+
+}
+
+static char *setdisc_any(Namval_t *np, const char *event, Namval_t *action, Namfun_t *fp)
+{
+ Shell_t *shp=nv_shell(np);
+ Namval_t *mp,fake;
+ char *name;
+ int getname=0, off=staktell();
+ fake.nvname = nv_name(np);
+ if(!event)
+ {
+ if(!action)
+ {
+ mp = (Namval_t*)dtprev(shp->fun_tree,&fake);
+ return((char*)dtnext(shp->fun_tree,mp));
+ }
+ getname = 1;
+ }
+ stakputs(fake.nvname);
+ stakputc('.');
+ stakputs(event);
+ stakputc(0);
+ name = stakptr(off);
+ mp = nv_search(name, shp->fun_tree, action?NV_ADD:0);
+ stakseek(off);
+ if(getname)
+ return(mp?(char*)dtnext(shp->fun_tree,mp):0);
+ if(action==np)
+ action = mp;
+ return(action?(char*)action:"");
+}
+
+static const Namdisc_t SH_MATH_disc = { 0, 0, get_math, 0, setdisc_any, create_math, };
+
+#if SHOPT_COSHELL
+static const Namdisc_t SH_JOBPOOL_disc = { 0, 0, 0, 0, setdisc_any, 0, };
+#endif /* SHOPT_COSHELL */
+
+#if SHOPT_NAMESPACE
+ static char* get_nspace(Namval_t* np, Namfun_t *fp)
+ {
+ if(sh.namespace)
+ return(nv_name(sh.namespace));
+ return((char*)np->nvalue.cp);
+ }
+ static const Namdisc_t NSPACE_disc = { 0, 0, get_nspace };
+ static Namfun_t NSPACE_init = { &NSPACE_disc, 1};
+#endif /* SHOPT_NAMESPACE */
+
+#ifdef _hdr_locale
+ static const Namdisc_t LC_disc = { sizeof(Namfun_t), put_lang };
+#endif /* _hdr_locale */
+
+/*
+ * This function will get called whenever a configuration parameter changes
+ */
+static int newconf(const char *name, const char *path, const char *value)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *arg;
+ if(!name)
+ setenviron(value);
+ else if(strcmp(name,"UNIVERSE")==0 && strcmp(astconf(name,0,0),value))
+ {
+ shp->universe = 0;
+ /* set directory in new universe */
+ if(*(arg = path_pwd(shp,0))=='/')
+ chdir(arg);
+ /* clear out old tracked alias */
+ stakseek(0);
+ stakputs(nv_getval(PATHNOD));
+ stakputc(0);
+ nv_putval(PATHNOD,stakseek(0),NV_RDONLY);
+ }
+ return(1);
+}
+
+#if (CC_NATIVE != CC_ASCII)
+ static void a2e(char *d, const char *s)
+ {
+ register const unsigned char *t;
+ register int i;
+ t = CCMAP(CC_ASCII, CC_NATIVE);
+ for(i=0; i<(1<<CHAR_BIT); i++)
+ d[t[i]] = s[i];
+ }
+
+ static void init_ebcdic(void)
+ {
+ int i;
+ char *cp = (char*)malloc(ST_NONE*(1<<CHAR_BIT));
+ for(i=0; i < ST_NONE; i++)
+ {
+ a2e(cp,sh_lexrstates[i]);
+ sh_lexstates[i] = cp;
+ cp += (1<<CHAR_BIT);
+ }
+ }
+#endif
+
+/*
+ * return SH_TYPE_* bitmask for path
+ * 0 for "not a shell"
+ */
+int sh_type(register const char *path)
+{
+ register const char* s;
+ register int t = 0;
+
+ if (s = (const char*)strrchr(path, '/'))
+ {
+ if (*path == '-')
+ t |= SH_TYPE_LOGIN;
+ s++;
+ }
+ else
+ s = path;
+ if (*s == '-')
+ {
+ s++;
+ t |= SH_TYPE_LOGIN;
+ }
+ for (;;)
+ {
+ if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH)))
+ {
+ if (*s == 'k')
+ {
+ s++;
+ t |= SH_TYPE_KSH;
+ continue;
+ }
+#if SHOPT_BASH
+ if (*s == 'b' && *(s+1) == 'a')
+ {
+ s += 2;
+ t |= SH_TYPE_BASH;
+ continue;
+ }
+#endif
+ }
+ if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED)))
+ {
+#if SHOPT_PFSH
+ if (*s == 'p' && *(s+1) == 'f')
+ {
+ s += 2;
+ t |= SH_TYPE_PROFILE;
+ continue;
+ }
+#endif
+ if (*s == 'r')
+ {
+ s++;
+ t |= SH_TYPE_RESTRICTED;
+ continue;
+ }
+ }
+ break;
+ }
+ if (*s++ == 's' && (*s == 'h' || *s == 'u'))
+ {
+ s++;
+ t |= SH_TYPE_SH;
+ if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3')
+ s += 2;
+#if _WINIX
+ if (*s == '.' && *(s+1) == 'e' && *(s+2) == 'x' && *(s+3) == 'e')
+ s += 4;
+#endif
+ if (!isalnum(*s))
+ return t;
+ }
+ return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED);
+}
+
+
+static char *get_mode(Namval_t* np, Namfun_t* nfp)
+{
+ mode_t mode = nv_getn(np,nfp);
+ return(fmtperm(mode));
+}
+
+static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
+{
+ if(val)
+ {
+ mode_t mode;
+ char *last=0;
+ if(flag&NV_INTEGER)
+ {
+ if(flag&NV_LONG)
+ mode = *(Sfdouble_t*)val;
+ else
+ mode = *(double*)val;
+ }
+ else
+ mode = strperm(val, &last,0);
+ if(*last)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
+ nv_putv(np,(char*)&mode,NV_INTEGER,nfp);
+ }
+ else
+ nv_putv(np,val,flag,nfp);
+}
+
+static const Namdisc_t modedisc =
+{
+ 0,
+ put_mode,
+ get_mode,
+};
+
+
+/*
+ * initialize the shell
+ */
+Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
+{
+ static int beenhere;
+ Shell_t *shp;
+ register int n;
+ int type;
+ static char *login_files[3];
+ memfatal();
+ n = strlen(e_version);
+ if(e_version[n-1]=='$' && e_version[n-2]==' ')
+ e_version[n-2]=0;
+#if (CC_NATIVE == CC_ASCII)
+ memcpy(sh_lexstates,sh_lexrstates,ST_NONE*sizeof(char*));
+#else
+ init_ebcdic();
+#endif
+ if(!beenhere)
+ {
+ beenhere = 1;
+ shp = &sh;
+ shgd = newof(0,struct shared,1,0);
+ shgd->pid = getpid();
+ shgd->ppid = getppid();
+ shgd->userid=getuid();
+ shgd->euserid=geteuid();
+ shgd->groupid=getgid();
+ shgd->egroupid=getegid();
+ shgd->lim.clk_tck = getconf("CLK_TCK");
+ shgd->lim.arg_max = getconf("ARG_MAX");
+ shgd->lim.child_max = getconf("CHILD_MAX");
+ shgd->lim.ngroups_max = getconf("NGROUPS_MAX");
+ shgd->lim.posix_version = getconf("VERSION");
+ shgd->lim.posix_jobcontrol = getconf("JOB_CONTROL");
+ if(shgd->lim.arg_max <=0)
+ shgd->lim.arg_max = ARG_MAX;
+ if(shgd->lim.child_max <=0)
+ shgd->lim.child_max = CHILD_MAX;
+ if(shgd->lim.clk_tck <=0)
+ shgd->lim.clk_tck = CLK_TCK;
+#if SHOPT_FS_3D
+ if(fs3d(FS3D_TEST))
+ shgd->lim.fs3d = 1;
+#endif /* SHOPT_FS_3D */
+ shgd->ed_context = (void*)ed_open(shp);
+ error_info.exit = sh_exit;
+ error_info.id = path_basename(argv[0]);
+ }
+ else
+ shp = newof(0,Shell_t,1,0);
+ umask(shp->mask=umask(0));
+ shp->gd = shgd;
+ shp->mac_context = sh_macopen(shp);
+ shp->arg_context = sh_argopen(shp);
+ shp->lex_context = (void*)sh_lexopen(0,shp,1);
+ shp->strbuf = sfstropen();
+ shp->stk = stkstd;
+ sfsetbuf(shp->strbuf,(char*)0,64);
+ sh_onstate(SH_INIT);
+#if ERROR_VERSION >= 20000102L
+ error_info.catalog = e_dict;
+#endif
+#if SHOPT_REGRESS
+ {
+ Opt_t* nopt;
+ Opt_t* oopt;
+ char* a;
+ char** av = argv;
+ char* regress[3];
+
+ sh_regress_init(shp);
+ regress[0] = "__regress__";
+ regress[2] = 0;
+ /* NOTE: only shp is used by __regress__ at this point */
+ shp->bltindata.shp = shp;
+ while ((a = *++av) && a[0] == '-' && (a[1] == 'I' || a[1] == '-' && a[2] == 'r'))
+ {
+ if (a[1] == 'I')
+ {
+ if (a[2])
+ regress[1] = a + 2;
+ else if (!(regress[1] = *++av))
+ break;
+ }
+ else if (strncmp(a+2, "regress", 7))
+ break;
+ else if (a[9] == '=')
+ regress[1] = a + 10;
+ else if (!(regress[1] = *++av))
+ break;
+ nopt = optctx(0, 0);
+ oopt = optctx(nopt, 0);
+ b___regress__(2, regress, &shp->bltindata);
+ optctx(oopt, nopt);
+ }
+ }
+#endif
+ shp->cpipe[0] = -1;
+ shp->coutpipe = -1;
+ for(n=0;n < 10; n++)
+ {
+ /* don't use lower bits when rand() generates large numbers */
+ if(rand() > RANDMASK)
+ {
+ rand_shift = 3;
+ break;
+ }
+ }
+ sh_ioinit(shp);
+ /* initialize signal handling */
+ sh_siginit(shp);
+ stakinstall(NIL(Stak_t*),nospace);
+ /* set up memory for name-value pairs */
+ shp->init_context = nv_init(shp);
+ /* read the environment */
+ if(argc>0)
+ {
+ type = sh_type(*argv);
+ if(type&SH_TYPE_LOGIN)
+ shp->login_sh = 2;
+ }
+ env_init(shp);
+ if(!ENVNOD->nvalue.cp)
+ {
+ sfprintf(shp->strbuf,"%s/.kshrc",nv_getval(HOME));
+ nv_putval(ENVNOD,sfstruse(shp->strbuf),NV_RDONLY);
+ }
+ *SHLVL->nvalue.ip +=1;
+ nv_offattr(SHLVL,NV_IMPORT);
+#if SHOPT_SPAWN
+ {
+ /*
+ * try to find the pathname for this interpreter
+ * try using environment variable _ or argv[0]
+ */
+ char *cp=nv_getval(L_ARGNOD);
+ char buff[PATH_MAX+1];
+ shp->gd->shpath = 0;
+#if _AST_VERSION >= 20090202L
+ if((n = pathprog(NiL, buff, sizeof(buff))) > 0 && n <= sizeof(buff))
+ shp->gd->shpath = strdup(buff);
+#else
+ sfprintf(shp->strbuf,"/proc/%d/exe",getpid());
+ if((n=readlink(sfstruse(shp->strbuf),buff,sizeof(buff)-1))>0)
+ {
+ buff[n] = 0;
+ shp->gd->shpath = strdup(buff);
+ }
+#endif
+ else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/')))
+ {
+ if(*cp=='/')
+ shp->gd->shpath = strdup(cp);
+ else if(cp = nv_getval(PWDNOD))
+ {
+ int offset = staktell();
+ stakputs(cp);
+ stakputc('/');
+ stakputs(argv[0]);
+ pathcanon(stakptr(offset),PATH_DOTDOT);
+ shp->gd->shpath = strdup(stakptr(offset));
+ stakseek(offset);
+ }
+ }
+ }
+#endif
+ nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
+#if SHOPT_FS_3D
+ nv_stack(VPATHNOD, &VPATH_init);
+#endif /* SHOPT_FS_3D */
+ astconfdisc(newconf);
+#if SHOPT_TIMEOUT
+ shp->st.tmout = SHOPT_TIMEOUT;
+#endif /* SHOPT_TIMEOUT */
+ /* initialize jobs table */
+ job_clear();
+ if(argc>0)
+ {
+ /* check for restricted shell */
+ if(type&SH_TYPE_RESTRICTED)
+ sh_onoption(SH_RESTRICTED);
+#if SHOPT_PFSH
+ /* check for profile shell */
+ else if(type&SH_TYPE_PROFILE)
+ sh_onoption(SH_PFSH);
+#endif
+#if SHOPT_BASH
+ /* check for invocation as bash */
+ if(type&SH_TYPE_BASH)
+ {
+ shp>userinit = userinit = bash_init;
+ sh_onoption(SH_BASH);
+ sh_onstate(SH_PREINIT);
+ (*userinit)(shp, 0);
+ sh_offstate(SH_PREINIT);
+ }
+#endif
+ /* look for options */
+ /* shp->st.dolc is $# */
+ if((shp->st.dolc = sh_argopts(-argc,argv,shp)) < 0)
+ {
+ shp->exitval = 2;
+ sh_done(shp,0);
+ }
+ opt_info.disc = 0;
+ shp->st.dolv=argv+(argc-1)-shp->st.dolc;
+ shp->st.dolv[0] = argv[0];
+ if(shp->st.dolc < 1)
+ sh_onoption(SH_SFLAG);
+ if(!sh_isoption(SH_SFLAG))
+ {
+ shp->st.dolc--;
+ shp->st.dolv++;
+#if _WINIX
+ {
+ char* name;
+ name = shp->st.dolv[0];
+ if(name[1]==':' && (name[2]=='/' || name[2]=='\\'))
+ {
+#if _lib_pathposix
+ char* p;
+
+ if((n = pathposix(name, NIL(char*), 0)) > 0 && (p = (char*)malloc(++n)))
+ {
+ pathposix(name, p, n);
+ name = p;
+ }
+ else
+#endif
+ {
+ name[1] = name[0];
+ name[0] = name[2] = '/';
+ }
+ }
+ }
+#endif /* _WINIX */
+ }
+ if(beenhere==1)
+ {
+ struct lconv* lc;
+ shp->decomma = (lc=localeconv()) && lc->decimal_point && *lc->decimal_point==',';
+ beenhere = 2;
+ }
+ }
+#if SHOPT_PFSH
+ if (sh_isoption(SH_PFSH))
+ {
+ struct passwd *pw = getpwuid(shp->gd->userid);
+ if(pw)
+ shp->gd->user = strdup(pw->pw_name);
+
+ }
+#endif
+ /* set[ug]id scripts require the -p flag */
+ if(shp->gd->userid!=shp->gd->euserid || shp->gd->groupid!=shp->gd->egroupid)
+ {
+#ifdef SHOPT_P_SUID
+ /* require sh -p to run setuid and/or setgid */
+ if(!sh_isoption(SH_PRIVILEGED) && shp->gd->userid >= SHOPT_P_SUID)
+ {
+ setuid(shp->gd->euserid=shp->gd->userid);
+ setgid(shp->gd->egroupid=shp->gd->groupid);
+ }
+ else
+#endif /* SHOPT_P_SUID */
+ sh_onoption(SH_PRIVILEGED);
+#ifdef SHELLMAGIC
+ /* careful of #! setuid scripts with name beginning with - */
+ if(shp->login_sh && argv[1] && strcmp(argv[0],argv[1])==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_prohibited);
+#endif /*SHELLMAGIC*/
+ }
+ else
+ sh_offoption(SH_PRIVILEGED);
+ /* shname for $0 in profiles and . scripts */
+ if(sh_isdevfd(argv[1]))
+ shp->shname = strdup(argv[0]);
+ else
+ shp->shname = strdup(shp->st.dolv[0]);
+ /*
+ * return here for shell script execution
+ * but not for parenthesis subshells
+ */
+ error_info.id = strdup(shp->st.dolv[0]); /* error_info.id is $0 */
+ shp->jmpbuffer = (void*)&shp->checkbase;
+ sh_pushcontext(shp,&shp->checkbase,SH_JMPSCRIPT);
+ shp->st.self = &shp->global;
+ shp->topscope = (Shscope_t*)shp->st.self;
+ sh_offstate(SH_INIT);
+ login_files[0] = (char*)e_profile;
+ login_files[1] = ".profile";
+ shp->gd->login_files = login_files;
+ shp->bltindata.version = SH_VERSION;
+ shp->bltindata.shp = shp;
+ shp->bltindata.shrun = sh_run;
+ shp->bltindata.shtrap = sh_trap;
+ shp->bltindata.shexit = sh_exit;
+ shp->bltindata.shbltin = sh_addbuiltin;
+#if _AST_VERSION >= 20080617L
+ shp->bltindata.shgetenv = sh_getenv;
+ shp->bltindata.shsetenv = sh_setenviron;
+ astintercept(&shp->bltindata,1);
+#endif
+#if 0
+#define NV_MKINTTYPE(x,y,z) nv_mkinttype(#x,sizeof(x),(x)-1<0,(y),(Namdisc_t*)z);
+ NV_MKINTTYPE(pid_t,"process id",0);
+ NV_MKINTTYPE(gid_t,"group id",0);
+ NV_MKINTTYPE(uid_t,"user id",0);
+ NV_MKINTTYPE(size_t,(const char*)0,0);
+ NV_MKINTTYPE(ssize_t,(const char*)0,0);
+ NV_MKINTTYPE(off_t,"offset in bytes",0);
+ NV_MKINTTYPE(ino_t,"\ai-\anode number",0);
+ NV_MKINTTYPE(mode_t,(const char*)0,&modedisc);
+ NV_MKINTTYPE(dev_t,"device id",0);
+ NV_MKINTTYPE(nlink_t,"hard link count",0);
+ NV_MKINTTYPE(blkcnt_t,"block count",0);
+ NV_MKINTTYPE(time_t,"seconds since the epoch",0);
+ nv_mkstat();
+#endif
+ if(shp->userinit=userinit)
+ (*userinit)(shp, 0);
+ return(shp);
+}
+
+Shell_t *sh_getinterp(void)
+{
+ return(&sh);
+}
+
+/*
+ * reinitialize before executing a script
+ */
+int sh_reinit(char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ Shopt_t opt;
+ Namval_t *np,*npnext;
+ Dt_t *dp;
+ struct adata
+ {
+ Shell_t *sh;
+ void *extra[2];
+ } data;
+ for(np=dtfirst(shp->fun_tree);np;np=npnext)
+ {
+ if((dp=shp->fun_tree)->walk)
+ dp = dp->walk;
+ npnext = (Namval_t*)dtnext(shp->fun_tree,np);
+ if(np>= shgd->bltin_cmds && np < &shgd->bltin_cmds[nbltins])
+ continue;
+ if(is_abuiltin(np) && nv_isattr(np,NV_EXPORT))
+ continue;
+ if(*np->nvname=='/')
+ continue;
+ nv_delete(np,dp,NV_NOFREE);
+ }
+ dtclose(shp->alias_tree);
+ shp->alias_tree = inittree(shp,shtab_aliases);
+ shp->last_root = shp->var_tree;
+ shp->inuse_bits = 0;
+ if(shp->userinit)
+ (*shp->userinit)(shp, 1);
+ if(shp->heredocs)
+ {
+ sfclose(shp->heredocs);
+ shp->heredocs = 0;
+ }
+ /* remove locals */
+ sh_onstate(SH_INIT);
+ memset(&data,0,sizeof(data));
+ data.sh = shp;
+ nv_scan(shp->var_tree,sh_envnolocal,(void*)&data,NV_EXPORT,0);
+ nv_scan(shp->var_tree,sh_envnolocal,(void*)&data,NV_ARRAY,NV_ARRAY);
+ sh_offstate(SH_INIT);
+ memset(shp->st.trapcom,0,(shp->st.trapmax+1)*sizeof(char*));
+ memset((void*)&opt,0,sizeof(opt));
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ {
+ dp=nv_dict(shp->namespace);
+ if(dp==shp->var_tree)
+ shp->var_tree = dtview(dp,0);
+ _nv_unset(shp->namespace,NV_RDONLY);
+ shp->namespace = 0;
+ }
+#endif /* SHOPT_NAMESPACE */
+ if(sh_isoption(SH_TRACKALL))
+ on_option(&opt,SH_TRACKALL);
+ if(sh_isoption(SH_EMACS))
+ on_option(&opt,SH_EMACS);
+ if(sh_isoption(SH_GMACS))
+ on_option(&opt,SH_GMACS);
+ if(sh_isoption(SH_VI))
+ on_option(&opt,SH_VI);
+ if(sh_isoption(SH_VIRAW))
+ on_option(&opt,SH_VIRAW);
+ shp->options = opt;
+ /* set up new args */
+ if(argv)
+ shp->arglist = sh_argcreate(argv);
+ if(shp->arglist)
+ sh_argreset(shp,shp->arglist,NIL(struct dolnod*));
+ shp->envlist=0;
+ shp->curenv = 0;
+ shp->shname = error_info.id = strdup(shp->st.dolv[0]);
+ sh_offstate(SH_FORKED);
+ shp->fn_depth = shp->dot_depth = 0;
+ sh_sigreset(0);
+ if(!(SHLVL->nvalue.ip))
+ {
+ shlvl = 0;
+ SHLVL->nvalue.ip = &shlvl;
+ nv_onattr(SHLVL,NV_INTEGER|NV_EXPORT|NV_NOFREE);
+ }
+ *SHLVL->nvalue.ip +=1;
+ nv_offattr(SHLVL,NV_IMPORT);
+ shp->st.filename = strdup(shp->lastarg);
+ nv_delete((Namval_t*)0, (Dt_t*)0, 0);
+ job.exitval = 0;
+ shp->inpipe = shp->outpipe = 0;
+ job_clear();
+ job.in_critical = 0;
+ return(1);
+}
+
+/*
+ * set when creating a local variable of this name
+ */
+Namfun_t *nv_cover(register Namval_t *np)
+{
+ if(np==IFSNOD || np==PATHNOD || np==SHELLNOD || np==FPATHNOD || np==CDPNOD || np==SECONDS || np==ENVNOD || np==LINENO)
+ return(np->nvfun);
+#ifdef _hdr_locale
+ if(np==LCALLNOD || np==LCTYPENOD || np==LCMSGNOD || np==LCCOLLNOD || np==LCNUMNOD || np==LANGNOD)
+ return(np->nvfun);
+#endif
+ return(0);
+}
+
+static const char *shdiscnames[] = { "tilde", 0};
+
+#ifdef SHOPT_STATS
+struct Stats
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+ char *nodes;
+ int numnodes;
+ int current;
+};
+
+static Namval_t *next_stat(register Namval_t* np, Dt_t *root,Namfun_t *fp)
+{
+ struct Stats *sp = (struct Stats*)fp;
+ if(!root)
+ sp->current = 0;
+ else if(++sp->current>=sp->numnodes)
+ return(0);
+ return(nv_namptr(sp->nodes,sp->current));
+}
+
+static Namval_t *create_stat(Namval_t *np,const char *name,int flag,Namfun_t *fp)
+{
+ struct Stats *sp = (struct Stats*)fp;
+ register const char *cp=name;
+ register int i=0,n;
+ Namval_t *nq=0;
+ Shell_t *shp = sp->sh;
+ if(!name)
+ return(SH_STATS);
+ while((i=*cp++) && i != '=' && i != '+' && i!='[');
+ n = (cp-1) -name;
+ for(i=0; i < sp->numnodes; i++)
+ {
+ nq = nv_namptr(sp->nodes,i);
+ if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
+ goto found;
+ }
+ nq = 0;
+found:
+ if(nq)
+ {
+ fp->last = (char*)&name[n];
+ shp->last_table = SH_STATS;
+ }
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
+ return(nq);
+}
+
+static const Namdisc_t stat_disc =
+{
+ 0, 0, 0, 0, 0,
+ create_stat,
+ 0, 0,
+ next_stat
+};
+
+static char *name_stat(Namval_t *np, Namfun_t *fp)
+{
+ Shell_t *shp = sh_getinterp();
+ sfprintf(shp->strbuf,".sh.stats.%s",np->nvname);
+ return(sfstruse(shp->strbuf));
+}
+
+static const Namdisc_t stat_child_disc =
+{
+ 0,0,0,0,0,0,0,
+ name_stat
+};
+
+static Namfun_t stat_child_fun =
+{
+ &stat_child_disc, 1, 0, sizeof(Namfun_t)
+};
+
+static void stat_init(Shell_t *shp)
+{
+ int i,nstat = STAT_SUBSHELL+1;
+ struct Stats *sp = newof(0,struct Stats,1,nstat*NV_MINSZ);
+ Namval_t *np;
+ sp->numnodes = nstat;
+ sp->nodes = (char*)(sp+1);
+ shgd->stats = (int*)calloc(sizeof(int),nstat);
+ sp->sh = shp;
+ for(i=0; i < nstat; i++)
+ {
+ np = nv_namptr(sp->nodes,i);
+ np->nvfun = &stat_child_fun;
+ np->nvname = (char*)shtab_stats[i].sh_name;
+ nv_onattr(np,NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER);
+ nv_setsize(np,10);
+ np->nvalue.ip = &shgd->stats[i];
+ }
+ sp->hdr.dsize = sizeof(struct Stats) + nstat*(sizeof(int)+NV_MINSZ);
+ sp->hdr.disc = &stat_disc;
+ nv_stack(SH_STATS,&sp->hdr);
+ sp->hdr.nofree = 1;
+ nv_setvtree(SH_STATS);
+}
+#else
+# define stat_init(x)
+#endif /* SHOPT_STATS */
+
+/*
+ * Initialize the shell name and alias table
+ */
+static Init_t *nv_init(Shell_t *shp)
+{
+ double d=0;
+ ip = newof(0,Init_t,1,0);
+ if(!ip)
+ return(0);
+ shp->nvfun.last = (char*)shp;
+ shp->nvfun.nofree = 1;
+ ip->sh = shp;
+ shp->var_base = shp->var_tree = inittree(shp,shtab_variables);
+ SHLVL->nvalue.ip = &shlvl;
+ ip->IFS_init.hdr.disc = &IFS_disc;
+ ip->PATH_init.disc = &RESTRICTED_disc;
+ ip->PATH_init.nofree = 1;
+ ip->FPATH_init.disc = &RESTRICTED_disc;
+ ip->FPATH_init.nofree = 1;
+ ip->CDPATH_init.disc = &CDPATH_disc;
+ ip->CDPATH_init.nofree = 1;
+ ip->SHELL_init.disc = &RESTRICTED_disc;
+ ip->SHELL_init.nofree = 1;
+ ip->ENV_init.disc = &RESTRICTED_disc;
+ ip->ENV_init.nofree = 1;
+ ip->VISUAL_init.disc = &EDITOR_disc;
+ ip->VISUAL_init.nofree = 1;
+ ip->EDITOR_init.disc = &EDITOR_disc;
+ ip->EDITOR_init.nofree = 1;
+ ip->HISTFILE_init.disc = &HISTFILE_disc;
+ ip->HISTFILE_init.nofree = 1;
+ ip->HISTSIZE_init.disc = &HISTFILE_disc;
+ ip->HISTSIZE_init.nofree = 1;
+ ip->OPTINDEX_init.disc = &OPTINDEX_disc;
+ ip->OPTINDEX_init.nofree = 1;
+ ip->SECONDS_init.hdr.disc = &SECONDS_disc;
+ ip->SECONDS_init.hdr.nofree = 1;
+ ip->RAND_init.hdr.disc = &RAND_disc;
+ ip->RAND_init.hdr.nofree = 1;
+ ip->RAND_init.sh = shp;
+ ip->SH_MATCH_init.hdr.disc = &SH_MATCH_disc;
+ ip->SH_MATCH_init.hdr.nofree = 1;
+ ip->SH_MATH_init.disc = &SH_MATH_disc;
+ ip->SH_MATH_init.nofree = 1;
+#if SHOPT_COSHELL
+ ip->SH_JOBPOOL_init.disc = &SH_JOBPOOL_disc;
+ ip->SH_JOBPOOL_init.nofree = 1;
+ nv_stack(SH_JOBPOOL, &ip->SH_JOBPOOL_init);
+#endif /* SHOPT_COSHELL */
+ ip->SH_VERSION_init.disc = &SH_VERSION_disc;
+ ip->SH_VERSION_init.nofree = 1;
+ ip->LINENO_init.disc = &LINENO_disc;
+ ip->LINENO_init.nofree = 1;
+ ip->L_ARG_init.disc = &L_ARG_disc;
+ ip->L_ARG_init.nofree = 1;
+#ifdef _hdr_locale
+ ip->LC_TYPE_init.disc = &LC_disc;
+ ip->LC_TYPE_init.nofree = 1;
+ ip->LC_NUM_init.disc = &LC_disc;
+ ip->LC_NUM_init.nofree = 1;
+ ip->LC_COLL_init.disc = &LC_disc;
+ ip->LC_COLL_init.nofree = 1;
+ ip->LC_MSG_init.disc = &LC_disc;
+ ip->LC_MSG_init.nofree = 1;
+ ip->LC_ALL_init.disc = &LC_disc;
+ ip->LC_ALL_init.nofree = 1;
+ ip->LANG_init.disc = &LC_disc;
+ ip->LANG_init.nofree = 1;
+#endif /* _hdr_locale */
+ nv_stack(IFSNOD, &ip->IFS_init.hdr);
+ ip->IFS_init.hdr.nofree = 1;
+ nv_stack(PATHNOD, &ip->PATH_init);
+ nv_stack(FPATHNOD, &ip->FPATH_init);
+ nv_stack(CDPNOD, &ip->CDPATH_init);
+ nv_stack(SHELLNOD, &ip->SHELL_init);
+ nv_stack(ENVNOD, &ip->ENV_init);
+ nv_stack(VISINOD, &ip->VISUAL_init);
+ nv_stack(EDITNOD, &ip->EDITOR_init);
+ nv_stack(HISTFILE, &ip->HISTFILE_init);
+ nv_stack(HISTSIZE, &ip->HISTSIZE_init);
+ nv_stack(OPTINDNOD, &ip->OPTINDEX_init);
+ nv_stack(SECONDS, &ip->SECONDS_init.hdr);
+ nv_stack(L_ARGNOD, &ip->L_ARG_init);
+ nv_putval(SECONDS, (char*)&d, NV_DOUBLE);
+ nv_stack(RANDNOD, &ip->RAND_init.hdr);
+ d = (shp->gd->pid&RANDMASK);
+ nv_putval(RANDNOD, (char*)&d, NV_DOUBLE);
+ nv_stack(LINENO, &ip->LINENO_init);
+ SH_MATCHNOD->nvfun = &ip->SH_MATCH_init.hdr;
+ nv_putsub(SH_MATCHNOD,(char*)0,10);
+ nv_stack(SH_MATHNOD, &ip->SH_MATH_init);
+ nv_stack(SH_VERSIONNOD, &ip->SH_VERSION_init);
+#ifdef _hdr_locale
+ nv_stack(LCTYPENOD, &ip->LC_TYPE_init);
+ nv_stack(LCALLNOD, &ip->LC_ALL_init);
+ nv_stack(LCMSGNOD, &ip->LC_MSG_init);
+ nv_stack(LCCOLLNOD, &ip->LC_COLL_init);
+ nv_stack(LCNUMNOD, &ip->LC_NUM_init);
+ nv_stack(LANGNOD, &ip->LANG_init);
+#endif /* _hdr_locale */
+ (PPIDNOD)->nvalue.lp = (&shp->gd->ppid);
+ (TMOUTNOD)->nvalue.lp = (&shp->st.tmout);
+ (MCHKNOD)->nvalue.lp = (&sh_mailchk);
+ (OPTINDNOD)->nvalue.lp = (&shp->st.optindex);
+ /* set up the seconds clock */
+ shp->alias_tree = inittree(shp,shtab_aliases);
+ shp->track_tree = dtopen(&_Nvdisc,Dtset);
+ shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins);
+ shp->fun_tree = dtopen(&_Nvdisc,Dtoset);
+ dtview(shp->fun_tree,shp->bltin_tree);
+ nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset));
+ nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0);
+ DOTSHNOD->nvalue.cp = Empty;
+ SH_LINENO->nvalue.ip = &shp->st.lineno;
+ VERSIONNOD->nvalue.nrp = newof(0,struct Namref,1,0);
+ VERSIONNOD->nvalue.nrp->np = SH_VERSIONNOD;
+ VERSIONNOD->nvalue.nrp->root = nv_dict(DOTSHNOD);
+ VERSIONNOD->nvalue.nrp->table = DOTSHNOD;
+ nv_onattr(VERSIONNOD,NV_REF);
+ math_init(shp);
+ if(!shgd->stats)
+ stat_init(shp);
+ return(ip);
+}
+
+/*
+ * initialize name-value pairs
+ */
+
+static Dt_t *inittree(Shell_t *shp,const struct shtable2 *name_vals)
+{
+ register Namval_t *np;
+ register const struct shtable2 *tp;
+ register unsigned n = 0;
+ register Dt_t *treep;
+ Dt_t *base_treep, *dict;
+ for(tp=name_vals;*tp->sh_name;tp++)
+ n++;
+ np = (Namval_t*)calloc(n,sizeof(Namval_t));
+ if(!shgd->bltin_nodes)
+ {
+ shgd->bltin_nodes = np;
+ shgd->bltin_nnodes = n;
+ }
+ else if(name_vals==(const struct shtable2*)shtab_builtins)
+ {
+ shgd->bltin_cmds = np;
+ nbltins = n;
+ }
+ base_treep = treep = dtopen(&_Nvdisc,Dtoset);
+ treep->user = (void*)shp;
+ for(tp=name_vals;*tp->sh_name;tp++,np++)
+ {
+ if((np->nvname = strrchr(tp->sh_name,'.')) && np->nvname!=((char*)tp->sh_name))
+ np->nvname++;
+ else
+ {
+ np->nvname = (char*)tp->sh_name;
+ treep = base_treep;
+ }
+ np->nvenv = 0;
+ if(name_vals==(const struct shtable2*)shtab_builtins)
+ np->nvalue.bfp = (Nambfp_f)((struct shtable3*)tp)->sh_value;
+ else
+ {
+ if(name_vals == shtab_variables)
+ np->nvfun = &shp->nvfun;
+ np->nvalue.cp = (char*)tp->sh_value;
+ }
+ nv_setattr(np,tp->sh_number);
+ if(nv_isattr(np,NV_TABLE))
+ nv_mount(np,(const char*)0,dict=dtopen(&_Nvdisc,Dtoset));
+ if(nv_isattr(np,NV_INTEGER))
+ nv_setsize(np,10);
+ else
+ nv_setsize(np,0);
+ dtinsert(treep,np);
+ if(nv_istable(np))
+ treep = dict;
+ }
+ return(treep);
+}
+
+/*
+ * read in the process environment and set up name-value pairs
+ * skip over items that are not name-value pairs
+ */
+
+static void env_init(Shell_t *shp)
+{
+ register char *cp;
+ register Namval_t *np,*mp;
+ register char **ep=environ;
+ char *dp,*next=0;
+ int nenv=0,k=0,size=0;
+ Namval_t *np0;
+#ifdef _ENV_H
+ shp->env = env_open(environ,3);
+ env_delete(shp->env,"_");
+#endif
+ if(!ep)
+ goto skip;
+ while(*ep++)
+ nenv++;
+ np = newof(0,Namval_t,nenv,0);
+ for(np0=np,ep=environ;cp= *ep; ep++)
+ {
+ dp = strchr(cp,'=');
+ if(!dp)
+ continue;
+ *dp++ = 0;
+ if(mp = dtmatch(shp->var_base,cp))
+ {
+ mp->nvenv = (char*)cp;
+ dp[-1] = '=';
+ }
+ else if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]==0)
+ {
+ dp[-1] = '=';
+ next = cp+4;
+ continue;
+ }
+ else
+ {
+ k++;
+ mp = np++;
+ mp->nvname = cp;
+ size += strlen(cp);
+ }
+ nv_onattr(mp,NV_IMPORT);
+ if(mp->nvfun || nv_isattr(mp,NV_INTEGER))
+ nv_putval(mp,dp,0);
+ else
+ {
+ mp->nvalue.cp = dp;
+ nv_onattr(mp,NV_NOFREE);
+ }
+ nv_onattr(mp,NV_EXPORT|NV_IMPORT);
+ }
+ np = (Namval_t*)realloc((void*)np0,k*sizeof(Namval_t));
+ dp = (char*)malloc(size+k);
+ while(k-->0)
+ {
+ size = strlen(np->nvname);
+ memcpy(dp,np->nvname,size+1);
+ np->nvname[size] = '=';
+ np->nvenv = np->nvname;
+ np->nvname = dp;
+ dp += size+1;
+ dtinsert(shp->var_base,np++);
+ }
+ while(cp=next)
+ {
+ if(next = strchr(++cp,'='))
+ *next = 0;
+ np = nv_search(cp+2,shp->var_tree,NV_ADD);
+ if(np!=SHLVL && nv_isattr(np,NV_IMPORT|NV_EXPORT))
+ {
+ int flag = *(unsigned char*)cp-' ';
+ int size = *(unsigned char*)(cp+1)-' ';
+ if((flag&NV_INTEGER) && size==0)
+ {
+ /* check for floating*/
+ char *val = nv_getval(np);
+ strtol(val,&dp,10);
+ if(*dp=='.' || *dp=='e' || *dp=='E')
+ {
+ char *lp;
+ flag |= NV_DOUBLE;
+ if(*dp=='.')
+ {
+ strtol(dp+1,&lp,10);
+ if(*lp)
+ dp = lp;
+ }
+ if(*dp && *dp!='.')
+ {
+ flag |= NV_EXPNOTE;
+ size = dp-val;
+ }
+ else
+ size = strlen(dp);
+ size--;
+ }
+ }
+ nv_newattr(np,flag|NV_IMPORT|NV_EXPORT,size);
+ if((flag&(NV_INTEGER|NV_UTOL|NV_LTOU))==(NV_UTOL|NV_LTOU))
+ nv_mapchar(np,(flag&NV_UTOL)?e_tolower:e_toupper);
+ }
+ else
+ cp += 2;
+ }
+skip:
+#ifdef _ENV_H
+ env_delete(shp->env,e_envmarker);
+#endif
+ if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED))
+ {
+ nv_offattr(PWDNOD,NV_TAGGED);
+ path_pwd(shp,0);
+ }
+ if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED))
+ sh_onoption(SH_RESTRICTED); /* restricted shell */
+ return;
+}
+
+/*
+ * terminate shell and free up the space
+ */
+int sh_term(void)
+{
+ sfdisc(sfstdin,SF_POPDISC);
+ free((char*)sh.outbuff);
+ stakset(NIL(char*),0);
+ return(0);
+}
+
+/* function versions of these */
+
+#define DISABLE /* proto workaround */
+
+unsigned long sh_isoption DISABLE (int opt)
+{
+ return(sh_isoption(opt));
+}
+
+unsigned long sh_onoption DISABLE (int opt)
+{
+ return(sh_onoption(opt));
+}
+
+unsigned long sh_offoption DISABLE (int opt)
+{
+ return(sh_offoption(opt));
+}
+
+void sh_sigcheck DISABLE (void)
+{
+ Shell_t *shp = sh_getinterp();
+ sh_sigcheck(shp);
+}
+
+Dt_t* sh_bltin_tree DISABLE (void)
+{
+ return(sh.bltin_tree);
+}
+
+/*
+ * This code is for character mapped variables with wctrans()
+ */
+struct Mapchar
+{
+ Namfun_t hdr;
+ const char *name;
+ wctrans_t trans;
+ int lctype;
+};
+
+static void put_trans(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct Mapchar *mp = (struct Mapchar*)fp;
+ int c,offset = staktell(),off=offset;
+ if(val)
+ {
+ if(mp->lctype!=lctype)
+ {
+ mp->lctype = lctype;
+ mp->trans = wctrans(mp->name);
+ }
+ if(!mp->trans || (flags&NV_INTEGER))
+ goto skip;
+ while(c = mbchar(val))
+ {
+ c = towctrans(c,mp->trans);
+ stakseek(off+c);
+ stakseek(off);
+ c = mbconv(stakptr(off),c);
+ off += c;
+ stakseek(off);
+ }
+ stakputc(0);
+ val = stakptr(offset);
+ }
+ else
+ {
+ nv_putv(np,val,flags,fp);
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ stakseek(offset);
+ return;
+ }
+skip:
+ nv_putv(np,val,flags,fp);
+ stakseek(offset);
+}
+
+static const Namdisc_t TRANS_disc = { sizeof(struct Mapchar), put_trans };
+
+Namfun_t *nv_mapchar(Namval_t *np,const char *name)
+{
+ wctrans_t trans = name?wctrans(name):0;
+ struct Mapchar *mp=0;
+ int n=0,low;
+ if(np)
+ mp = (struct Mapchar*)nv_hasdisc(np,&TRANS_disc);
+ if(!name)
+ return(mp?(Namfun_t*)mp->name:0);
+ if(!trans)
+ return(0);
+ if(!np)
+ return(((Namfun_t*)0)+1);
+ if((low=strcmp(name,e_tolower)) && strcmp(name,e_toupper))
+ n += strlen(name)+1;
+ if(mp)
+ {
+ if(strcmp(name,mp->name)==0)
+ return(&mp->hdr);
+ nv_disc(np,&mp->hdr,NV_POP);
+ if(!(mp->hdr.nofree&1))
+ free((void*)mp);
+ }
+ mp = newof(0,struct Mapchar,1,n);
+ mp->trans = trans;
+ mp->lctype = lctype;
+ if(low==0)
+ mp->name = e_tolower;
+ else if(n==0)
+ mp->name = e_toupper;
+ else
+ {
+ mp->name = (char*)(mp+1);
+ strcpy((char*)mp->name,name);
+ }
+ mp->hdr.disc = &TRANS_disc;
+ return(&mp->hdr);
+}
diff --git a/src/cmd/ksh93/sh/io.c b/src/cmd/ksh93/sh/io.c
new file mode 100644
index 0000000..9649f1f
--- /dev/null
+++ b/src/cmd/ksh93/sh/io.c
@@ -0,0 +1,2647 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Input/output file processing
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include <ls.h>
+#include <stdarg.h>
+#include <regex.h>
+#include "variables.h"
+#include "path.h"
+#include "io.h"
+#include "jobs.h"
+#include "shnodes.h"
+#include "history.h"
+#include "edit.h"
+#include "timeout.h"
+#include "FEATURE/externs"
+#include "FEATURE/dynamic"
+#include "FEATURE/poll"
+
+#ifdef FNDELAY
+# ifdef EAGAIN
+# if EAGAIN!=EWOULDBLOCK
+# undef EAGAIN
+# define EAGAIN EWOULDBLOCK
+# endif
+# else
+# define EAGAIN EWOULDBLOCK
+# endif /* EAGAIN */
+# ifndef O_NONBLOCK
+# define O_NONBLOCK FNDELAY
+# endif /* !O_NONBLOCK */
+#endif /* FNDELAY */
+
+#ifndef O_SERVICE
+# define O_SERVICE O_NOCTTY
+#endif
+
+#define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
+
+static void *timeout;
+static int (*fdnotify)(int,int);
+
+#if defined(_lib_socket) && defined(_sys_socket) && defined(_hdr_netinet_in)
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# if !defined(htons) && !_lib_htons
+# define htons(x) (x)
+# endif
+# if !defined(htonl) && !_lib_htonl
+# define htonl(x) (x)
+# endif
+# if _pipe_socketpair && !_stream_peek
+# ifndef SHUT_RD
+# define SHUT_RD 0
+# endif
+# ifndef SHUT_WR
+# define SHUT_WR 1
+# endif
+# if _socketpair_shutdown_mode
+# define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||fchmod((v)[1],S_IWUSR)<0||shutdown((v)[0],SHUT_WR)<0||fchmod((v)[0],S_IRUSR)<0)?(-1):0)
+# else
+# define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||shutdown((v)[0],SHUT_WR)<0)?(-1):0)
+# endif
+# endif
+
+#if !_lib_getaddrinfo
+
+#undef EAI_SYSTEM
+
+#define EAI_SYSTEM 1
+
+#undef addrinfo
+#undef getaddrinfo
+#undef freeaddrinfo
+
+#define addrinfo local_addrinfo
+#define getaddrinfo local_getaddrinfo
+#define freeaddrinfo local_freeaddrinfo
+
+struct addrinfo
+{
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ socklen_t ai_addrlen;
+ struct sockaddr* ai_addr;
+ struct addrinfo* ai_next;
+};
+
+static int
+getaddrinfo(const char* node, const char* service, const struct addrinfo* hint, struct addrinfo **addr)
+{
+ unsigned long ip_addr = 0;
+ unsigned short ip_port = 0;
+ struct addrinfo* ap;
+ struct hostent* hp;
+ struct sockaddr_in* ip;
+ char* prot;
+ long n;
+
+ if (!(hp = gethostbyname(node)) || hp->h_addrtype!=AF_INET || hp->h_length>sizeof(struct in_addr))
+ {
+ errno = EADDRNOTAVAIL;
+ return EAI_SYSTEM;
+ }
+ ip_addr = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr;
+ if ((n = strtol(service, &prot, 10)) > 0 && n <= USHRT_MAX && !*prot)
+ ip_port = htons((unsigned short)n);
+ else
+ {
+ struct servent* sp;
+ const char* protocol = 0;
+
+ if (hint)
+ switch (hint->ai_socktype)
+ {
+ case SOCK_STREAM:
+ switch (hint->ai_protocol)
+ {
+ case 0:
+ protocol = "tcp";
+ break;
+#ifdef IPPROTO_SCTP
+ case IPPROTO_SCTP:
+ protocol = "sctp";
+ break;
+#endif
+ }
+ break;
+ case SOCK_DGRAM:
+ protocol = "udp";
+ break;
+ }
+ if (!protocol)
+ {
+ errno = EPROTONOSUPPORT;
+ return 1;
+ }
+ if (sp = getservbyname(service, protocol))
+ ip_port = sp->s_port;
+ }
+ if (!ip_port)
+ {
+ errno = EADDRNOTAVAIL;
+ return EAI_SYSTEM;
+ }
+ if (!(ap = newof(0, struct addrinfo, 1, sizeof(struct sockaddr_in))))
+ return EAI_SYSTEM;
+ if (hint)
+ *ap = *hint;
+ ap->ai_family = hp->h_addrtype;
+ ap->ai_addrlen = sizeof(struct sockaddr_in);
+ ap->ai_addr = (struct sockaddr *)(ap+1);
+ ip = (struct sockaddr_in *)ap->ai_addr;
+ ip->sin_family = AF_INET;
+ ip->sin_port = ip_port;
+ ip->sin_addr.s_addr = ip_addr;
+ *addr = ap;
+ return 0;
+}
+
+static void
+freeaddrinfo(struct addrinfo* ap)
+{
+ if (ap)
+ free(ap);
+}
+
+#endif
+
+/*
+ * return <protocol>/<host>/<service> fd
+ * If called with flags==O_NONBLOCK return 1 if protocol is supported
+ */
+
+typedef int (*Inetintr_f)(struct addrinfo*, void*);
+
+static int
+inetopen(const char* path, int flags, Inetintr_f onintr, void* handle)
+{
+ register char* s;
+ register char* t;
+ int fd;
+ int oerrno;
+ struct addrinfo hint;
+ struct addrinfo* addr;
+ struct addrinfo* p;
+ int server = !!(flags&O_SERVICE);
+
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = PF_UNSPEC;
+ switch (path[0])
+ {
+#ifdef IPPROTO_SCTP
+ case 's':
+ if (path[1]!='c' || path[2]!='t' || path[3]!='p' || path[4]!='/')
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_SCTP;
+ path += 5;
+ break;
+#endif
+ case 't':
+ if (path[1]!='c' || path[2]!='p' || path[3]!='/')
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ hint.ai_socktype = SOCK_STREAM;
+ path += 4;
+ break;
+ case 'u':
+ if (path[1]!='d' || path[2]!='p' || path[3]!='/')
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ hint.ai_socktype = SOCK_DGRAM;
+ path += 4;
+ break;
+ default:
+ errno = ENOTDIR;
+ return -1;
+ }
+ if(flags==O_NONBLOCK)
+ return 1;
+ if (!(s = strdup(path)))
+ return -1;
+ if (t = strchr(s, '/'))
+ {
+ *t++ = 0;
+ if (streq(s, "local"))
+ s = strdup("localhost");
+ fd = getaddrinfo(s, t, &hint, &addr);
+ }
+ else
+ fd = -1;
+ free(s);
+ if (fd)
+ {
+ if (fd != EAI_SYSTEM)
+ errno = ENOTDIR;
+ return -1;
+ }
+ oerrno = errno;
+ errno = 0;
+ fd = -1;
+ for (p = addr; p; p = p->ai_next)
+ {
+ /*
+ * some api's don't take the hint
+ */
+
+ if (!p->ai_protocol)
+ p->ai_protocol = hint.ai_protocol;
+ if (!p->ai_socktype)
+ p->ai_socktype = hint.ai_socktype;
+ while ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) >= 0)
+ {
+ if (server && !bind(fd, p->ai_addr, p->ai_addrlen) && !listen(fd, 5) || !server && !connect(fd, p->ai_addr, p->ai_addrlen))
+ goto done;
+ close(fd);
+ fd = -1;
+ if (errno != EINTR || !onintr)
+ break;
+ if ((*onintr)(addr, handle))
+ goto done;
+ }
+ }
+ done:
+ freeaddrinfo(addr);
+ if (fd >= 0)
+ errno = oerrno;
+ return fd;
+}
+
+#else
+
+#undef O_SERVICE
+#undef SHOPT_COSHELL
+
+#endif
+
+struct fdsave
+{
+ int orig_fd; /* original file descriptor */
+ int save_fd; /* saved file descriptor */
+ int subshell; /* saved for subshell */
+ char *tname; /* name used with >; */
+};
+
+struct Iodisc
+{
+ Sfdisc_t disc;
+ Shell_t *sh;
+};
+
+static int subexcept(Sfio_t*, int, void*, Sfdisc_t*);
+static int eval_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
+static int slowexcept(Sfio_t*, int, void*, Sfdisc_t*);
+static int pipeexcept(Sfio_t*, int, void*, Sfdisc_t*);
+static ssize_t piperead(Sfio_t*, void*, size_t, Sfdisc_t*);
+static ssize_t slowread(Sfio_t*, void*, size_t, Sfdisc_t*);
+static ssize_t subread(Sfio_t*, void*, size_t, Sfdisc_t*);
+static ssize_t tee_write(Sfio_t*,const void*,size_t,Sfdisc_t*);
+static int io_prompt(Shell_t*,Sfio_t*,int);
+static int io_heredoc(Shell_t*,register struct ionod*, const char*, int);
+static void sftrack(Sfio_t*,int,void*);
+static const Sfdisc_t eval_disc = { NULL, NULL, NULL, eval_exceptf, NULL};
+static Sfdisc_t tee_disc = {NULL,tee_write,NULL,NULL,NULL};
+static Sfio_t *subopen(Shell_t *,Sfio_t*, off_t, long);
+static const Sfdisc_t sub_disc = { subread, 0, 0, subexcept, 0 };
+
+struct subfile
+{
+ Sfdisc_t disc;
+ Sfio_t *oldsp;
+ off_t offset;
+ long size;
+ long left;
+};
+
+struct Eof
+{
+ Namfun_t hdr;
+ int fd;
+};
+
+static Sfdouble_t nget_cur_eof(register Namval_t* np, Namfun_t *fp)
+{
+ struct Eof *ep = (struct Eof*)fp;
+ Sfoff_t end, cur =lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
+ if(*np->nvname=='C')
+ return((Sfdouble_t)cur);
+ if(cur<0)
+ return((Sfdouble_t)-1);
+ end =lseek(ep->fd, (Sfoff_t)0, SEEK_END);
+ lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
+ return((Sfdouble_t)end);
+}
+
+static const Namdisc_t EOF_disc = { sizeof(struct Eof), 0, 0, nget_cur_eof};
+
+#define MATCH_BUFF (64*1024)
+struct Match
+{
+ Sfoff_t offset;
+ char *base;
+};
+
+static int matchf(void *handle, char *ptr, size_t size)
+{
+ struct Match *mp = (struct Match*)handle;
+ mp->offset += (ptr-mp->base);
+ return(1);
+}
+
+
+static struct fdsave *filemap;
+static short filemapsize;
+
+#define PSEUDOFD (SHRT_MAX)
+
+/* ======== input output and file copying ======== */
+
+int sh_iovalidfd(Shell_t *shp, int fd)
+{
+ Sfio_t **sftable = shp->sftable;
+ int max,n, **fdptrs = shp->fdptrs;
+ unsigned char *fdstatus = shp->fdstatus;
+ if(fd<0)
+ return(0);
+ if(fd < shp->gd->lim.open_max)
+ return(1);
+ max = strtol(astconf("OPEN_MAX",NiL,NiL),NiL,0);
+ if(fd >= max)
+ {
+ errno = EBADF;
+ return(0);
+ }
+ n = (fd+16)&~0xf;
+ if(n > max)
+ n = max;
+ max = shp->gd->lim.open_max;
+ shp->sftable = (Sfio_t**)calloc((n+1)*(sizeof(int*)+sizeof(Sfio_t*)+1),1);
+ if(max)
+ memcpy(shp->sftable,sftable,max*sizeof(Sfio_t*));
+ shp->fdptrs = (int**)(&shp->sftable[n]);
+ if(max)
+ memcpy(shp->fdptrs,fdptrs,max*sizeof(int*));
+ shp->fdstatus = (unsigned char*)(&shp->fdptrs[n]);
+ if(max)
+ memcpy(shp->fdstatus,fdstatus,max);
+ if(sftable)
+ free((void*)sftable);
+ shp->gd->lim.open_max = n;
+ return(1);
+}
+
+int sh_inuse(Shell_t *shp, int fd)
+{
+ return(fd < shp->gd->lim.open_max && shp->fdptrs[fd]);
+}
+
+void sh_ioinit(Shell_t *shp)
+{
+ filemapsize = 8;
+ filemap = (struct fdsave*)malloc(filemapsize*sizeof(struct fdsave));
+ sh_iovalidfd(shp,16);
+ shp->sftable[0] = sfstdin;
+ shp->sftable[1] = sfstdout;
+ shp->sftable[2] = sfstderr;
+ sfnotify(sftrack);
+ sh_iostream(shp,0);
+ sh_iostream(shp,1);
+ /* all write steams are in the same pool and share outbuff */
+ shp->outpool = sfopen(NIL(Sfio_t*),NIL(char*),"sw"); /* pool identifier */
+ shp->outbuff = (char*)malloc(IOBSIZE+4);
+ shp->errbuff = (char*)malloc(IOBSIZE/4);
+ sfsetbuf(sfstderr,shp->errbuff,IOBSIZE/4);
+ sfsetbuf(sfstdout,shp->outbuff,IOBSIZE);
+ sfpool(sfstdout,shp->outpool,SF_WRITE);
+ sfpool(sfstderr,shp->outpool,SF_WRITE);
+ sfset(sfstdout,SF_LINE,0);
+ sfset(sfstderr,SF_LINE,0);
+ sfset(sfstdin,SF_SHARE|SF_PUBLIC,1);
+}
+
+/*
+ * Handle output stream exceptions
+ */
+static int outexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ static int active = 0;
+ if(type==SF_DPOP || type==SF_FINAL)
+ free((void*)handle);
+ else if(type==SF_WRITE && (*(ssize_t*)data)<0 && sffileno(iop)!=2)
+ switch (errno)
+ {
+ case EINTR:
+ case EPIPE:
+#ifdef ECONNRESET
+ case ECONNRESET:
+#endif
+#ifdef ESHUTDOWN
+ case ESHUTDOWN:
+#endif
+ break;
+ default:
+ if(!active)
+ {
+ int mode = ((struct checkpt*)shp->jmplist)->mode;
+ int save = errno;
+ active = 1;
+ ((struct checkpt*)shp->jmplist)->mode = 0;
+ sfpurge(iop);
+ sfpool(iop,NIL(Sfio_t*),SF_WRITE);
+ errno = save;
+ errormsg(SH_DICT,ERROR_system(1),e_badwrite,sffileno(iop));
+ active = 0;
+ ((struct checkpt*)shp->jmplist)->mode = mode;
+ sh_exit(1);
+ }
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ * create or initialize a stream corresponding to descriptor <fd>
+ * a buffer with room for a sentinal is allocated for a read stream.
+ * A discipline is inserted when read stream is a tty or a pipe
+ * For output streams, the buffer is set to sh.output and put into
+ * the sh.outpool synchronization pool
+ */
+Sfio_t *sh_iostream(Shell_t *shp, register int fd)
+{
+ register Sfio_t *iop;
+ register int status = sh_iocheckfd(shp,fd);
+ register int flags = SF_WRITE;
+ char *bp;
+ struct Iodisc *dp;
+ if(status==IOCLOSE)
+ {
+ switch(fd)
+ {
+ case 0:
+ return(sfstdin);
+ case 1:
+ return(sfstdout);
+ case 2:
+ return(sfstderr);
+ }
+ return(NIL(Sfio_t*));
+ }
+ if(status&IOREAD)
+ {
+ if(!(bp = (char *)malloc(IOBSIZE+1)))
+ return(NIL(Sfio_t*));
+ flags |= SF_READ;
+ if(!(status&IOWRITE))
+ flags &= ~SF_WRITE;
+ }
+ else
+ bp = shp->outbuff;
+ if(status&IODUP)
+ flags |= SF_SHARE|SF_PUBLIC;
+ if((iop = shp->sftable[fd]) && sffileno(iop)>=0)
+ {
+ if(status&IOTTY)
+ sfset(iop,SF_LINE|SF_WCWIDTH,1);
+ sfsetbuf(iop, bp, IOBSIZE);
+ }
+ else if(!(iop=sfnew((fd<=2?iop:0),bp,IOBSIZE,fd,flags)))
+ return(NIL(Sfio_t*));
+ dp = newof(0,struct Iodisc,1,0);
+ dp->sh = shp;
+ if(status&IOREAD)
+ {
+ sfset(iop,SF_MALLOC,1);
+ if(!(status&IOWRITE))
+ sfset(iop,SF_IOCHECK,1);
+ dp->disc.exceptf = slowexcept;
+ if(status&IOTTY)
+ dp->disc.readf = slowread;
+ else if(status&IONOSEEK)
+ {
+ dp->disc.readf = piperead;
+ sfset(iop, SF_IOINTR,1);
+ }
+ else
+ dp->disc.readf = 0;
+ dp->disc.seekf = 0;
+ dp->disc.writef = 0;
+ }
+ else
+ {
+ if((status&(IONOSEEK|IOTTY)) == IONOSEEK)
+ dp->disc.exceptf = pipeexcept;
+ else
+ dp->disc.exceptf = outexcept;
+ sfpool(iop,shp->outpool,SF_WRITE);
+ }
+ sfdisc(iop,&dp->disc);
+ shp->sftable[fd] = iop;
+ return(iop);
+}
+
+/*
+ * preserve the file descriptor or stream by moving it
+ */
+static void io_preserve(Shell_t* shp, register Sfio_t *sp, register int f2)
+{
+ register int fd;
+ if(sp)
+ fd = sfsetfd(sp,10);
+ else
+ fd = sh_fcntl(f2,F_DUPFD,10);
+ if(f2==shp->infd)
+ shp->infd = fd;
+ if(fd<0)
+ {
+ shp->toomany = 1;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ }
+ if(f2 >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,f2);
+ if(shp->fdptrs[fd]=shp->fdptrs[f2])
+ {
+ if(f2==job.fd)
+ job.fd=fd;
+ *shp->fdptrs[fd] = fd;
+ shp->fdptrs[f2] = 0;
+ }
+ shp->sftable[fd] = sp;
+ shp->fdstatus[fd] = shp->fdstatus[f2];
+ if(fcntl(f2,F_GETFD,0)&1)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ shp->sftable[f2] = 0;
+}
+
+/*
+ * Given a file descriptor <f1>, move it to a file descriptor number <f2>
+ * If <f2> is needed move it, otherwise it is closed first.
+ * The original stream <f1> is closed.
+ * The new file descriptor <f2> is returned;
+ */
+int sh_iorenumber(Shell_t *shp, register int f1,register int f2)
+{
+ register Sfio_t *sp = shp->sftable[f2];
+ if(f1!=f2)
+ {
+ /* see whether file descriptor is in use */
+ if(sh_inuse(shp,f2) || (f2>2 && sp))
+ {
+ if(!(shp->inuse_bits&(1<<f2)))
+ io_preserve(shp,sp,f2);
+ sp = 0;
+ }
+ else if(f2==0)
+ shp->st.ioset = 1;
+ sh_close(f2);
+ if(f2<=2 && sp)
+ {
+ register Sfio_t *spnew = sh_iostream(shp,f1);
+ shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
+ sfsetfd(spnew,f2);
+ sfswap(spnew,sp);
+ sfset(sp,SF_SHARE|SF_PUBLIC,1);
+ }
+ else
+ {
+ shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
+ if((f2 = sh_fcntl(f1,F_DUPFD, f2)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ else if(f2 <= 2)
+ sh_iostream(shp,f2);
+ }
+ if(sp)
+ shp->sftable[f1] = 0;
+ if(shp->fdstatus[f1]!=IOCLOSE)
+ sh_close(f1);
+ }
+ else if(sp)
+ {
+ sfsetfd(sp,f2);
+ if(f2<=2)
+ sfset(sp,SF_SHARE|SF_PUBLIC,1);
+ }
+ if(f2>=shp->gd->lim.open_max)
+ sh_iovalidfd(shp,f2);
+ return(f2);
+}
+
+/*
+ * close a file descriptor and update stream table and attributes
+ */
+int sh_close(register int fd)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ register int r = 0;
+ if(fd<0)
+ return(-1);
+ if(fd >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ if(!(sp=shp->sftable[fd]) || sfclose(sp) < 0)
+ {
+ if(fdnotify)
+ (*fdnotify)(fd,SH_FDCLOSE);
+ r=close(fd);
+ }
+ if(fd>2)
+ shp->sftable[fd] = 0;
+ shp->fdstatus[fd] = IOCLOSE;
+ if(shp->fdptrs[fd])
+ *shp->fdptrs[fd] = -1;
+ shp->fdptrs[fd] = 0;
+ if(fd < 10)
+ shp->inuse_bits &= ~(1<<fd);
+ return(r);
+}
+
+#ifdef O_SERVICE
+
+static int
+onintr(struct addrinfo* addr, void* handle)
+{
+ Shell_t* sh = (Shell_t*)handle;
+
+ if (sh->trapnote&SH_SIGSET)
+ {
+ freeaddrinfo(addr);
+ sh_exit(SH_EXITSIG);
+ return -1;
+ }
+ if (sh->trapnote)
+ sh_chktrap(sh);
+ return 0;
+}
+
+#endif
+
+/*
+ * Mimic open(2) with checks for pseudo /dev/ files.
+ */
+int sh_open(register const char *path, int flags, ...)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fd = -1;
+ mode_t mode;
+ char *e;
+ va_list ap;
+ va_start(ap, flags);
+ mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
+ va_end(ap);
+ errno = 0;
+ if(path==0)
+ {
+ errno = EFAULT;
+ return(-1);
+ }
+ if(*path==0)
+ {
+ errno = ENOENT;
+ return(-1);
+ }
+ if (path[0]=='/' && path[1]=='d' && path[2]=='e' && path[3]=='v' && path[4]=='/')
+ {
+ switch (path[5])
+ {
+ case 'f':
+ if (path[6]=='d' && path[7]=='/')
+ {
+ if(flags==O_NONBLOCK)
+ return(1);
+ fd = (int)strtol(path+8, &e, 10);
+ if (*e)
+ fd = -1;
+ }
+ break;
+ case 's':
+ if (path[6]=='t' && path[7]=='d')
+ switch (path[8])
+ {
+ case 'e':
+ if (path[9]=='r' && path[10]=='r' && !path[11])
+ fd = 2;
+ break;
+ case 'i':
+ if (path[9]=='n' && !path[10])
+ fd = 0;
+ break;
+ case 'o':
+ if (path[9]=='u' && path[10]=='t' && !path[11])
+ fd = 1;
+ break;
+ }
+ }
+#ifdef O_SERVICE
+ if (fd < 0)
+ {
+ if ((fd = inetopen(path+5, flags, onintr, shp)) < 0 && errno != ENOTDIR)
+ return -1;
+ if(flags==O_NONBLOCK)
+ return(fd>=0);
+ if (fd >= 0)
+ goto ok;
+ }
+ if(flags==O_NONBLOCK)
+ return(0);
+#endif
+ }
+ if (fd >= 0)
+ {
+ int nfd= -1;
+ if (flags & O_CREAT)
+ {
+ struct stat st;
+ if (stat(path,&st) >=0)
+ nfd = open(path,flags,st.st_mode);
+ }
+ else
+ nfd = open(path,flags);
+ if(nfd>=0)
+ {
+ fd = nfd;
+ goto ok;
+ }
+ if((mode=sh_iocheckfd(shp,fd))==IOCLOSE)
+ return(-1);
+ flags &= O_ACCMODE;
+ if(!(mode&IOWRITE) && ((flags==O_WRONLY) || (flags==O_RDWR)))
+ return(-1);
+ if(!(mode&IOREAD) && ((flags==O_RDONLY) || (flags==O_RDWR)))
+ return(-1);
+ if((fd=dup(fd))<0)
+ return(-1);
+ }
+ else
+ {
+#if SHOPT_REGRESS
+ char buf[PATH_MAX];
+ if(strncmp(path,"/etc/",5)==0)
+ {
+ sfsprintf(buf, sizeof(buf), "%s%s", sh_regress_etc(path, __LINE__, __FILE__), path+4);
+ path = buf;
+ }
+#endif
+ while((fd = open(path, flags, mode)) < 0)
+ if(errno!=EINTR || shp->trapnote)
+ return(-1);
+ }
+ ok:
+ flags &= O_ACCMODE;
+ if(flags==O_WRONLY)
+ mode = IOWRITE;
+ else if(flags==O_RDWR)
+ mode = (IOREAD|IOWRITE);
+ else
+ mode = IOREAD;
+ if(fd >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ shp->fdstatus[fd] = mode;
+ return(fd);
+}
+
+/*
+ * Open a file for reading
+ * On failure, print message.
+ */
+int sh_chkopen(register const char *name)
+{
+ register int fd = sh_open(name,O_RDONLY,0);
+ if(fd < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,name);
+ return(fd);
+}
+
+/*
+ * move open file descriptor to a number > 2
+ */
+int sh_iomovefd(register int fdold)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fdnew;
+ if(fdold >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fdold);
+ if(fdold<0 || fdold>2)
+ return(fdold);
+ fdnew = sh_iomovefd(dup(fdold));
+ shp->fdstatus[fdnew] = (shp->fdstatus[fdold]&~IOCLEX);
+ close(fdold);
+ shp->fdstatus[fdold] = IOCLOSE;
+ return(fdnew);
+}
+
+/*
+ * create a pipe and print message on failure
+ */
+int sh_pipe(register int pv[])
+{
+ Shell_t *shp = sh_getinterp();
+ int fd[2];
+ if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ pv[0] = sh_iomovefd(pv[0]);
+ pv[1] = sh_iomovefd(pv[1]);
+ shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
+ shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
+ sh_subsavefd(pv[0]);
+ sh_subsavefd(pv[1]);
+ return(0);
+}
+
+#if SHOPT_COSHELL
+ int sh_coaccept(Shell_t *shp,int *pv,int out)
+ {
+ int fd = accept(pv[0],(struct sockaddr*)0,(socklen_t*)0);
+ sh_close(pv[0]);
+ pv[0] = -1;
+ if(fd<0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ if((pv[out]=sh_fcntl(fd,F_DUPFD,10)) >=10)
+ sh_close(fd);
+ else
+ pv[out] = sh_iomovefd(fd);
+ if(fcntl(pv[out],F_SETFD,FD_CLOEXEC) >=0)
+ shp->fdstatus[pv[out]] |= IOCLEX;
+ shp->fdstatus[pv[out]] = (out?IOWRITE:IOREAD);
+ shp->fdstatus[pv[out]] |= IONOSEEK;
+ sh_subsavefd(pv[out]);
+#if defined(SHUT_RD) && defined(SHUT_WR)
+ shutdown(pv[out],out?SHUT_RD:SHUT_WR);
+#endif
+ return(0);
+ }
+
+ int sh_copipe(Shell_t *shp, int *pv, int out)
+ {
+ int r,port=20000;
+ struct sockaddr_in sin;
+ socklen_t slen;
+ if ((pv[out] = socket (AF_INET, SOCK_STREAM, 0)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ do
+ {
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(++port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+ slen = sizeof (sin);
+ }
+ while ((r=bind (pv[out], (struct sockaddr *) &sin, slen)) == -1 && errno==EADDRINUSE);
+ if(r<0 || listen(pv[out],5) <0)
+ {
+ close(pv[out]);
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ }
+ fcntl(pv[out],F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[pv[out]] |= IOCLEX;
+ pv[1-out] = -1;
+ pv[2] = port;
+ return(0);
+ }
+#endif /* SHOPT_COSHELL */
+
+static int pat_seek(void *handle, const char *str, size_t sz)
+{
+ char **bp = (char**)handle;
+ *bp = (char*)str;
+ return(-1);
+}
+
+static int pat_line(const regex_t* rp, const char *buff, register size_t n)
+{
+ register const char *cp=buff, *sp;
+ while(n>0)
+ {
+ for(sp=cp; n-->0 && *cp++ != '\n';);
+ if(regnexec(rp,sp,cp-sp, 0, (regmatch_t*)0, 0)==0)
+ return(sp-buff);
+ }
+ return(cp-buff);
+}
+
+static int io_patseek(Shell_t *shp, regex_t *rp, Sfio_t* sp, int flags)
+{
+ char *cp, *match;
+ int r, fd=sffileno(sp), close_exec = shp->fdstatus[fd]&IOCLEX;
+ int was_share,s=(PIPE_BUF>SF_BUFSIZE?SF_BUFSIZE:PIPE_BUF);
+ size_t n,m;
+ shp->fdstatus[sffileno(sp)] |= IOCLEX;
+ if(fd==0)
+ was_share = sfset(sp,SF_SHARE,1);
+ while((cp=sfreserve(sp, -s, SF_LOCKR)) || (cp=sfreserve(sp,SF_UNBOUND, SF_LOCKR)))
+ {
+ m = n = sfvalue(sp);
+ while(n>0 && cp[n-1]!='\n')
+ n--;
+ if(n)
+ m = n;
+ r = regrexec(rp,cp,m,0,(regmatch_t*)0, 0, '\n', (void*)&match, pat_seek);
+ if(r<0)
+ m = match-cp;
+ else if(r==2)
+ {
+ if((m = pat_line(rp,cp,m)) < n)
+ r = -1;
+ }
+ if(m && (flags&IOCOPY))
+ sfwrite(sfstdout,cp,m);
+ sfread(sp,cp,m);
+ if(r<0)
+ break;
+ }
+ if(!close_exec)
+ shp->fdstatus[sffileno(sp)] &= ~IOCLEX;
+ if(fd==0 && !(was_share&SF_SHARE))
+ sfset(sp, SF_SHARE,0);
+ return(0);
+}
+
+static Sfoff_t file_offset(Shell_t *shp, int fn, char *fname)
+{
+ Sfio_t *sp = shp->sftable[fn];
+ char *cp;
+ Sfoff_t off;
+ struct Eof endf;
+ Namval_t *mp = nv_open("EOF",shp->var_tree,0);
+ Namval_t *pp = nv_open("CUR",shp->var_tree,0);
+ memset(&endf,0,sizeof(struct Eof));
+ endf.fd = fn;
+ endf.hdr.disc = &EOF_disc;
+ endf.hdr.nofree = 1;
+ if(mp)
+ nv_stack(mp, &endf.hdr);
+ if(pp)
+ nv_stack(pp, &endf.hdr);
+ if(sp)
+ sfsync(sp);
+ off = sh_strnum(fname, &cp, 0);
+ if(mp)
+ nv_stack(mp, NiL);
+ if(pp)
+ nv_stack(pp, NiL);
+ return(*cp?(Sfoff_t)-1:off);
+}
+
+/*
+ * close a pipe
+ */
+void sh_pclose(register int pv[])
+{
+ if(pv[0]>=2)
+ sh_close(pv[0]);
+ if(pv[1]>=2)
+ sh_close(pv[1]);
+ pv[0] = pv[1] = -1;
+}
+
+static char *io_usename(char *name, int *perm, int fno, int mode)
+{
+ struct stat statb;
+ char *tname, *sp, *ep;
+ int fd;
+ if(mode==0)
+ {
+ if((fd = sh_open(name,O_RDONLY,0)) > 0)
+ {
+ if(fstat(fd,&statb) < 0)
+ return(0);
+ if(!S_ISREG(statb.st_mode))
+ return(0);
+ *perm = statb.st_mode&(RW_ALL|(S_IXUSR|S_IXGRP|S_IXOTH));
+ }
+ else if(fd < 0 && errno!=ENOENT)
+ return(0);
+ }
+ stakseek(1);
+ stakputs(name);
+ stakputc(0);
+ pathcanon(stakptr(1),PATH_PHYSICAL);
+ sp = ep = stakptr(1);
+ if(ep = strrchr(sp,'/'))
+ {
+ memmove(stakptr(0),sp,++ep-sp);
+ stakseek(ep-sp);
+ }
+ else
+ {
+ ep = sp;
+ stakseek(0);
+ }
+ stakputc('.');
+ sfprintf(stkstd,"%<#d_%d{;.tmp",getpid(),fno);
+ tname = stakfreeze(1);
+ switch(mode)
+ {
+ unlink(tname);
+ break;
+ case 1:
+ rename(tname,name);
+ break;
+ default:
+ unlink(tname);
+ break;
+ }
+ return(tname);
+}
+
+/*
+ * I/O redirection
+ * flag = 0 if files are to be restored
+ * flag = 2 if files are to be closed on exec
+ * flag = 3 when called from $( < ...), just open file and return
+ * flag = SH_SHOWME for trace only
+ */
+int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
+{
+ Sfoff_t off;
+ register char *fname;
+ register int fd, iof;
+ const char *message = e_open;
+ int o_mode; /* mode flag for open */
+ static char io_op[7]; /* used for -x trace info */
+ int trunc=0, clexec=0, fn, traceon;
+ int r, indx = shp->topfd, perm= -1;
+ char *tname=0, *after="", *trace = shp->st.trap[SH_DEBUGTRAP];
+ Namval_t *np=0;
+ int isstring = shp->subshell?(sfset(sfstdout,0,0)&SF_STRING):0;
+
+ if(flag==2)
+ clexec = 1;
+ if(iop)
+ traceon = sh_trace(shp,NIL(char**),0);
+ for(;iop;iop=iop->ionxt)
+ {
+ iof=iop->iofile;
+ fn = (iof&IOUFD);
+ if(fn==1 && shp->subshell && !shp->subshare && (flag==2 || isstring))
+ sh_subfork();
+ if(shp->redir0 && fn==0 && !(iof&IOMOV))
+ shp->redir0 = 2;
+ io_op[0] = '0'+(iof&IOUFD);
+ if(iof&IOPUT)
+ {
+ io_op[1] = '>';
+ o_mode = O_WRONLY|O_CREAT;
+ }
+ else
+ {
+ io_op[1] = '<';
+ o_mode = O_RDONLY|O_NONBLOCK;
+ }
+ io_op[2] = 0;
+ io_op[3] = 0;
+ io_op[4] = 0;
+ fname = iop->ioname;
+ if(!(iof&IORAW))
+ {
+ if(iof&IOLSEEK)
+ {
+ struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
+ memset(ap, 0, ARGVAL);
+ ap->argflag = ARG_MAC;
+ strcpy(ap->argval,iop->ioname);
+ fname=sh_macpat(shp,ap,(iof&IOARITH)?ARG_ARITH:ARG_EXP);
+ }
+ else if(iof&IOPROCSUB)
+ {
+ struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
+ memset(ap, 0, ARGVAL);
+ if(iof&IOPUT)
+ ap->argflag = ARG_RAW;
+ else if(shp->subshell)
+ sh_subtmpfile(shp);
+ ap->argchn.ap = (struct argnod*)fname;
+ ap = sh_argprocsub(shp,ap);
+ fname = ap->argval;
+ }
+ else
+ fname=sh_mactrim(shp,fname,(!sh_isoption(SH_NOGLOB)&&sh_isoption(SH_INTERACTIVE))?2:0);
+ }
+ errno=0;
+ np = 0;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ if(!(iof&(IODOC|IOLSEEK|IOMOV)))
+ sh_coaddfile(shp,fname);
+ continue;
+ }
+#endif /* SHOPT_COSHELL */
+ if(iop->iovname)
+ {
+ np = nv_open(iop->iovname,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
+ if(nv_isattr(np,NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ io_op[0] = '}';
+ if((iof&IOLSEEK) || ((iof&IOMOV) && *fname=='-'))
+ fn = nv_getnum(np);
+ }
+ if(fn>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fn))
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ if(iof&IOLSEEK)
+ {
+ io_op[2] = '#';
+ if(iof&IOARITH)
+ {
+ strcpy(&io_op[3]," ((");
+ after = "))";
+ }
+ else if(iof&IOCOPY)
+ io_op[3] = '#';
+ goto traceit;
+ }
+ if(*fname || (iof&(IODOC|IOSTRG))==(IODOC|IOSTRG))
+ {
+ if(iof&IODOC)
+ {
+ if(traceon)
+ sfputr(sfstderr,io_op,'<');
+ fd = io_heredoc(shp,iop,fname,traceon);
+ if(traceon && (flag==SH_SHOWME))
+ sh_close(fd);
+ fname = 0;
+ }
+ else if(iof&IOMOV)
+ {
+ int dupfd,toclose= -1;
+ io_op[2] = '&';
+ if((fd=fname[0])>='0' && fd<='9')
+ {
+ char *number = fname;
+ dupfd = strtol(fname,&number,10);
+ if(*number=='-')
+ {
+ toclose = dupfd;
+ number++;
+ }
+ if(*number || dupfd > IOUFD)
+ {
+ message = e_file;
+ goto fail;
+ }
+ if(shp->subshell && dupfd==1)
+ {
+ if(sfset(sfstdout,0,0)&SF_STRING)
+ sh_subtmpfile(shp);
+ if(shp->comsub==1)
+ shp->subdup |= 1<<fn;
+ dupfd = sffileno(sfstdout);
+ }
+ else if(shp->sftable[dupfd])
+ sfsync(shp->sftable[dupfd]);
+ if(dupfd!=1 && fn < 10)
+ shp->subdup &= ~(1<<fn);
+ }
+ else if(fd=='-' && fname[1]==0)
+ {
+ fd= -1;
+ goto traceit;
+ }
+ else if(fd=='p' && fname[1]==0)
+ {
+ if(iof&IOPUT)
+ dupfd = shp->coutpipe;
+ else
+ dupfd = shp->cpipe[0];
+ if(flag)
+ toclose = dupfd;
+ }
+ else
+ {
+ message = e_file;
+ goto fail;
+ }
+ if(flag==SH_SHOWME)
+ goto traceit;
+ if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
+ goto fail;
+ if(fd>= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ sh_iocheckfd(shp,dupfd);
+ shp->fdstatus[fd] = (shp->fdstatus[dupfd]&~IOCLEX);
+ if(toclose<0 && shp->fdstatus[fd]&IOREAD)
+ shp->fdstatus[fd] |= IODUP;
+ else if(dupfd==shp->cpipe[0])
+ sh_pclose(shp->cpipe);
+ else if(toclose>=0)
+ {
+ if(flag==0)
+ sh_iosave(shp,toclose,indx,(char*)0); /* save file descriptor */
+ sh_close(toclose);
+ }
+ }
+ else if(iof&IORDW)
+ {
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
+ io_op[2] = '>';
+ o_mode = O_RDWR|O_CREAT;
+ if(iof&IOREWRITE)
+ trunc = io_op[2] = ';';
+ goto openit;
+ }
+ else if(!(iof&IOPUT))
+ {
+ if(flag==SH_SHOWME)
+ goto traceit;
+ fd=sh_chkopen(fname);
+ }
+ else if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
+ else
+ {
+ if(iof&IOAPP)
+ {
+ io_op[2] = '>';
+ o_mode |= O_APPEND;
+ }
+ else if((iof&IOREWRITE) && (flag==0 || flag==1 || sh_subsavefd(fn)))
+ {
+ io_op[2] = ';';
+ o_mode |= O_TRUNC;
+ if(tname = io_usename(fname,&perm,fn,0))
+ o_mode |= O_EXCL;
+ }
+ else
+ {
+ o_mode |= O_TRUNC;
+ if(iof&IOCLOB)
+ io_op[2] = '|';
+ else if(sh_isoption(SH_NOCLOBBER))
+ {
+ struct stat sb;
+ if(stat(fname,&sb)>=0)
+ {
+#if SHOPT_FS_3D
+ if(S_ISREG(sb.st_mode)&&
+ (!shp->gd->lim.fs3d || iview(&sb)==0))
+#else
+ if(S_ISREG(sb.st_mode))
+#endif /* SHOPT_FS_3D */
+ {
+ errno = EEXIST;
+ errormsg(SH_DICT,ERROR_system(1),e_exists,fname);
+ }
+ }
+ else
+ o_mode |= O_EXCL;
+ }
+ }
+ openit:
+ if(flag!=SH_SHOWME)
+ {
+ if((fd=sh_open(tname?tname:fname,o_mode,RW_ALL)) <0)
+ errormsg(SH_DICT,ERROR_system(1),((o_mode&O_CREAT)?e_create:e_open),fname);
+ if(perm>0)
+#if _lib_fchmod
+ fchmod(fd,perm);
+#else
+ chmod(tname,perm);
+#endif
+ }
+ }
+ traceit:
+ if(traceon && fname)
+ {
+ if(np)
+ sfprintf(sfstderr,"{%s",nv_name(np));
+ sfprintf(sfstderr,"%s %s%s%c",io_op,fname,after,iop->ionxt?' ':'\n');
+ }
+ if(flag==SH_SHOWME)
+ return(indx);
+ if(trace && fname)
+ {
+ char *argv[7], **av=argv;
+ av[3] = io_op;
+ av[4] = fname;
+ av[5] = 0;
+ av[6] = 0;
+ if(iof&IOARITH)
+ av[5] = after;
+ if(np)
+ {
+ av[0] = "{";
+ av[1] = nv_name(np);
+ av[2] = "}";
+ }
+ else
+ av +=3;
+ sh_debug(shp,trace,(char*)0,(char*)0,av,ARG_NOGLOB);
+ }
+ if(iof&IOLSEEK)
+ {
+ Sfio_t *sp = shp->sftable[fn];
+ r = shp->fdstatus[fn];
+ if(!(r&(IOSEEK|IONOSEEK)))
+ r = sh_iocheckfd(shp,fn);
+ sfsprintf(io_op,sizeof(io_op),"%d\0",fn);
+ if(r==IOCLOSE)
+ {
+ fname = io_op;
+ message = e_file;
+ goto fail;
+ }
+ if(iof&IOARITH)
+ {
+ if(r&IONOSEEK)
+ {
+ fname = io_op;
+ message = e_notseek;
+ goto fail;
+ }
+ message = e_badseek;
+ if((off = file_offset(shp,fn,fname))<0)
+ goto fail;
+ if(sp)
+ {
+ off=sfseek(sp, off, SEEK_SET);
+ sfsync(sp);
+ }
+ else
+ off=lseek(fn, off, SEEK_SET);
+ if(off<0)
+ r = -1;
+ }
+ else
+ {
+ regex_t *rp;
+ extern const char e_notimp[];
+ if(!(r&IOREAD))
+ {
+ message = e_noread;
+ goto fail;
+ }
+ if(!(rp = regcache(fname, REG_SHELL|REG_NOSUB|REG_NEWLINE|REG_AUGMENTED|REG_FIRST|REG_LEFT|REG_RIGHT, &r)))
+ {
+ message = e_badpattern;
+ goto fail;
+ }
+ if(!sp)
+ sp = sh_iostream(shp,fn);
+ r=io_patseek(shp,rp,sp,iof);
+ if(sp && flag==3)
+ {
+ /* close stream but not fn */
+ sfsetfd(sp,-1);
+ sfclose(sp);
+ }
+ }
+ if(r<0)
+ goto fail;
+ if(flag==3)
+ return(fn);
+ continue;
+ }
+ if(!np)
+ {
+ if(flag==0 || tname || (flag==1 && fn==1 && (shp->fdstatus[fn]&IONOSEEK) && shp->outpipepid && shp->outpipepid==getpid()))
+ {
+ if(fd==fn)
+ {
+ if((r=sh_fcntl(fd,F_DUPFD,10)) > 0)
+ {
+ fd = r;
+ sh_close(fn);
+ }
+ }
+ sh_iosave(shp,fn,indx,tname?fname:(trunc?Empty:0));
+ }
+ else if(sh_subsavefd(fn))
+ sh_iosave(shp,fn,indx|IOSUBSHELL,tname?fname:0);
+ }
+ if(fd<0)
+ {
+ if(sh_inuse(shp,fn) || (fn && fn==shp->infd))
+ {
+ if(fn>9 || !(shp->inuse_bits&(1<<fn)))
+ io_preserve(shp,shp->sftable[fn],fn);
+ }
+ sh_close(fn);
+ }
+ if(flag==3)
+ return(fd);
+ if(fd>=0)
+ {
+ if(np)
+ {
+ int32_t v;
+ fn = fd;
+ if(fd<10)
+ {
+ if((fn=fcntl(fd,F_DUPFD,10)) < 0)
+ goto fail;
+ if(fn>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fn))
+ goto fail;
+ shp->fdstatus[fn] = shp->fdstatus[fd];
+ sh_close(fd);
+ fd = fn;
+ }
+ _nv_unset(np,0);
+ nv_onattr(np,NV_INT32);
+ v = fn;
+ nv_putval(np,(char*)&v, NV_INT32);
+ sh_iocheckfd(shp,fd);
+ }
+ else
+ {
+ fd = sh_iorenumber(shp,sh_iomovefd(fd),fn);
+ if(fn>2 && fn<10)
+ shp->inuse_bits |= (1<<fn);
+ }
+ }
+ if(fd >2 && clexec)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ }
+ else
+ goto fail;
+ }
+ return(indx);
+fail:
+ errormsg(SH_DICT,ERROR_system(1),message,fname);
+ /* NOTREACHED */
+ return(0);
+}
+/*
+ * Create a tmp file for the here-document
+ */
+static int io_heredoc(Shell_t *shp,register struct ionod *iop, const char *name, int traceon)
+{
+ register Sfio_t *infile = 0, *outfile, *tmp;
+ register int fd;
+ Sfoff_t off;
+ if(!(iop->iofile&IOSTRG) && (!shp->heredocs || iop->iosize==0))
+ return(sh_open(e_devnull,O_RDONLY));
+ /* create an unnamed temporary file */
+ if(!(outfile=sftmp(0)))
+ errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
+ if(iop->iofile&IOSTRG)
+ {
+ if(traceon)
+ sfprintf(sfstderr,"< %s\n",name);
+ sfputr(outfile,name,'\n');
+ }
+ else
+ {
+ /*
+ * the locking is only needed in case & blocks process
+ * here-docs so this can be eliminted in some cases
+ */
+ struct flock lock;
+ int fno = sffileno(shp->heredocs);
+ if(fno>=0)
+ {
+ memset((void*)&lock,0,sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ fcntl(fno,F_SETLKW,&lock);
+ lock.l_type = F_UNLCK;
+ }
+ off = sftell(shp->heredocs);
+ infile = subopen(shp,shp->heredocs,iop->iooffset,iop->iosize);
+ if(traceon)
+ {
+ char *cp = sh_fmtq(iop->iodelim);
+ fd = (*cp=='$' || *cp=='\'')?' ':'\\';
+ sfprintf(sfstderr," %c%s\n",fd,cp);
+ sfdisc(outfile,&tee_disc);
+ }
+ tmp = outfile;
+ if(fno>=0 && !(iop->iofile&IOQUOTE))
+ tmp = sftmp(iop->iosize<IOBSIZE?iop->iosize:0);
+ if(fno>=0 || (iop->iofile&IOQUOTE))
+ {
+ /* This is a quoted here-document, not expansion */
+ sfmove(infile,tmp,SF_UNBOUND,-1);
+ sfclose(infile);
+ if(sffileno(tmp)>0)
+ {
+ sfsetbuf(tmp,malloc(IOBSIZE+1),IOBSIZE);
+ sfset(tmp,SF_MALLOC,1);
+ }
+ sfseek(shp->heredocs,off,SEEK_SET);
+ if(fno>=0)
+ fcntl(fno,F_SETLK,&lock);
+ sfseek(tmp,(off_t)0,SEEK_SET);
+ infile = tmp;
+ }
+ if(!(iop->iofile&IOQUOTE))
+ {
+ char *lastpath = shp->lastpath;
+ sh_machere(shp,infile,outfile,iop->ioname);
+ shp->lastpath = lastpath;
+ if(infile)
+ sfclose(infile);
+ }
+ }
+ /* close stream outfile, but save file descriptor */
+ fd = sffileno(outfile);
+ sfsetfd(outfile,-1);
+ sfclose(outfile);
+ if(traceon && !(iop->iofile&IOSTRG))
+ sfputr(sfstderr,iop->ioname,'\n');
+ lseek(fd,(off_t)0,SEEK_SET);
+ shp->fdstatus[fd] = IOREAD;
+ return(fd);
+}
+
+/*
+ * This write discipline also writes the output on standard error
+ * This is used when tracing here-documents
+ */
+static ssize_t tee_write(Sfio_t *iop,const void *buff,size_t n,Sfdisc_t *unused)
+{
+ NOT_USED(unused);
+ sfwrite(sfstderr,buff,n);
+ return(write(sffileno(iop),buff,n));
+}
+
+/*
+ * copy file <origfd> into a save place
+ * The saved file is set close-on-exec
+ * if <origfd> < 0, then -origfd is saved, but not duped so that it
+ * will be closed with sh_iorestore.
+ */
+void sh_iosave(Shell_t *shp, register int origfd, int oldtop, char *name)
+{
+ register int savefd;
+ int flag = (oldtop&IOSUBSHELL);
+ oldtop &= ~IOSUBSHELL;
+ /* see if already saved, only save once */
+ for(savefd=shp->topfd; --savefd>=oldtop; )
+ {
+ if(filemap[savefd].orig_fd == origfd)
+ return;
+ }
+ /* make sure table is large enough */
+ if(shp->topfd >= filemapsize)
+ {
+ char *cp, *oldptr = (char*)filemap;
+ char *oldend = (char*)&filemap[filemapsize];
+ long moved;
+ filemapsize += 8;
+ if(!(filemap = (struct fdsave*)realloc(filemap,filemapsize*sizeof(struct fdsave))))
+ errormsg(SH_DICT,ERROR_exit(4),e_nospace);
+ if(moved = (char*)filemap - oldptr)
+ {
+ for(savefd=shp->gd->lim.open_max; --savefd>=0; )
+ {
+ cp = (char*)shp->fdptrs[savefd];
+ if(cp >= oldptr && cp < oldend)
+ shp->fdptrs[savefd] = (int*)(cp+moved);
+ }
+ }
+ }
+#if SHOPT_DEVFD
+ if(origfd <0)
+ {
+ savefd = origfd;
+ origfd = -origfd;
+ }
+ else
+#endif /* SHOPT_DEVFD */
+ {
+ if((savefd = sh_fcntl(origfd, F_DUPFD, 10)) < 0 && errno!=EBADF)
+ {
+ shp->toomany=1;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ }
+ }
+ filemap[shp->topfd].tname = name;
+ filemap[shp->topfd].subshell = flag;
+ filemap[shp->topfd].orig_fd = origfd;
+ filemap[shp->topfd++].save_fd = savefd;
+ if(savefd >=0)
+ {
+ register Sfio_t* sp = shp->sftable[origfd];
+ /* make saved file close-on-exec */
+ sh_fcntl(savefd,F_SETFD,FD_CLOEXEC);
+ if(origfd==job.fd)
+ job.fd = savefd;
+ shp->fdstatus[savefd] = shp->fdstatus[origfd];
+ shp->fdptrs[savefd] = &filemap[shp->topfd-1].save_fd;
+ if(!(shp->sftable[savefd]=sp))
+ return;
+ sfsync(sp);
+ if(origfd <=2)
+ {
+ /* copy standard stream to new stream */
+ sp = sfswap(sp,NIL(Sfio_t*));
+ shp->sftable[savefd] = sp;
+ }
+ else
+ shp->sftable[origfd] = 0;
+ }
+}
+
+/*
+ * close all saved file descriptors
+ */
+void sh_iounsave(Shell_t* shp)
+{
+ register int fd, savefd, newfd;
+ for(newfd=fd=0; fd < shp->topfd; fd++)
+ {
+ if((savefd = filemap[fd].save_fd)< 0)
+ filemap[newfd++] = filemap[fd];
+ else
+ {
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ }
+ }
+ shp->topfd = newfd;
+}
+
+/*
+ * restore saved file descriptors from <last> on
+ */
+void sh_iorestore(Shell_t *shp, int last, int jmpval)
+{
+ register int origfd, savefd, fd;
+ int flag = (last&IOSUBSHELL);
+ last &= ~IOSUBSHELL;
+ for (fd = shp->topfd - 1; fd >= last; fd--)
+ {
+ if(!flag && filemap[fd].subshell)
+ continue;
+ if(jmpval==SH_JMPSCRIPT)
+ {
+ if ((savefd = filemap[fd].save_fd) >= 0)
+ {
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ }
+ continue;
+ }
+ origfd = filemap[fd].orig_fd;
+ if(origfd<0)
+ {
+ /* this should never happen */
+ savefd = filemap[fd].save_fd;
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ return;
+ }
+ if(filemap[fd].tname == Empty && shp->exitval==0)
+ ftruncate(origfd,lseek(origfd,0,SEEK_CUR));
+ else if(filemap[fd].tname)
+ io_usename(filemap[fd].tname,(int*)0,origfd,shp->exitval?2:1);
+ sh_close(origfd);
+ if ((savefd = filemap[fd].save_fd) >= 0)
+ {
+ sh_fcntl(savefd, F_DUPFD, origfd);
+ if(savefd==job.fd)
+ job.fd=origfd;
+ shp->fdstatus[origfd] = shp->fdstatus[savefd];
+ /* turn off close-on-exec if flag if necessary */
+ if(shp->fdstatus[origfd]&IOCLEX)
+ fcntl(origfd,F_SETFD,FD_CLOEXEC);
+ if(origfd<=2)
+ {
+ sfswap(shp->sftable[savefd],shp->sftable[origfd]);
+ if(origfd==0)
+ shp->st.ioset = 0;
+ }
+ else
+ shp->sftable[origfd] = shp->sftable[savefd];
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ }
+ else
+ shp->fdstatus[origfd] = IOCLOSE;
+ }
+ if(!flag)
+ {
+ /* keep file descriptors for subshell restore */
+ for (fd = last ; fd < shp->topfd; fd++)
+ {
+ if(filemap[fd].subshell)
+ filemap[last++] = filemap[fd];
+ }
+ }
+ if(last < shp->topfd)
+ shp->topfd = last;
+}
+
+/*
+ * returns access information on open file <fd>
+ * returns -1 for failure, 0 for success
+ * <mode> is the same as for access()
+ */
+int sh_ioaccess(int fd,register int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ register int flags;
+ if(mode==X_OK)
+ return(-1);
+ if((flags=sh_iocheckfd(shp,fd))!=IOCLOSE)
+ {
+ if(mode==F_OK)
+ return(0);
+ if(mode==R_OK && (flags&IOREAD))
+ return(0);
+ if(mode==W_OK && (flags&IOWRITE))
+ return(0);
+ }
+ return(-1);
+}
+
+/*
+ * Handle interrupts for slow streams
+ */
+static int slowexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ register int n,fno;
+ NOT_USED(handle);
+ if(type==SF_DPOP || type==SF_FINAL)
+ free((void*)handle);
+ if(type==SF_WRITE && errno==EPIPE)
+ {
+ sfpurge(iop);
+ return(-1);
+ }
+ if(type!=SF_READ)
+ return(0);
+ if((shp->trapnote&(SH_SIGSET|SH_SIGTRAP)) && errno!=EIO && errno!=ENXIO)
+ errno = EINTR;
+ fno = sffileno(iop);
+ if((n=sfvalue(iop))<=0)
+ {
+#ifndef FNDELAY
+# ifdef O_NDELAY
+ if(errno==0 && (n=fcntl(fno,F_GETFL,0))&O_NDELAY)
+ {
+ n &= ~O_NDELAY;
+ fcntl(fno, F_SETFL, n);
+ return(1);
+ }
+# endif /* O_NDELAY */
+#endif /* !FNDELAY */
+#ifdef O_NONBLOCK
+ if(errno==EAGAIN)
+ {
+ n = fcntl(fno,F_GETFL,0);
+ n &= ~O_NONBLOCK;
+ fcntl(fno, F_SETFL, n);
+ return(1);
+ }
+#endif /* O_NONBLOCK */
+ if(errno!=EINTR)
+ return(0);
+ else if(shp->bltinfun && (shp->trapnote&SH_SIGTRAP) && shp->lastsig)
+ return(-1);
+ n=1;
+ sh_onstate(SH_TTYWAIT);
+ }
+ else
+ n = 0;
+ if(shp->bltinfun && shp->bltindata.sigset)
+ return(-1);
+ errno = 0;
+ if(shp->trapnote&SH_SIGSET)
+ {
+ if(isatty(fno))
+ sfputc(sfstderr,'\n');
+ sh_exit(SH_EXITSIG);
+ }
+ if(shp->trapnote&SH_SIGTRAP)
+ sh_chktrap(shp);
+ return(n);
+}
+
+/*
+ * called when slowread times out
+ */
+static void time_grace(void *handle)
+{
+ Shell_t *shp = (Shell_t*)handle;
+ timeout = 0;
+ if(sh_isstate(SH_GRACE))
+ {
+ sh_offstate(SH_GRACE);
+ if(!sh_isstate(SH_INTERACTIVE))
+ return;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
+ errormsg(SH_DICT,2,e_timeout);
+ shp->trapnote |= SH_SIGSET;
+ return;
+ }
+ errormsg(SH_DICT,0,e_timewarn);
+ sh_onstate(SH_GRACE);
+ sigrelease(SIGALRM);
+ shp->trapnote |= SH_SIGTRAP;
+}
+
+static ssize_t piperead(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ int fd = sffileno(iop);
+ if(job.waitsafe && job.savesig)
+ {
+ job_lock();
+ job_unlock();
+ }
+ if(shp->trapnote)
+ {
+ errno = EINTR;
+ return(-1);
+ }
+ if(sh_isstate(SH_INTERACTIVE) && sffileno(iop)==0 && io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
+ return(0);
+ sh_onstate(SH_TTYWAIT);
+ if(!(shp->fdstatus[fd]&IOCLEX) && (sfset(iop,0,0)&SF_SHARE))
+ size = ed_read(shgd->ed_context, fd, (char*)buff, size,0);
+ else
+ size = sfrd(iop,buff,size,handle);
+ sh_offstate(SH_TTYWAIT);
+ return(size);
+}
+/*
+ * This is the read discipline that is applied to slow devices
+ * This routine takes care of prompting for input
+ */
+static ssize_t slowread(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ int (*readf)(void*, int, char*, int, int);
+ int reedit=0, rsize;
+#if SHOPT_HISTEXPAND
+ char *xp=0;
+#endif
+# if SHOPT_ESH
+ if(sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS))
+ readf = ed_emacsread;
+ else
+# endif /* SHOPT_ESH */
+# if SHOPT_VSH
+# if SHOPT_RAWONLY
+ if(sh_isoption(SH_VI) || ((SHOPT_RAWONLY-0) && mbwide()))
+# else
+ if(sh_isoption(SH_VI))
+# endif
+ readf = ed_viread;
+ else
+# endif /* SHOPT_VSH */
+ readf = ed_read;
+ if(shp->trapnote)
+ {
+ errno = EINTR;
+ return(-1);
+ }
+ while(1)
+ {
+ if(io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
+ return(0);
+ if(shp->timeout)
+ timeout = (void*)sh_timeradd(sh_isstate(SH_GRACE)?1000L*TGRACE:1000L*shp->timeout,0,time_grace,shp);
+ rsize = (*readf)(shgd->ed_context, sffileno(iop), (char*)buff, size, reedit);
+ if(timeout)
+ timerdel(timeout);
+ timeout=0;
+#if SHOPT_HISTEXPAND
+ if(rsize && *(char*)buff != '\n' && shp->nextprompt==1 && sh_isoption(SH_HISTEXPAND))
+ {
+ int r;
+ ((char*)buff)[rsize] = '\0';
+ if(xp)
+ {
+ free(xp);
+ xp = 0;
+ }
+ r = hist_expand(buff, &xp);
+ if((r & (HIST_EVENT|HIST_PRINT)) && !(r & HIST_ERROR) && xp)
+ {
+ strlcpy(buff, xp, size);
+ rsize = strlen(buff);
+ if(!sh_isoption(SH_HISTVERIFY) || readf==ed_read)
+ {
+ sfputr(sfstderr, xp, -1);
+ break;
+ }
+ reedit = rsize - 1;
+ continue;
+ }
+ if((r & HIST_ERROR) && sh_isoption(SH_HISTREEDIT))
+ {
+ reedit = rsize - 1;
+ continue;
+ }
+ if(r & (HIST_ERROR|HIST_PRINT))
+ {
+ *(char*)buff = '\n';
+ rsize = 1;
+ }
+ }
+#endif
+ break;
+ }
+ return(rsize);
+}
+
+/*
+ * check and return the attributes for a file descriptor
+ */
+
+int sh_iocheckfd(Shell_t *shp, register int fd)
+{
+ register int flags, n;
+ if((n=shp->fdstatus[fd])&IOCLOSE)
+ return(n);
+ if(!(n&(IOREAD|IOWRITE)))
+ {
+#ifdef F_GETFL
+ if((flags=fcntl(fd,F_GETFL,0)) < 0)
+ return(shp->fdstatus[fd]=IOCLOSE);
+ if((flags&O_ACCMODE)!=O_WRONLY)
+ n |= IOREAD;
+ if((flags&O_ACCMODE)!=O_RDONLY)
+ n |= IOWRITE;
+#else
+ struct stat statb;
+ if((flags = fstat(fd,&statb))< 0)
+ return(shp->fdstatus[fd]=IOCLOSE);
+ n |= (IOREAD|IOWRITE);
+ if(read(fd,"",0) < 0)
+ n &= ~IOREAD;
+#endif /* F_GETFL */
+ }
+ if(!(n&(IOSEEK|IONOSEEK)))
+ {
+ struct stat statb;
+ /* /dev/null check is a workaround for select bug */
+ static ino_t null_ino;
+ static dev_t null_dev;
+ if(null_ino==0 && stat(e_devnull,&statb) >=0)
+ {
+ null_ino = statb.st_ino;
+ null_dev = statb.st_dev;
+ }
+ if(tty_check(fd))
+ n |= IOTTY;
+ if(lseek(fd,NIL(off_t),SEEK_CUR)<0)
+ {
+ n |= IONOSEEK;
+#ifdef S_ISSOCK
+ if((fstat(fd,&statb)>=0) && S_ISSOCK(statb.st_mode))
+ {
+ n |= IOREAD|IOWRITE;
+# if _socketpair_shutdown_mode
+ if(!(statb.st_mode&S_IRUSR))
+ n &= ~IOREAD;
+ else if(!(statb.st_mode&S_IWUSR))
+ n &= ~IOWRITE;
+# endif
+ }
+#endif /* S_ISSOCK */
+ }
+ else if((fstat(fd,&statb)>=0) && (
+ S_ISFIFO(statb.st_mode) ||
+#ifdef S_ISSOCK
+ S_ISSOCK(statb.st_mode) ||
+#endif /* S_ISSOCK */
+ /* The following is for sockets on the sgi */
+ (statb.st_ino==0 && (statb.st_mode & ~(S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH|S_IXUSR|S_IXGRP|S_IXOTH|S_ISUID|S_ISGID))==0) ||
+ (S_ISCHR(statb.st_mode) && (statb.st_ino!=null_ino || statb.st_dev!=null_dev))
+ ))
+ n |= IONOSEEK;
+ else
+ n |= IOSEEK;
+ }
+ if(fd==0)
+ n &= ~IOWRITE;
+ else if(fd==1)
+ n &= ~IOREAD;
+ shp->fdstatus[fd] = n;
+ return(n);
+}
+
+/*
+ * Display prompt PS<flag> on standard error
+ */
+
+static int io_prompt(Shell_t *shp,Sfio_t *iop,register int flag)
+{
+ register char *cp;
+ char buff[1];
+ char *endprompt;
+ static short cmdno;
+ int sfflags;
+ if(flag<3 && !sh_isstate(SH_INTERACTIVE))
+ flag = 0;
+ if(flag==2 && sfpkrd(sffileno(iop),buff,1,'\n',0,1) >= 0)
+ flag = 0;
+ if(flag==0)
+ return(sfsync(sfstderr));
+ sfflags = sfset(sfstderr,SF_SHARE|SF_PUBLIC|SF_READ,0);
+ if(!(shp->prompt=(char*)sfreserve(sfstderr,0,0)))
+ shp->prompt = "";
+ switch(flag)
+ {
+ case 1:
+ {
+ register int c;
+#if defined(TIOCLBIC) && defined(LFLUSHO)
+ if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
+ {
+ /*
+ * re-enable output in case the user has
+ * disabled it. Not needed with edit mode
+ */
+ int mode = LFLUSHO;
+ ioctl(sffileno(sfstderr),TIOCLBIC,&mode);
+ }
+#endif /* TIOCLBIC */
+ cp = sh_mactry(shp,nv_getval(sh_scoped(shp,PS1NOD)));
+ for(;c= *cp;cp++)
+ {
+ if(c==HIST_CHAR)
+ {
+ /* look at next character */
+ c = *++cp;
+ /* print out line number if not !! */
+ if(c!= HIST_CHAR)
+ {
+ sfprintf(sfstderr,"%d", shp->gd->hist_ptr?(int)shp->gd->hist_ptr->histind:++cmdno);
+ }
+ if(c==0)
+ goto done;
+ }
+ sfputc(sfstderr,c);
+ }
+ goto done;
+ }
+ case 2:
+ cp = nv_getval(sh_scoped(shp,PS2NOD));
+ break;
+ case 3:
+ cp = nv_getval(sh_scoped(shp,PS3NOD));
+ break;
+ default:
+ goto done;
+ }
+ if(cp)
+ sfputr(sfstderr,cp,-1);
+done:
+ if(*shp->prompt && (endprompt=(char*)sfreserve(sfstderr,0,0)))
+ *endprompt = 0;
+ sfset(sfstderr,sfflags&SF_READ|SF_SHARE|SF_PUBLIC,1);
+ return(sfsync(sfstderr));
+}
+
+/*
+ * This discipline is inserted on write pipes to prevent SIGPIPE
+ * from causing an infinite loop
+ */
+static int pipeexcept(Sfio_t* iop, int mode, void *data, Sfdisc_t* handle)
+{
+ if(mode==SF_DPOP || mode==SF_FINAL)
+ free((void*)handle);
+ else if(mode==SF_WRITE && errno==EPIPE)
+ {
+ sfpurge(iop);
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ * keep track of each stream that is opened and closed
+ */
+static void sftrack(Sfio_t* sp, int flag, void* data)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fd = sffileno(sp);
+ register struct checkpt *pp;
+ register int mode;
+ int newfd = integralof(data);
+ if(flag==SF_SETFD || flag==SF_CLOSING)
+ {
+ if(newfd<0)
+ flag = SF_CLOSING;
+ if(fdnotify)
+ (*fdnotify)(sffileno(sp),flag==SF_CLOSING?-1:newfd);
+ }
+#ifdef DEBUG
+ if(flag==SF_READ || flag==SF_WRITE)
+ {
+ char *z = fmtbase((long)getpid(),0,0);
+ write(ERRIO,z,strlen(z));
+ write(ERRIO,": ",2);
+ write(ERRIO,"attempt to ",11);
+ if(flag==SF_READ)
+ write(ERRIO,"read from",9);
+ else
+ write(ERRIO,"write to",8);
+ write(ERRIO," locked stream\n",15);
+ return;
+ }
+#endif
+ if(fd<0 || fd==PSEUDOFD || (fd>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fd)))
+ return;
+ if(sh_isstate(SH_NOTRACK))
+ return;
+ mode = sfset(sp,0,0);
+ if(sp==shp->heredocs && fd < 10 && flag==SF_NEW)
+ {
+ fd = sfsetfd(sp,10);
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ }
+ if(fd < 3)
+ return;
+ if(flag==SF_NEW)
+ {
+ if(!shp->sftable[fd] && shp->fdstatus[fd]==IOCLOSE)
+ {
+ shp->sftable[fd] = sp;
+ flag = (mode&SF_WRITE)?IOWRITE:0;
+ if(mode&SF_READ)
+ flag |= IOREAD;
+ shp->fdstatus[fd] = flag;
+ sh_iostream(shp,fd);
+ }
+ if((pp=(struct checkpt*)shp->jmplist) && pp->mode==SH_JMPCMD)
+ {
+ struct openlist *item;
+ /*
+ * record open file descriptors so they can
+ * be closed in case a longjmp prevents
+ * built-ins from cleanup
+ */
+ item = new_of(struct openlist, 0);
+ item->strm = sp;
+ item->next = pp->olist;
+ pp->olist = item;
+ }
+ if(fdnotify)
+ (*fdnotify)(-1,sffileno(sp));
+ }
+ else if(flag==SF_CLOSING || (flag==SF_SETFD && newfd<=2))
+ {
+ shp->sftable[fd] = 0;
+ shp->fdstatus[fd]=IOCLOSE;
+ if(pp=(struct checkpt*)shp->jmplist)
+ {
+ struct openlist *item;
+ for(item=pp->olist; item; item=item->next)
+ {
+ if(item->strm == sp)
+ {
+ item->strm = 0;
+ break;
+ }
+ }
+ }
+ }
+}
+
+struct eval
+{
+ Sfdisc_t disc;
+ char **argv;
+ short slen;
+ char addspace;
+};
+
+/*
+ * Create a stream consisting of a space separated argv[] list
+ */
+
+Sfio_t *sh_sfeval(register char *argv[])
+{
+ register Sfio_t *iop;
+ register char *cp;
+ if(argv[1])
+ cp = "";
+ else
+ cp = argv[0];
+ iop = sfopen(NIL(Sfio_t*),(char*)cp,"s");
+ if(argv[1])
+ {
+ register struct eval *ep;
+ if(!(ep = new_of(struct eval,0)))
+ return(NIL(Sfio_t*));
+ ep->disc = eval_disc;
+ ep->argv = argv;
+ ep->slen = -1;
+ ep->addspace = 0;
+ sfdisc(iop,&ep->disc);
+ }
+ return(iop);
+}
+
+/*
+ * This code gets called whenever an end of string is found with eval
+ */
+
+static int eval_exceptf(Sfio_t *iop,int type, void *data, Sfdisc_t *handle)
+{
+ register struct eval *ep = (struct eval*)handle;
+ register char *cp;
+ register int len;
+
+ /* no more to do */
+ if(type!=SF_READ || !(cp = ep->argv[0]))
+ {
+ if(type==SF_CLOSING)
+ sfdisc(iop,SF_POPDISC);
+ else if(ep && (type==SF_DPOP || type==SF_FINAL))
+ free((void*)ep);
+ return(0);
+ }
+
+ if(!ep->addspace)
+ {
+ /* get the length of this string */
+ ep->slen = len = strlen(cp);
+ /* move to next string */
+ ep->argv++;
+ }
+ else /* insert space between arguments */
+ {
+ len = 1;
+ cp = " ";
+ }
+ /* insert the new string */
+ sfsetbuf(iop,cp,len);
+ ep->addspace = !ep->addspace;
+ return(1);
+}
+
+/*
+ * This routine returns a stream pointer to a segment of length <size> from
+ * the stream <sp> starting at offset <offset>
+ * The stream can be read with the normal stream operations
+ */
+
+static Sfio_t *subopen(Shell_t *shp,Sfio_t* sp, off_t offset, long size)
+{
+ register struct subfile *disp;
+ if(sfseek(sp,offset,SEEK_SET) <0)
+ return(NIL(Sfio_t*));
+ if(!(disp = (struct subfile*)malloc(sizeof(struct subfile)+IOBSIZE+1)))
+ return(NIL(Sfio_t*));
+ disp->disc = sub_disc;
+ disp->oldsp = sp;
+ disp->offset = offset;
+ disp->size = disp->left = size;
+ sp = sfnew(NIL(Sfio_t*),(char*)(disp+1),IOBSIZE,PSEUDOFD,SF_READ);
+ sfdisc(sp,&disp->disc);
+ return(sp);
+}
+
+/*
+ * read function for subfile discipline
+ */
+static ssize_t subread(Sfio_t* sp,void* buff,register size_t size,Sfdisc_t* handle)
+{
+ register struct subfile *disp = (struct subfile*)handle;
+ ssize_t n;
+ NOT_USED(sp);
+ sfseek(disp->oldsp,disp->offset,SEEK_SET);
+ if(disp->left == 0)
+ return(0);
+ if(size > disp->left)
+ size = disp->left;
+ disp->left -= size;
+ n = sfread(disp->oldsp,buff,size);
+ if(size>0)
+ disp->offset += size;
+ return(n);
+}
+
+/*
+ * exception handler for subfile discipline
+ */
+static int subexcept(Sfio_t* sp,register int mode, void *data, Sfdisc_t* handle)
+{
+ register struct subfile *disp = (struct subfile*)handle;
+ if(mode==SF_CLOSING)
+ {
+ sfdisc(sp,SF_POPDISC);
+ return(0);
+ }
+ else if(disp && (mode==SF_DPOP || mode==SF_FINAL))
+ {
+ free((void*)disp);
+ return(0);
+ }
+#ifdef SF_ATEXIT
+ else if (mode==SF_ATEXIT)
+ {
+ sfdisc(sp, SF_POPDISC);
+ return(0);
+ }
+#endif
+ else if(mode==SF_READ)
+ return(0);
+ return(-1);
+}
+
+#define NROW 15 /* number of rows before going to multi-columns */
+#define LBLSIZ 3 /* size of label field and interfield spacing */
+/*
+ * print a list of arguments in columns
+ */
+void sh_menu(Sfio_t *outfile,int argn,char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ register int i,j;
+ register char **arg;
+ int nrow, ncol=1, ndigits=1;
+ int fldsize, wsize = ed_window();
+ char *cp = nv_getval(sh_scoped(shp,LINES));
+ nrow = (cp?1+2*((int)strtol(cp, (char**)0, 10)/3):NROW);
+ for(i=argn;i >= 10;i /= 10)
+ ndigits++;
+ if(argn < nrow)
+ {
+ nrow = argn;
+ goto skip;
+ }
+ i = 0;
+ for(arg=argv; *arg;arg++)
+ {
+ if((j=strlen(*arg)) > i)
+ i = j;
+ }
+ i += (ndigits+LBLSIZ);
+ if(i < wsize)
+ ncol = wsize/i;
+ if(argn > nrow*ncol)
+ {
+ nrow = 1 + (argn-1)/ncol;
+ }
+ else
+ {
+ ncol = 1 + (argn-1)/nrow;
+ nrow = 1 + (argn-1)/ncol;
+ }
+skip:
+ fldsize = (wsize/ncol)-(ndigits+LBLSIZ);
+ for(i=0;i<nrow;i++)
+ {
+ if(shp->trapnote&SH_SIGSET)
+ return;
+ j = i;
+ while(1)
+ {
+ arg = argv+j;
+ sfprintf(outfile,"%*d) %s",ndigits,j+1,*arg);
+ j += nrow;
+ if(j >= argn)
+ break;
+ sfnputc(outfile,' ',fldsize-strlen(*arg));
+ }
+ sfputc(outfile,'\n');
+ }
+}
+
+#undef read
+/*
+ * shell version of read() for user added builtins
+ */
+ssize_t sh_read(register int fd, void* buff, size_t n)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ if(sp=shp->sftable[fd])
+ return(sfread(sp,buff,n));
+ else
+ return(read(fd,buff,n));
+}
+
+#undef write
+/*
+ * shell version of write() for user added builtins
+ */
+ssize_t sh_write(register int fd, const void* buff, size_t n)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ if(sp=shp->sftable[fd])
+ return(sfwrite(sp,buff,n));
+ else
+ return(write(fd,buff,n));
+}
+
+#undef lseek
+/*
+ * shell version of lseek() for user added builtins
+ */
+off_t sh_seek(register int fd, off_t offset, int whence)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ if((sp=shp->sftable[fd]) && (sfset(sp,0,0)&(SF_READ|SF_WRITE)))
+ return(sfseek(sp,offset,whence));
+ else
+ return(lseek(fd,offset,whence));
+}
+
+#undef dup
+int sh_dup(register int old)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fd = dup(old);
+ if(fd>=0)
+ {
+ if(shp->fdstatus[old] == IOCLOSE)
+ shp->fdstatus[old] = 0;
+ shp->fdstatus[fd] = (shp->fdstatus[old]&~IOCLEX);
+ if(fdnotify)
+ (*fdnotify)(old,fd);
+ }
+ return(fd);
+}
+
+#undef fcntl
+int sh_fcntl(register int fd, int op, ...)
+{
+ Shell_t *shp = sh_getinterp();
+ int newfd, arg;
+ va_list ap;
+ va_start(ap, op);
+ arg = va_arg(ap, int) ;
+ va_end(ap);
+ newfd = fcntl(fd,op,arg);
+ if(newfd>=0) switch(op)
+ {
+ case F_DUPFD:
+ if(shp->fdstatus[fd] == IOCLOSE)
+ shp->fdstatus[fd] = 0;
+ if(newfd>=shp->gd->lim.open_max)
+ sh_iovalidfd(shp,newfd);
+ shp->fdstatus[newfd] = (shp->fdstatus[fd]&~IOCLEX);
+ if(fdnotify)
+ (*fdnotify)(fd,newfd);
+ break;
+ case F_SETFD:
+ if(shp->fdstatus[fd] == IOCLOSE)
+ shp->fdstatus[fd] = 0;
+ if(arg&FD_CLOEXEC)
+ shp->fdstatus[fd] |= IOCLEX;
+ else
+ shp->fdstatus[fd] &= ~IOCLEX;
+ }
+ return(newfd);
+}
+
+#undef umask
+mode_t sh_umask(mode_t m)
+{
+ Shell_t *shp = sh_getinterp();
+ shp->mask = m;
+ return(umask(m));
+}
+
+/*
+ * give file descriptor <fd> and <mode>, return an iostream pointer
+ * <mode> must be SF_READ or SF_WRITE
+ * <fd> must be a non-negative number ofr SH_IOCOPROCESS or SH_IOHISTFILE.
+ * returns NULL on failure and may set errno.
+ */
+
+Sfio_t *sh_iogetiop(int fd, int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ int n;
+ Sfio_t *iop=0;
+ if(mode!=SF_READ && mode!=SF_WRITE)
+ {
+ errno = EINVAL;
+ return(iop);
+ }
+ switch(fd)
+ {
+ case SH_IOHISTFILE:
+ if(!sh_histinit((void*)shp))
+ return(iop);
+ fd = sffileno(shp->gd->hist_ptr->histfp);
+ break;
+ case SH_IOCOPROCESS:
+ if(mode==SF_WRITE)
+ fd = shp->coutpipe;
+ else
+ fd = shp->cpipe[0];
+ break;
+ default:
+ if(fd<0 || !sh_iovalidfd(shp,fd))
+ fd = -1;
+ }
+ if(fd<0)
+ {
+ errno = EBADF;
+ return(iop);
+ }
+ if(!(n=shp->fdstatus[fd]))
+ n = sh_iocheckfd(shp,fd);
+ if(mode==SF_WRITE && !(n&IOWRITE))
+ return(iop);
+ if(mode==SF_READ && !(n&IOREAD))
+ return(iop);
+ if(!(iop = shp->sftable[fd]))
+ iop=sh_iostream(shp,fd);
+ return(iop);
+}
+
+typedef int (*Notify_f)(int,int);
+
+Notify_f sh_fdnotify(Notify_f notify)
+{
+ Notify_f old;
+ old = fdnotify;
+ fdnotify = notify;
+ return(old);
+}
+
+Sfio_t *sh_fd2sfio(int fd)
+{
+ Shell_t *shp = sh_getinterp();
+ register int status;
+ Sfio_t *sp = shp->sftable[fd];
+ if(!sp && (status = sh_iocheckfd(shp,fd))!=IOCLOSE)
+ {
+ register int flags=0;
+ if(status&IOREAD)
+ flags |= SF_READ;
+ if(status&IOWRITE)
+ flags |= SF_WRITE;
+ sp = sfnew(NULL, NULL, -1, fd,flags);
+ shp->sftable[fd] = sp;
+ }
+ return(sp);
+}
+
+Sfio_t *sh_pathopen(const char *cp)
+{
+ Shell_t *shp = sh_getinterp();
+ int n;
+#ifdef PATH_BFPATH
+ if((n=path_open(shp,cp,path_get(shp,cp))) < 0)
+ n = path_open(shp,cp,(Pathcomp_t*)0);
+#else
+ if((n=path_open(shp,cp,path_get(cp))) < 0)
+ n = path_open(shp,cp,"");
+#endif
+ if(n < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,cp);
+ return(sh_iostream(shp,n));
+}
+
+int sh_isdevfd(register const char *fd)
+{
+ if(!fd || memcmp(fd,"/dev/fd/",8) || fd[8]==0)
+ return(0);
+ for ( fd=&fd[8] ; *fd != '\0' ; fd++ )
+ {
+ if (*fd < '0' || *fd > '9')
+ return(0);
+ }
+ return(1);
+}
diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c
new file mode 100644
index 0000000..5dca257
--- /dev/null
+++ b/src/cmd/ksh93/sh/jobs.c
@@ -0,0 +1,2055 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Job control for UNIX Shell
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ * Written October, 1982
+ * Rewritten April, 1988
+ * Revised January, 1992
+ */
+
+#include "defs.h"
+#include <wait.h>
+#include "io.h"
+#include "jobs.h"
+#include "history.h"
+
+#if !defined(WCONTINUED) || !defined(WIFCONTINUED)
+# undef WCONTINUED
+# define WCONTINUED 0
+# undef WIFCONTINUED
+# define WIFCONTINUED(wstat) (0)
+#endif
+
+#define NJOB_SAVELIST 4
+
+/*
+ * temporary hack to get W* macros to work
+ */
+#undef wait
+#define wait ______wait
+/*
+ * This struct saves a link list of processes that have non-zero exit
+ * status, have had $! saved, but haven't been waited for
+ */
+struct jobsave
+{
+ struct jobsave *next;
+ pid_t pid;
+ unsigned short exitval;
+};
+
+static struct jobsave *job_savelist;
+static int njob_savelist;
+static struct process *pwfg;
+static int jobfork;
+
+pid_t pid_fromstring(char *str)
+{
+ pid_t pid;
+ char *last;
+ errno = 0;
+ if(sizeof(pid)==sizeof(Sflong_t))
+ pid = (pid_t)strtoll(str, &last, 10);
+ else
+ pid = (pid_t)strtol(str, &last, 10);
+ if(errno==ERANGE || *last)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: invalid process id",str);
+ return(pid);
+}
+
+static void init_savelist(void)
+{
+ register struct jobsave *jp;
+ while(njob_savelist < NJOB_SAVELIST)
+ {
+ jp = newof(0,struct jobsave,1,0);
+ jp->next = job_savelist;
+ job_savelist = jp;
+ njob_savelist++;
+ }
+}
+
+struct back_save
+{
+ int count;
+ struct jobsave *list;
+ struct back_save *prev;
+};
+
+#define BYTE(n) (((n)+CHAR_BIT-1)/CHAR_BIT)
+#define MAXMSG 25
+#define SH_STOPSIG (SH_EXITSIG<<1)
+
+#ifdef VSUSP
+# ifndef CNSUSP
+# ifdef _POSIX_VDISABLE
+# define CNSUSP _POSIX_VDISABLE
+# else
+# define CNSUSP 0
+# endif /* _POSIX_VDISABLE */
+# endif /* CNSUSP */
+# ifndef CSWTCH
+# ifdef CSUSP
+# define CSWTCH CSUSP
+# else
+# define CSWTCH ('z'&037)
+# endif /* CSUSP */
+# endif /* CSWTCH */
+#endif /* VSUSP */
+
+/* Process states */
+#define P_EXITSAVE 01
+#define P_STOPPED 02
+#define P_NOTIFY 04
+#define P_SIGNALLED 010
+#define P_STTY 020
+#define P_DONE 040
+#define P_COREDUMP 0100
+#define P_DISOWN 0200
+#define P_FG 0400
+#ifdef SHOPT_BGX
+#define P_BG 01000
+#endif /* SHOPT_BGX */
+
+static int job_chksave(pid_t);
+static struct process *job_bypid(pid_t);
+static struct process *job_byjid(int);
+static char *job_sigmsg(int);
+static int job_alloc(void);
+static void job_free(int);
+static struct process *job_unpost(struct process*,int);
+static void job_unlink(struct process*);
+static void job_prmsg(struct process*);
+static struct process *freelist;
+static char beenhere;
+static char possible;
+static struct process dummy;
+static char by_number;
+static Sfio_t *outfile;
+static pid_t lastpid;
+static struct back_save bck;
+
+#ifdef JOBS
+ static void job_set(struct process*);
+ static void job_reset(struct process*);
+ static void job_waitsafe(int);
+ static struct process *job_byname(char*);
+ static struct process *job_bystring(char*);
+ static struct termios my_stty; /* terminal state for shell */
+ static char *job_string;
+#else
+ extern const char e_coredump[];
+#endif /* JOBS */
+
+#ifdef SIGTSTP
+ static void job_unstop(struct process*);
+ static void job_fgrp(struct process*, int);
+# ifndef _lib_tcgetpgrp
+# ifdef TIOCGPGRP
+ static int _i_;
+# define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
+# endif /* TIOCGPGRP */
+ int tcsetpgrp(int fd,pid_t pgrp)
+ {
+ int pgid = pgrp;
+# ifdef TIOCGPGRP
+ return(ioctl(fd, TIOCSPGRP, &pgid));
+# else
+ return(-1);
+# endif /* TIOCGPGRP */
+ }
+# endif /* _lib_tcgetpgrp */
+#else
+# define job_unstop(pw)
+# undef CNSUSP
+#endif /* SIGTSTP */
+
+#ifndef OTTYDISC
+# undef NTTYDISC
+#endif /* OTTYDISC */
+
+#ifdef JOBS
+
+typedef int (*Waitevent_f)(int,long,int);
+
+#ifdef SHOPT_BGX
+void job_chldtrap(Shell_t *shp, const char *trap, int unpost)
+{
+ register struct process *pw,*pwnext;
+ pid_t bckpid;
+ int oldexit,trapnote;
+ job_lock();
+ shp->sigflag[SIGCHLD] &= ~SH_SIGTRAP;
+ trapnote = shp->trapnote;
+ shp->trapnote = 0;
+ for(pw=job.pwlist;pw;pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ if((pw->p_flag&(P_BG|P_DONE)) != (P_BG|P_DONE))
+ continue;
+ pw->p_flag &= ~P_BG;
+ bckpid = shp->bckpid;
+ oldexit = shp->savexit;
+ shp->bckpid = pw->p_pid;
+ shp->savexit = pw->p_exit;
+ if(pw->p_flag&P_SIGNALLED)
+ shp->savexit |= SH_EXITSIG;
+ sh_trap(trap,0);
+ if(pw->p_pid==bckpid && unpost)
+ job_unpost(pw,0);
+ shp->savexit = oldexit;
+ shp->bckpid = bckpid;
+ }
+ shp->trapnote = trapnote;
+ job_unlock();
+}
+#endif /* SHOPT_BGX */
+
+/*
+ * return next on link list of jobsave free list
+ */
+static struct jobsave *jobsave_create(pid_t pid)
+{
+ register struct jobsave *jp = job_savelist;
+ job_chksave(pid);
+ if(++bck.count > shgd->lim.child_max)
+ job_chksave(0);
+ if(jp)
+ {
+ njob_savelist--;
+ job_savelist = jp->next;
+ }
+ else
+ jp = newof(0,struct jobsave,1,0);
+ if(jp)
+ {
+ jp->pid = pid;
+ jp->next = bck.list;
+ bck.list = jp;
+ jp->exitval = 0;
+ }
+ return(jp);
+}
+
+#if SHOPT_COSHELL
+ pid_t sh_copid(struct cosh *csp)
+ {
+ return(COPID_BIT|(csp->id<<16)|csp->cojob->id);
+ }
+
+
+ char *sh_pid2str(Shell_t *shp,pid_t pid)
+ {
+ struct cosh *csp=0;
+ if(pid&COPID_BIT)
+ {
+ int id = (pid>>16) &0x3f;
+ for(csp=job.colist; csp; csp = csp->next)
+ {
+ if(csp->id == id)
+ break;
+ }
+ }
+ if(csp)
+ sfprintf(shp->strbuf,"%s.%d%c",csp->name,pid&0xff,0);
+ else
+ sfprintf(shp->strbuf,"%d%c",pid,0);
+ return(sfstruse(shp->strbuf));
+ }
+
+ int job_cowalk(int (*fun)(struct process*,int),int arg,char *name)
+ {
+ Shell_t *shp = sh_getinterp();
+ struct cosh *csp;
+ struct process *pw,*pwnext;
+ pid_t val;
+ int n,r=0;
+ char *cp = strchr(name,'.');
+ if(!cp)
+ n = strlen(name);
+ else
+ n = cp-name;
+ for(csp=(struct cosh*)job.colist;csp;csp=csp->next)
+ {
+ if(memcmp(name,csp->name,n)==0 && csp->name[n]==0)
+ break;
+ }
+ if(!csp)
+ errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name);
+ if(cp)
+ {
+ n = pid_fromstring(cp+1);
+ val = (csp->id<<16)|n|COPID_BIT;
+ }
+ job_reap(SIGCHLD);
+ for(n=0,pw=job.pwlist; pw; pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ if((cp && val==pw->p_pid) || (pw->p_cojob && pw->p_cojob->local==(void*)csp))
+ {
+ if(fun)
+ {
+ if(pw->p_flag&P_DONE)
+ continue;
+ r |= (*fun)(pw,arg);
+ }
+ else
+ job_wait(-pw->p_pid);
+ n++;
+ }
+ }
+ if(!n)
+ shp->exitval = fun?1:ERROR_NOENT;
+ else if(fun)
+ shp->exitval = r;
+ return(r);
+ }
+
+#endif /* SHOPT_COSHELL */
+
+/*
+ * Reap one job
+ * When called with sig==0, it does a blocking wait
+ */
+int job_reap(register int sig)
+{
+ Shell_t *shp = sh_getinterp();
+ register pid_t pid;
+ register struct process *pw;
+ struct process *px;
+ register int flags;
+ struct jobsave *jp;
+ int nochild=0, oerrno, wstat;
+ Waitevent_f waitevent = shp->gd->waitevent;
+ static int wcontinued = WCONTINUED;
+#if SHOPT_COSHELL
+ Cojob_t *cjp;
+ int cojobs;
+ long cotimeout = sig?0:-1;
+ for(pw=job.pwlist;pw;pw=pw->p_nxtjob)
+ {
+ if(pw->p_cojob && !(pw->p_flag&P_DONE))
+ break;
+ }
+ cojobs = (pw!=0);
+ pid = 0;
+#endif /* SHOPT_COSHELL */
+ if (vmbusy())
+ {
+ errormsg(SH_DICT,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen");
+ if (getenv("_AST_KSH_VMBUSY_ABORT"))
+ abort();
+ }
+#ifdef DEBUG
+ if(sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__,getpid(),job.in_critical,sig) <=0)
+ write(2,"waitsafe\n",9);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ job.savesig = 0;
+ if(sig)
+ flags = WNOHANG|WUNTRACED|wcontinued;
+ else
+ flags = WUNTRACED|wcontinued;
+ shp->gd->waitevent = 0;
+ oerrno = errno;
+ while(1)
+ {
+ if(!(flags&WNOHANG) && !sh.intrap && job.pwlist)
+ {
+ sh_onstate(SH_TTYWAIT);
+ if(waitevent && (*waitevent)(-1,-1L,0))
+ flags |= WNOHANG;
+ }
+#if SHOPT_COSHELL
+ if(cojobs)
+ {
+ if(cjp = cowait(0,0,cotimeout))
+ {
+ struct cosh *csp;
+ csp = (struct cosh*)(cjp->coshell->data);
+ csp->cojob = cjp;
+ pid = sh_copid(csp);
+ if(cjp->status < 256)
+ wstat = cjp->status <<8;
+ else
+ wstat = cjp->status-256;
+ cotimeout = 0;
+ goto cojob;
+ }
+ else if(copending(0)==0)
+ cojobs = 0;
+ cotimeout = 0;
+ }
+#endif /* SHOPT_COSHELL */
+ pid = waitpid((pid_t)-1,&wstat,flags);
+ sh_offstate(SH_TTYWAIT);
+#if SHOPT_COSHELL
+ cojob:
+#endif /* SHOPT_COSHELL */
+
+ /*
+ * some systems (linux 2.6) may return EINVAL
+ * when there are no continued children
+ */
+
+ if (pid<0 && errno==EINVAL && (flags&WCONTINUED))
+ pid = waitpid((pid_t)-1,&wstat,flags&=~WCONTINUED);
+ sh_sigcheck(shp);
+ if(pid<0 && errno==EINTR && (sig||job.savesig))
+ {
+ errno = 0;
+ continue;
+ }
+ if(pid<=0)
+ break;
+ if(wstat==0)
+ job_chksave(pid);
+ flags |= WNOHANG;
+ job.waitsafe++;
+ jp = 0;
+ lastpid = pid;
+ if(!(pw=job_bypid(pid)))
+ {
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d unknown job pid=%d pw=%x\n",__LINE__,getpid(),job.in_critical,pid,pw);
+#endif /* DEBUG */
+ if (WIFCONTINUED(wstat) && wcontinued)
+ continue;
+ pw = &dummy;
+ pw->p_exit = 0;
+ pw->p_pgrp = 0;
+ pw->p_exitmin = 0;
+ if(job.toclear)
+ job_clear();
+ jp = jobsave_create(pid);
+ pw->p_flag = 0;
+ lastpid = pw->p_pid = pid;
+ px = 0;
+ if(jp && WIFSTOPPED(wstat))
+ {
+ jp->exitval = SH_STOPSIG;
+ continue;
+ }
+ }
+#ifdef SIGTSTP
+ else
+ px=job_byjid(pw->p_job);
+ if (WIFCONTINUED(wstat) && wcontinued)
+ pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED);
+ else if(WIFSTOPPED(wstat))
+ {
+ pw->p_flag |= (P_NOTIFY|P_SIGNALLED|P_STOPPED);
+ pw->p_exit = WSTOPSIG(wstat);
+ if(pw->p_pgrp && pw->p_pgrp==job.curpgid && sh_isstate(SH_STOPOK))
+ sh_fault(pw->p_exit);
+ if(px)
+ {
+ /* move to top of job list */
+ job_unlink(px);
+ px->p_nxtjob = job.pwlist;
+ job.pwlist = px;
+ }
+ continue;
+ }
+ else
+#endif /* SIGTSTP */
+ {
+ /* check for coprocess completion */
+ if(pid==shp->cpid)
+ {
+ sh_close(sh.coutpipe);
+ sh_close(sh.cpipe[1]);
+ sh.cpipe[1] = -1;
+ sh.coutpipe = -1;
+ }
+ else if(shp->subshell)
+ sh_subjobcheck(pid);
+
+ pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
+ if (WIFSIGNALED(wstat))
+ {
+ pw->p_flag |= (P_DONE|P_NOTIFY|P_SIGNALLED);
+ if (WTERMCORE(wstat))
+ pw->p_flag |= P_COREDUMP;
+ pw->p_exit = WTERMSIG(wstat);
+ /* if process in current jobs terminates from
+ * an interrupt, propogate to parent shell
+ */
+ if(pw->p_pgrp && pw->p_pgrp==job.curpgid && pw->p_exit==SIGINT && sh_isstate(SH_STOPOK))
+ {
+ pw->p_flag &= ~P_NOTIFY;
+ sh_offstate(SH_STOPOK);
+ sh_fault(SIGINT);
+ sh_onstate(SH_STOPOK);
+ }
+ }
+ else
+ {
+ pw->p_flag |= (P_DONE|P_NOTIFY);
+ pw->p_exit = pw->p_exitmin;
+ if(WEXITSTATUS(wstat) > pw->p_exitmin)
+ pw->p_exit = WEXITSTATUS(wstat);
+ }
+#ifdef SHOPT_BGX
+ if((pw->p_flag&P_DONE) && (pw->p_flag&P_BG))
+ {
+ job.numbjob--;
+ if(shp->st.trapcom[SIGCHLD])
+ {
+ shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
+ if(sig==0)
+ job_chldtrap(shp,shp->st.trapcom[SIGCHLD],0);
+ else
+ shp->trapnote |= SH_SIGTRAP;
+ }
+ else
+ pw->p_flag &= ~P_BG;
+ }
+#endif /* SHOPT_BGX */
+ if(pw->p_pgrp==0)
+ pw->p_flag &= ~P_NOTIFY;
+ }
+ if(jp && pw== &dummy)
+ {
+ jp->exitval = pw->p_exit;
+ if(pw->p_flag&P_SIGNALLED)
+ jp->exitval |= SH_EXITSIG;
+ }
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d job %d with pid %d flags=%o complete with status=%x exit=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,pid,pw->p_flag,wstat,pw->p_exit);
+ sfsync(sfstderr);
+#endif /* DEBUG*/
+ /* only top-level process in job should have notify set */
+ if(px && pw != px)
+ pw->p_flag &= ~P_NOTIFY;
+ if(pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY))
+ {
+ px = job_byjid((int)pw->p_job);
+ for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc);
+ if(!px)
+ tcsetpgrp(JOBTTY,job.mypid);
+ }
+#ifndef SHOPT_BGX
+ if(!shp->intrap && shp->st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid)))
+ {
+ shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
+ shp->trapnote |= SH_SIGTRAP;
+ }
+#endif
+ }
+ if(errno==ECHILD)
+ {
+ errno = oerrno;
+#ifdef SHOPT_BGX
+ job.numbjob = 0;
+#endif /* SHOPT_BGX */
+ nochild = 1;
+ }
+ shp->gd->waitevent = waitevent;
+ if(sh_isoption(SH_NOTIFY) && sh_isstate(SH_TTYWAIT))
+ {
+ outfile = sfstderr;
+ job_list(pw,JOB_NFLAG|JOB_NLFLAG);
+ job_unpost(pw,1);
+ sfsync(sfstderr);
+ }
+ if(sig)
+ signal(sig, job_waitsafe);
+ return(nochild);
+}
+
+/*
+ * This is the SIGCLD interrupt routine
+ */
+static void job_waitsafe(int sig)
+{
+ if(job.in_critical || vmbusy())
+ {
+ job.savesig = sig;
+ job.waitsafe++;
+ }
+ else
+ job_reap(sig);
+}
+
+/*
+ * initialize job control if possible
+ * if lflag is set the switching driver message will not print
+ */
+void job_init(Shell_t *shp, int lflag)
+{
+ register int ntry=0;
+ job.fd = JOBTTY;
+ signal(SIGCHLD,job_waitsafe);
+# if defined(SIGCLD) && (SIGCLD!=SIGCHLD)
+ signal(SIGCLD,job_waitsafe);
+# endif
+ if(njob_savelist < NJOB_SAVELIST)
+ init_savelist();
+ if(!sh_isoption(SH_INTERACTIVE))
+ return;
+ /* use new line discipline when available */
+#ifdef NTTYDISC
+# ifdef FIOLOOKLD
+ if((job.linedisc = ioctl(JOBTTY, FIOLOOKLD, 0)) <0)
+# else
+ if(ioctl(JOBTTY,TIOCGETD,&job.linedisc) !=0)
+# endif /* FIOLOOKLD */
+ return;
+ if(job.linedisc!=NTTYDISC && job.linedisc!=OTTYDISC)
+ {
+ /* no job control when running with MPX */
+# if SHOPT_VSH
+ sh_onoption(SH_VIRAW);
+# endif /* SHOPT_VSH */
+ return;
+ }
+ if(job.linedisc==NTTYDISC)
+ job.linedisc = -1;
+#endif /* NTTYDISC */
+
+ job.mypgid = getpgrp();
+ /* some systems have job control, but not initialized */
+ if(job.mypgid<=0)
+ {
+ /* Get a controlling terminal and set process group */
+ /* This should have already been done by rlogin */
+ register int fd;
+ register char *ttynam;
+#ifndef SIGTSTP
+ setpgid(0,shp->gd->pid);
+#endif /*SIGTSTP */
+ if(job.mypgid<0 || !(ttynam=ttyname(JOBTTY)))
+ return;
+ close(JOBTTY);
+ if((fd = open(ttynam,O_RDWR)) <0)
+ return;
+ if(fd!=JOBTTY)
+ sh_iorenumber(shp,fd,JOBTTY);
+ job.mypgid = shp->gd->pid;
+#ifdef SIGTSTP
+ tcsetpgrp(JOBTTY,shp->gd->pid);
+ setpgid(0,shp->gd->pid);
+#endif /* SIGTSTP */
+ }
+#ifdef SIGTSTP
+ if(possible = (setpgid(0,job.mypgid)>=0) || errno==EPERM)
+ {
+ /* wait until we are in the foreground */
+ while((job.mytgid=tcgetpgrp(JOBTTY)) != job.mypgid)
+ {
+ if(job.mytgid == -1)
+ return;
+ /* Stop this shell until continued */
+ signal(SIGTTIN,SIG_DFL);
+ kill(shp->gd->pid,SIGTTIN);
+ /* resumes here after continue tries again */
+ if(ntry++ > IOMAXTRY)
+ {
+ errormsg(SH_DICT,0,e_no_start);
+ return;
+ }
+ }
+ }
+#endif /* SIGTTIN */
+
+#ifdef NTTYDISC
+ /* set the line discipline */
+ if(job.linedisc>=0)
+ {
+ int linedisc = NTTYDISC;
+# ifdef FIOPUSHLD
+ tty_get(JOBTTY,&my_stty);
+ if (ioctl(JOBTTY, FIOPOPLD, 0) < 0)
+ return;
+ if (ioctl(JOBTTY, FIOPUSHLD, &linedisc) < 0)
+ {
+ ioctl(JOBTTY, FIOPUSHLD, &job.linedisc);
+ return;
+ }
+ tty_set(JOBTTY,TCSANOW,&my_stty);
+# else
+ if(ioctl(JOBTTY,TIOCSETD,&linedisc) !=0)
+ return;
+# endif /* FIOPUSHLD */
+ if(lflag==0)
+ errormsg(SH_DICT,0,e_newtty);
+ else
+ job.linedisc = -1;
+ }
+#endif /* NTTYDISC */
+ if(!possible)
+ return;
+
+#ifdef SIGTSTP
+ /* make sure that we are a process group leader */
+ setpgid(0,shp->gd->pid);
+# if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT)
+# if !defined(SA_NOCLDSTOP)
+# define SA_NOCLDSTOP 0
+# endif
+# if !defined(SA_NOCLDWAIT)
+# define SA_NOCLDWAIT 0
+# endif
+ sigflag(SIGCHLD, SA_NOCLDSTOP|SA_NOCLDWAIT, 0);
+# endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */
+ signal(SIGTTIN,SIG_IGN);
+ signal(SIGTTOU,SIG_IGN);
+ /* The shell now handles ^Z */
+ signal(SIGTSTP,sh_fault);
+ tcsetpgrp(JOBTTY,shp->gd->pid);
+# ifdef CNSUSP
+ /* set the switch character */
+ tty_get(JOBTTY,&my_stty);
+ job.suspend = (unsigned)my_stty.c_cc[VSUSP];
+ if(job.suspend == (unsigned char)CNSUSP)
+ {
+ my_stty.c_cc[VSUSP] = CSWTCH;
+ tty_set(JOBTTY,TCSAFLUSH,&my_stty);
+ }
+# endif /* CNSUSP */
+ sh_onoption(SH_MONITOR);
+ job.jobcontrol++;
+ job.mypid = shp->gd->pid;
+#endif /* SIGTSTP */
+ return;
+}
+
+
+/*
+ * see if there are any stopped jobs
+ * restore tty driver and pgrp
+ */
+int job_close(Shell_t* shp)
+{
+ register struct process *pw;
+ register int count = 0, running = 0;
+ if(possible && !job.jobcontrol)
+ return(0);
+ else if(!possible && (!sh_isstate(SH_MONITOR) || sh_isstate(SH_FORKED)))
+ return(0);
+ else if(getpid() != job.mypid)
+ return(0);
+ job_lock();
+ if(!tty_check(0))
+ beenhere++;
+ for(pw=job.pwlist;pw;pw=pw->p_nxtjob)
+ {
+ if(!(pw->p_flag&P_STOPPED))
+ {
+ if(!(pw->p_flag&P_DONE))
+ running++;
+ continue;
+ }
+ if(beenhere)
+ killpg(pw->p_pgrp,SIGTERM);
+ count++;
+ }
+ if(beenhere++ == 0 && job.pwlist)
+ {
+ if(count)
+ {
+ errormsg(SH_DICT,0,e_terminate);
+ return(-1);
+ }
+ else if(running && shp->login_sh)
+ {
+ errormsg(SH_DICT,0,e_jobsrunning);
+ return(-1);
+ }
+ }
+ job_unlock();
+# ifdef SIGTSTP
+ if(possible && setpgid(0,job.mypgid)>=0)
+ tcsetpgrp(job.fd,job.mypgid);
+# endif /* SIGTSTP */
+# ifdef NTTYDISC
+ if(job.linedisc>=0)
+ {
+ /* restore old line discipline */
+# ifdef FIOPUSHLD
+ tty_get(job.fd,&my_stty);
+ if (ioctl(job.fd, FIOPOPLD, 0) < 0)
+ return(0);
+ if (ioctl(job.fd, FIOPUSHLD, &job.linedisc) < 0)
+ {
+ job.linedisc = NTTYDISC;
+ ioctl(job.fd, FIOPUSHLD, &job.linedisc);
+ return(0);
+ }
+ tty_set(job.fd,TCSAFLUSH,&my_stty);
+# else
+ if(ioctl(job.fd,TIOCSETD,&job.linedisc) !=0)
+ return(0);
+# endif /* FIOPUSHLD */
+ errormsg(SH_DICT,0,e_oldtty);
+ }
+# endif /* NTTYDISC */
+# ifdef CNSUSP
+ if(possible && job.suspend==CNSUSP)
+ {
+ tty_get(job.fd,&my_stty);
+ my_stty.c_cc[VSUSP] = CNSUSP;
+ tty_set(job.fd,TCSAFLUSH,&my_stty);
+ }
+# endif /* CNSUSP */
+ job.jobcontrol = 0;
+ return(0);
+}
+
+static void job_set(register struct process *pw)
+{
+ Shell_t *shp = pw->p_shp;
+ /* save current terminal state */
+ tty_get(job.fd,&my_stty);
+ if(pw->p_flag&P_STTY)
+ {
+ /* restore terminal state for job */
+ tty_set(job.fd,TCSAFLUSH,&pw->p_stty);
+ }
+#ifdef SIGTSTP
+ if((pw->p_flag&P_STOPPED) || tcgetpgrp(job.fd) == shp->gd->pid)
+ tcsetpgrp(job.fd,pw->p_fgrp);
+ /* if job is stopped, resume it in the background */
+ job_unstop(pw);
+#endif /* SIGTSTP */
+}
+
+static void job_reset(register struct process *pw)
+{
+ /* save the terminal state for current job */
+#ifdef SIGTSTP
+ job_fgrp(pw,tcgetpgrp(job.fd));
+ if(tcsetpgrp(job.fd,job.mypid) !=0)
+ return;
+#endif /* SIGTSTP */
+ /* force the following tty_get() to do a tcgetattr() unless fg */
+ if(!(pw->p_flag&P_FG))
+ tty_set(-1, 0, NIL(struct termios*));
+ if(pw && (pw->p_flag&P_SIGNALLED) && pw->p_exit!=SIGHUP)
+ {
+ if(tty_get(job.fd,&pw->p_stty) == 0)
+ pw->p_flag |= P_STTY;
+ /* restore terminal state for job */
+ tty_set(job.fd,TCSAFLUSH,&my_stty);
+ }
+ beenhere = 0;
+}
+#endif /* JOBS */
+
+/*
+ * wait built-in command
+ */
+
+void job_bwait(char **jobs)
+{
+ register char *jp;
+ register struct process *pw;
+ register pid_t pid;
+ if(*jobs==0)
+ job_wait((pid_t)-1);
+ else while(jp = *jobs++)
+ {
+#ifdef JOBS
+ if(*jp == '%')
+ {
+ job_lock();
+ pw = job_bystring(jp);
+ job_unlock();
+ if(pw)
+ pid = pw->p_pid;
+ else
+ return;
+ }
+# if SHOPT_COSHELL
+ else if(isalpha(*jp))
+ {
+ job_cowalk(NULL,0,jp);
+ return;
+ }
+# endif /* SHOPT_COSHELL */
+ else
+#endif /* JOBS */
+ pid = pid_fromstring(jp);
+ job_wait(-pid);
+ }
+}
+
+#ifdef JOBS
+/*
+ * execute function <fun> for each job
+ */
+
+int job_walk(Sfio_t *file,int (*fun)(struct process*,int),int arg,char *joblist[])
+{
+ register struct process *pw;
+ register int r = 0;
+ register char *jobid, **jobs=joblist;
+ register struct process *px;
+ job_string = 0;
+ outfile = file;
+ by_number = 0;
+ job_lock();
+ pw = job.pwlist;
+#if SHOPT_COSHELL
+ job_waitsafe(SIGCHLD);
+#endif /* SHOPT_COSHELL */
+ if(jobs==0)
+ {
+ /* do all jobs */
+ for(;pw;pw=px)
+ {
+ px = pw->p_nxtjob;
+ if(pw->p_env != sh.jobenv)
+ continue;
+ if((*fun)(pw,arg))
+ r = 2;
+ }
+ }
+ else if(*jobs==0) /* current job */
+ {
+ /* skip over non-stop jobs */
+ while(pw && (pw->p_env!=sh.jobenv || pw->p_pgrp==0))
+ pw = pw->p_nxtjob;
+ if((*fun)(pw,arg))
+ r = 2;
+ }
+ else while(jobid = *jobs++)
+ {
+ job_string = jobid;
+ if(*jobid==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string);
+#if SHOPT_COSHELL
+ if(isalpha(*jobid))
+ {
+ r = job_cowalk(fun,arg,jobid);
+ by_number = 0;
+ job_unlock();
+ return(r);
+ }
+#endif /* SHOPT_COSHELL */
+ if(*jobid == '%')
+ pw = job_bystring(jobid);
+ else
+ {
+ int pid = pid_fromstring(jobid);
+ if(!(pw = job_bypid(pid)))
+ {
+ pw = &dummy;
+ pw->p_shp = sh_getinterp();
+ pw->p_pid = pid;
+ pw->p_pgrp = pid;
+ }
+ by_number = 1;
+ }
+ if((*fun)(pw,arg))
+ r = 2;
+ by_number = 0;
+ }
+ job_unlock();
+ return(r);
+}
+
+/*
+ * send signal <sig> to background process group if not disowned
+ */
+int job_terminate(register struct process *pw,register int sig)
+{
+ if(pw->p_pgrp && !(pw->p_flag&P_DISOWN))
+ job_kill(pw,sig);
+ return(0);
+}
+
+/*
+ * list the given job
+ * flag JOB_LFLAG for long listing
+ * flag JOB_NFLAG for list only jobs marked for notification
+ * flag JOB_PFLAG for process id(s) only
+ */
+
+int job_list(struct process *pw,register int flag)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct process *px = pw;
+ register int n;
+ register const char *msg;
+ register int msize;
+ if(!pw || pw->p_job<=0)
+ return(1);
+ if(pw->p_env != shp->jobenv)
+ return(0);
+ if((flag&JOB_NFLAG) && (!(px->p_flag&P_NOTIFY)||px->p_pgrp==0))
+ return(0);
+ if((flag&JOB_PFLAG))
+ {
+#if SHOPT_COSHELL
+ sfprintf(outfile,"%s\n",sh_pid2str(shp,px->p_pgrp?px->p_pgrp:px->p_pid));
+#else
+ sfprintf(outfile,"%d\n",px->p_pgrp?px->p_pgrp:px->p_pid);
+#endif /* SHOPT_COSHELL */
+ return(0);
+ }
+ if((px->p_flag&P_DONE) && job.waitall && !(flag&JOB_LFLAG))
+ return(0);
+ job_lock();
+ n = px->p_job;
+ if(px==job.pwlist)
+ msize = '+';
+ else if(px==job.pwlist->p_nxtjob)
+ msize = '-';
+ else
+ msize = ' ';
+ if(flag&JOB_NLFLAG)
+ sfputc(outfile,'\n');
+ sfprintf(outfile,"[%d] %c ",n, msize);
+ do
+ {
+ n = 0;
+ if(flag&JOB_LFLAG)
+#if SHOPT_COSHELL
+ sfprintf(outfile,"%s\t",sh_pid2str(shp,px->p_pid));
+#else
+ sfprintf(outfile,"%d\t",px->p_pid);
+#endif /* SHOPT_COSHELL */
+ if(px->p_flag&P_SIGNALLED)
+ msg = job_sigmsg((int)(px->p_exit));
+ else if(px->p_flag&P_NOTIFY)
+ {
+ msg = sh_translate(e_done);
+ n = px->p_exit;
+ }
+ else
+ msg = sh_translate(e_running);
+ px->p_flag &= ~P_NOTIFY;
+ sfputr(outfile,msg,-1);
+ msize = strlen(msg);
+ if(n)
+ {
+ sfprintf(outfile,"(%d)",(int)n);
+ msize += (3+(n>10)+(n>100));
+ }
+ if(px->p_flag&P_COREDUMP)
+ {
+ msg = sh_translate(e_coredump);
+ sfputr(outfile, msg, -1);
+ msize += strlen(msg);
+ }
+ sfnputc(outfile,' ',MAXMSG>msize?MAXMSG-msize:1);
+ if(flag&JOB_LFLAG)
+ px = px->p_nxtproc;
+ else
+ {
+ while(px=px->p_nxtproc)
+ px->p_flag &= ~P_NOTIFY;
+ px = 0;
+ }
+ if(!px)
+ hist_list(shgd->hist_ptr,outfile,pw->p_name,0,";");
+ else
+ sfputr(outfile, e_nlspace, -1);
+ }
+ while(px);
+ job_unlock();
+ return(0);
+}
+
+/*
+ * get the process group given the job number
+ * This routine returns the process group number or -1
+ */
+static struct process *job_bystring(register char *ajob)
+{
+ register struct process *pw=job.pwlist;
+ register int c;
+ if(*ajob++ != '%' || !pw)
+ return(NIL(struct process*));
+ c = *ajob;
+ if(isdigit(c))
+ pw = job_byjid((int)strtol(ajob, (char**)0, 10));
+ else if(c=='+' || c=='%')
+ ;
+ else if(c=='-')
+ {
+ if(pw)
+ pw = job.pwlist->p_nxtjob;
+ }
+ else
+ pw = job_byname(ajob);
+ if(pw && pw->p_flag)
+ return(pw);
+ return(NIL(struct process*));
+}
+
+/*
+ * Kill a job or process
+ */
+
+int job_kill(register struct process *pw,register int sig)
+{
+ Shell_t *shp = pw->p_shp;
+ register pid_t pid;
+ register int r;
+ const char *msg;
+#ifdef SIGTSTP
+ int stopsig = (sig==SIGSTOP||sig==SIGTSTP||sig==SIGTTIN||sig==SIGTTOU);
+#else
+# define stopsig 1
+#endif /* SIGTSTP */
+ job_lock();
+ errno = ECHILD;
+ if(pw==0)
+ goto error;
+ pid = pw->p_pid;
+#if SHOPT_COSHELL
+ if(pw->p_cojob)
+ r = cokill(pw->p_cojob->coshell,pw->p_cojob,sig);
+ else
+#endif /* SHOPT_COSHELL */
+ if(by_number)
+ {
+ if(pid==0 && job.jobcontrol)
+ r = job_walk(outfile, job_kill,sig, (char**)0);
+#ifdef SIGTSTP
+ if(sig==SIGSTOP && pid==shp->gd->pid && shp->gd->ppid==1)
+ {
+ /* can't stop login shell */
+ errno = EPERM;
+ r = -1;
+ }
+ else
+ {
+ if(pid>=0)
+ {
+ if((r = kill(pid,sig))>=0 && !stopsig)
+ {
+ if(pw->p_flag&P_STOPPED)
+ pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
+ if(sig)
+ kill(pid,SIGCONT);
+ }
+ }
+ else
+ {
+ if((r = killpg(-pid,sig))>=0 && !stopsig)
+ {
+ job_unstop(job_bypid(pw->p_pid));
+ if(sig)
+ killpg(-pid,SIGCONT);
+ }
+ }
+ }
+#else
+ if(pid>=0)
+ r = kill(pid,sig);
+ else
+ r = killpg(-pid,sig);
+#endif /* SIGTSTP */
+ }
+ else
+ {
+ if(pid = pw->p_pgrp)
+ {
+ r = killpg(pid,sig);
+#ifdef SIGTSTP
+ if(r>=0 && (sig==SIGHUP||sig==SIGTERM || sig==SIGCONT))
+ job_unstop(pw);
+#endif /* SIGTSTP */
+ if(r>=0)
+ sh_delay(.05);
+ }
+ while(pw && pw->p_pgrp==0 && (r=kill(pw->p_pid,sig))>=0)
+ {
+#ifdef SIGTSTP
+ if(sig==SIGHUP || sig==SIGTERM)
+ kill(pw->p_pid,SIGCONT);
+#endif /* SIGTSTP */
+ pw = pw->p_nxtproc;
+ }
+ }
+ if(r<0 && job_string)
+ {
+ error:
+ if(pw && by_number)
+ msg = sh_translate(e_no_proc);
+ else
+ msg = sh_translate(e_no_job);
+ if(errno == EPERM)
+ msg = sh_translate(e_access);
+ sfprintf(sfstderr,"kill: %s: %s\n",job_string, msg);
+ r = 2;
+ }
+ sh_delay(.001);
+ job_unlock();
+ return(r);
+}
+
+/*
+ * Get process structure from first letters of jobname
+ *
+ */
+
+static struct process *job_byname(char *name)
+{
+ register struct process *pw = job.pwlist;
+ register struct process *pz = 0;
+ register int *flag = 0;
+ register char *cp = name;
+ int offset;
+ if(!shgd->hist_ptr)
+ return(NIL(struct process*));
+ if(*cp=='?')
+ cp++,flag= &offset;
+ for(;pw;pw=pw->p_nxtjob)
+ {
+ if(hist_match(shgd->hist_ptr,pw->p_name,cp,flag)>=0)
+ {
+ if(pz)
+ errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name-1);
+ pz = pw;
+ }
+ }
+ return(pz);
+}
+
+#else
+# define job_set(x)
+# define job_reset(x)
+#endif /* JOBS */
+
+
+
+/*
+ * Initialize the process posting array
+ */
+
+void job_clear(void)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct process *pw, *px;
+ register struct process *pwnext;
+ register int j = BYTE(shp->gd->lim.child_max);
+ register struct jobsave *jp,*jpnext;
+ job_lock();
+ for(pw=job.pwlist; pw; pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ while(px=pw)
+ {
+ pw = pw->p_nxtproc;
+ free((void*)px);
+ }
+ }
+ for(jp=bck.list; jp;jp=jpnext)
+ {
+ jpnext = jp->next;
+ free((void*)jp);
+ }
+ bck.list = 0;
+ if(njob_savelist < NJOB_SAVELIST)
+ init_savelist();
+ job.pwlist = NIL(struct process*);
+ job.numpost=0;
+#ifdef SHOPT_BGX
+ job.numbjob = 0;
+#endif /* SHOPT_BGX */
+ job.waitall = 0;
+ job.curpgid = 0;
+ job.toclear = 0;
+ if(!job.freejobs)
+ job.freejobs = (unsigned char*)malloc((unsigned)(j+1));
+ while(j >=0)
+ job.freejobs[j--] = 0;
+ job_unlock();
+}
+
+/*
+ * put the process <pid> on the process list and return the job number
+ * if non-zero, <join> is the process id of the job to join
+ */
+
+int job_post(Shell_t *shp,pid_t pid, pid_t join)
+{
+ register struct process *pw;
+ register History_t *hp = shp->gd->hist_ptr;
+#ifdef SHOPT_BGX
+ int val,bg=0;
+#else
+ int val;
+#endif
+ shp->jobenv = shp->curenv;
+ if(job.toclear)
+ {
+ job_clear();
+ return(0);
+ }
+ job_lock();
+#ifdef SHOPT_BGX
+ if(join==1)
+ {
+ join = 0;
+ bg = P_BG;
+ job.numbjob++;
+ }
+#endif /* SHOPT_BGX */
+ if(njob_savelist < NJOB_SAVELIST)
+ init_savelist();
+ if(pw = job_bypid(pid))
+ job_unpost(pw,0);
+ if(join)
+ {
+ if(pw=job_bypid(join))
+ val = pw->p_job;
+ else
+ val = job.curjobid;
+ /* if job to join is not first move it to front */
+ if(val && (pw=job_byjid(val)) != job.pwlist)
+ {
+ job_unlink(pw);
+ pw->p_nxtjob = job.pwlist;
+ job.pwlist = pw;
+ }
+ }
+ if(pw=freelist)
+ freelist = pw->p_nxtjob;
+ else
+ pw = new_of(struct process,0);
+ pw->p_flag = 0;
+ job.numpost++;
+ if(join && job.pwlist)
+ {
+ /* join existing current job */
+ pw->p_nxtjob = job.pwlist->p_nxtjob;
+ pw->p_nxtproc = job.pwlist;
+ pw->p_job = job.pwlist->p_job;
+ }
+ else
+ {
+ /* create a new job */
+ while((pw->p_job = job_alloc()) < 0)
+ job_wait((pid_t)1);
+ pw->p_nxtjob = job.pwlist;
+ pw->p_nxtproc = 0;
+ }
+ pw->p_exitval = job.exitval;
+#if SHOPT_COSHELL
+ pw->p_cojob = 0;
+ if(shp->coshell && (pid&COPID_BIT))
+ {
+ pw->p_cojob = ((struct cosh*)shp->coshell)->cojob;
+ job.curpgid = sh_isstate(SH_MONITOR)?pid:0;
+ }
+#endif /* SHOPT_COSHELL */
+ job.pwlist = pw;
+ pw->p_shp = shp;
+ pw->p_env = shp->curenv;
+ pw->p_pid = pid;
+ if(!shp->outpipe || shp->cpid==pid)
+ pw->p_flag = P_EXITSAVE;
+ pw->p_exitmin = shp->xargexit;
+ pw->p_exit = 0;
+ if(sh_isstate(SH_MONITOR))
+ {
+ if(killpg(job.curpgid,0)<0 && errno==ESRCH)
+ job.curpgid = pid;
+ pw->p_fgrp = job.curpgid;
+ }
+ else
+ pw->p_fgrp = 0;
+ pw->p_pgrp = pw->p_fgrp;
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: post pid=%d critical=%d job=%d pid=%d pgid=%d savesig=%d join=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,
+ pw->p_pid,pw->p_pgrp,job.savesig,join);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+#ifdef JOBS
+ if(hp && !sh_isstate(SH_PROFILE))
+ pw->p_name=hist_tell(shgd->hist_ptr,(int)hp->histind-1);
+ else
+ pw->p_name = -1;
+#endif /* JOBS */
+ if ((val = job_chksave(pid))>=0 && !jobfork)
+ {
+ pw->p_exit = val;
+ if(pw->p_exit==SH_STOPSIG)
+ {
+ pw->p_flag |= (P_SIGNALLED|P_STOPPED);
+ pw->p_exit = 0;
+ }
+ else if(pw->p_exit >= SH_EXITSIG)
+ {
+ pw->p_flag |= P_DONE|P_SIGNALLED;
+ pw->p_exit &= SH_EXITMASK;
+ }
+ else
+ pw->p_flag |= (P_DONE|P_NOTIFY);
+ }
+#ifdef SHOPT_BGX
+ if(bg)
+ {
+ if(pw->p_flag&P_DONE)
+ job.numbjob--;
+ else
+ pw->p_flag |= P_BG;
+ }
+#endif /* SHOPT_BGX */
+ lastpid = 0;
+ job_unlock();
+ return(pw->p_job);
+}
+
+/*
+ * Returns a process structure give a process id
+ */
+
+static struct process *job_bypid(pid_t pid)
+{
+ register struct process *pw, *px;
+ for(pw=job.pwlist; pw; pw=pw->p_nxtjob)
+ for(px=pw; px; px=px->p_nxtproc)
+ {
+ if(px->p_pid==pid)
+ return(px);
+ }
+ return(NIL(struct process*));
+}
+
+/*
+ * return a pointer to a job given the job id
+ */
+
+static struct process *job_byjid(int jobid)
+{
+ register struct process *pw;
+ for(pw=job.pwlist;pw; pw = pw->p_nxtjob)
+ {
+ if(pw->p_job==jobid)
+ break;
+ }
+ return(pw);
+}
+
+/*
+ * print a signal message
+ */
+static void job_prmsg(register struct process *pw)
+{
+ if(pw->p_exit!=SIGINT && pw->p_exit!=SIGPIPE)
+ {
+ register const char *msg, *dump;
+ msg = job_sigmsg((int)(pw->p_exit));
+ msg = sh_translate(msg);
+ if(pw->p_flag&P_COREDUMP)
+ dump = sh_translate(e_coredump);
+ else
+ dump = "";
+ if(sh_isstate(SH_INTERACTIVE))
+ sfprintf(sfstderr,"%s%s\n",msg,dump);
+ else
+ errormsg(SH_DICT,2,"%d: %s%s",pw->p_pid,msg,dump);
+ }
+}
+
+/*
+ * Wait for process pid to complete
+ * If pid < -1, then wait can be interrupted, -pid is waited for (wait builtin)
+ * pid=0 to unpost all done processes
+ * pid=1 to wait for at least one process to complete
+ * pid=-1 to wait for all runing processes
+ */
+
+int job_wait(register pid_t pid)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct process *pw=0,*px;
+ register int jobid = 0;
+ int nochild = 1;
+ char intr = 0;
+ if(pid < 0)
+ {
+ pid = -pid;
+ intr = 1;
+ }
+ job_lock();
+ if(pid==0)
+ {
+ if(!job.waitall || !job.curjobid || !(pw = job_byjid(job.curjobid)))
+ {
+ job_unlock();
+ goto done;
+ }
+ jobid = pw->p_job;
+ job.curjobid = 0;
+ if(!(pw->p_flag&(P_DONE|P_STOPPED)))
+ job_reap(job.savesig);
+ }
+ if(pid > 1)
+ {
+ if(pid==shp->spid)
+ shp->spid = 0;
+ if(!(pw=job_bypid(pid)))
+ {
+ /* check to see whether job status has been saved */
+ if((shp->exitval = job_chksave(pid)) < 0)
+ shp->exitval = ERROR_NOENT;
+ exitset();
+ job_unlock();
+ return(nochild);
+ }
+ else if(intr && pw->p_env!=shp->curenv)
+ {
+ shp->exitval = ERROR_NOENT;
+ job_unlock();
+ return(nochild);
+ }
+ jobid = pw->p_job;
+ if(!intr)
+ pw->p_flag &= ~P_EXITSAVE;
+ if(pw->p_pgrp && job.parent!= (pid_t)-1)
+ job_set(job_byjid(jobid));
+ }
+ pwfg = pw;
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d job=%d pid=%d\n",__LINE__,getpid(),job.in_critical,jobid,pid);
+ if(pw)
+ sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__,getpid(),job.in_critical,pw->p_flag);
+#endif /* DEBUG*/
+ errno = 0;
+ if(shp->coutpipe>=0 && lastpid && shp->cpid==lastpid)
+ {
+ sh_close(shp->coutpipe);
+ sh_close(shp->cpipe[1]);
+ shp->cpipe[1] = shp->coutpipe = -1;
+ }
+ while(1)
+ {
+ if(job.waitsafe)
+ {
+ for(px=job.pwlist;px; px = px->p_nxtjob)
+ {
+ if(px!=pw && (px->p_flag&P_NOTIFY))
+ {
+ if(sh_isoption(SH_NOTIFY))
+ {
+ outfile = sfstderr;
+ job_list(px,JOB_NFLAG|JOB_NLFLAG);
+ sfsync(sfstderr);
+ }
+ else if(!sh_isoption(SH_INTERACTIVE) && (px->p_flag&P_SIGNALLED))
+ {
+ job_prmsg(px);
+ px->p_flag &= ~P_NOTIFY;
+ }
+ }
+ }
+ }
+ if(pw && (pw->p_flag&(P_DONE|P_STOPPED)))
+ {
+#ifdef SIGTSTP
+ if(pw->p_flag&P_STOPPED)
+ {
+ pw->p_flag |= P_EXITSAVE;
+ if(sh_isoption(SH_INTERACTIVE) && !sh_isstate(SH_FORKED))
+ {
+ if( pw->p_exit!=SIGTTIN && pw->p_exit!=SIGTTOU)
+ break;
+
+ killpg(pw->p_pgrp,SIGCONT);
+ }
+ else /* ignore stop when non-interactive */
+ pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED|P_EXITSAVE);
+ }
+ else
+#endif /* SIGTSTP */
+ {
+ if(pw->p_flag&P_SIGNALLED)
+ {
+ pw->p_flag &= ~P_NOTIFY;
+ job_prmsg(pw);
+ }
+ else if(pw->p_flag&P_DONE)
+ pw->p_flag &= ~P_NOTIFY;
+ if(pw->p_job==jobid)
+ {
+ px = job_byjid(jobid);
+ /* last process in job */
+ if(px!=pw)
+ px = 0;
+ if(px)
+ {
+ shp->exitval=px->p_exit;
+ if(px->p_flag&P_SIGNALLED)
+ shp->exitval |= SH_EXITSIG;
+ if(intr)
+ px->p_flag &= ~P_EXITSAVE;
+ }
+ }
+ px = job_unpost(pw,1);
+ if(!px || !job.waitall)
+ break;
+ pw = px;
+ continue;
+ }
+ }
+ sfsync(sfstderr);
+ job.waitsafe = 0;
+ nochild = job_reap(job.savesig);
+ if(job.waitsafe)
+ continue;
+ if(nochild)
+ break;
+ if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
+ sh_timetraps(shp);
+ if((intr && shp->trapnote) || (pid==1 && !intr))
+ break;
+ }
+ if(intr && shp->trapnote)
+ shp->exitval = 1;
+ pwfg = 0;
+ job_unlock();
+ if(pid==1)
+ return(nochild);
+ exitset();
+ if(pid==0)
+ goto done;
+ if(pw->p_pgrp)
+ {
+ job_reset(pw);
+ /* propogate keyboard interrupts to parent */
+ if((pw->p_flag&P_SIGNALLED) && pw->p_exit==SIGINT && !(shp->sigflag[SIGINT]&SH_SIGOFF))
+ sh_fault(SIGINT);
+#ifdef SIGTSTP
+ else if((pw->p_flag&P_STOPPED) && pw->p_exit==SIGTSTP)
+ {
+ job.parent = 0;
+ sh_fault(SIGTSTP);
+ }
+#endif /* SIGTSTP */
+ }
+ else
+ {
+ if(pw->p_pid == tcgetpgrp(JOBTTY))
+ {
+ if(pw->p_pgrp==0)
+ pw->p_pgrp = pw->p_pid;
+ job_reset(pw);
+ }
+ tty_set(-1, 0, NIL(struct termios*));
+ }
+done:
+ if(!job.waitall && sh_isoption(SH_PIPEFAIL))
+ return(nochild);
+ if(!shp->intrap)
+ {
+ job_lock();
+ for(pw=job.pwlist; pw; pw=px)
+ {
+ px = pw->p_nxtjob;
+ job_unpost(pw,0);
+ }
+ job_unlock();
+ }
+ return(nochild);
+}
+
+/*
+ * move job to foreground if bgflag == 'f'
+ * move job to background if bgflag == 'b'
+ * disown job if bgflag == 'd'
+ */
+
+int job_switch(register struct process *pw,int bgflag)
+{
+ register const char *msg;
+ job_lock();
+ if(!pw || !(pw=job_byjid((int)pw->p_job)))
+ {
+ job_unlock();
+ return(1);
+ }
+ if(bgflag=='d')
+ {
+ for(; pw; pw=pw->p_nxtproc)
+ pw->p_flag |= P_DISOWN;
+ job_unlock();
+ return(0);
+ }
+#ifdef SIGTSTP
+ if(bgflag=='b')
+ {
+ sfprintf(outfile,"[%d]\t",(int)pw->p_job);
+ sh.bckpid = pw->p_pid;
+#ifdef SHOPT_BGX
+ pw->p_flag |= P_BG;
+#endif
+ msg = "&";
+ }
+ else
+ {
+ job_unlink(pw);
+ pw->p_nxtjob = job.pwlist;
+ job.pwlist = pw;
+ msg = "";
+ }
+ hist_list(shgd->hist_ptr,outfile,pw->p_name,'&',";");
+ sfputr(outfile,msg,'\n');
+ sfsync(outfile);
+ if(bgflag=='f')
+ {
+ if(!(pw=job_unpost(pw,1)))
+ {
+ job_unlock();
+ return(1);
+ }
+ job.waitall = 1;
+ pw->p_flag |= P_FG;
+#ifdef SHOPT_BGX
+ pw->p_flag &= ~P_BG;
+#endif
+ job_wait(pw->p_pid);
+ job.waitall = 0;
+ }
+ else if(pw->p_flag&P_STOPPED)
+ job_unstop(pw);
+#endif /* SIGTSTP */
+ job_unlock();
+ return(0);
+}
+
+
+#ifdef SIGTSTP
+/*
+ * Set the foreground group associated with a job
+ */
+
+static void job_fgrp(register struct process *pw, int newgrp)
+{
+ for(; pw; pw=pw->p_nxtproc)
+ pw->p_fgrp = newgrp;
+}
+
+/*
+ * turn off STOP state of a process group and send CONT signals
+ */
+
+static void job_unstop(register struct process *px)
+{
+ register struct process *pw;
+ register int num = 0;
+ for(pw=px ;pw ;pw=pw->p_nxtproc)
+ {
+ if(pw->p_flag&P_STOPPED)
+ {
+ num++;
+ pw->p_flag &= ~(P_STOPPED|P_SIGNALLED|P_NOTIFY);
+ }
+ }
+ if(num!=0)
+ {
+ if(px->p_fgrp != px->p_pgrp)
+ killpg(px->p_fgrp,SIGCONT);
+ killpg(px->p_pgrp,SIGCONT);
+ }
+}
+#endif /* SIGTSTP */
+
+/*
+ * remove a job from table
+ * If all the processes have not completed, unpost first non-completed process
+ * Otherwise the job is removed and job_unpost returns NULL.
+ * pwlist is reset if the first job is removed
+ * if <notify> is non-zero, then jobs with pending notifications are unposted
+ */
+
+static struct process *job_unpost(register struct process *pwtop,int notify)
+{
+ register struct process *pw;
+ /* make sure all processes are done */
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: drop pid=%d critical=%d pid=%d env=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_pid,pwtop->p_env);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ pwtop = pw = job_byjid((int)pwtop->p_job);
+#ifdef SHOPT_BGX
+ if(pw->p_flag&P_BG)
+ return(pw);
+#endif /* SHOPT_BGX */
+ for(; pw && (pw->p_flag&P_DONE)&&(notify||!(pw->p_flag&P_NOTIFY)||pw->p_env); pw=pw->p_nxtproc);
+ if(pw)
+ return(pw);
+ if(pwtop->p_job == job.curjobid)
+ return(0);
+ /* all processes complete, unpost job */
+ job_unlink(pwtop);
+ for(pw=pwtop; pw; pw=pw->p_nxtproc)
+ {
+ if(pw && pw->p_exitval)
+ *pw->p_exitval = pw->p_exit;
+ /* save the exit status for background jobs */
+ if((pw->p_flag&P_EXITSAVE) || pw->p_pid==sh.spid)
+ {
+ struct jobsave *jp;
+ /* save status for future wait */
+ if(jp = jobsave_create(pw->p_pid))
+ {
+ jp->exitval = pw->p_exit;
+ if(pw->p_flag&P_SIGNALLED)
+ jp->exitval |= SH_EXITSIG;
+ }
+ pw->p_flag &= ~P_EXITSAVE;
+ }
+ pw->p_flag &= ~P_DONE;
+ job.numpost--;
+ pw->p_nxtjob = freelist;
+ freelist = pw;
+ }
+ pwtop->p_pid = 0;
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_job);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ job_free((int)pwtop->p_job);
+ return((struct process*)0);
+}
+
+/*
+ * unlink a job form the job list
+ */
+static void job_unlink(register struct process *pw)
+{
+ register struct process *px;
+ if(pw==job.pwlist)
+ {
+ job.pwlist = pw->p_nxtjob;
+ job.curpgid = 0;
+ return;
+ }
+ for(px=job.pwlist;px;px=px->p_nxtjob)
+ if(px->p_nxtjob == pw)
+ {
+ px->p_nxtjob = pw->p_nxtjob;
+ return;
+ }
+}
+
+/*
+ * get an unused job number
+ * freejobs is a bit vector, 0 is unused
+ */
+
+static int job_alloc(void)
+{
+ register int j=0;
+ register unsigned mask = 1;
+ register unsigned char *freeword;
+ register int jmax = BYTE(shgd->lim.child_max);
+ /* skip to first word with a free slot */
+ for(j=0;job.freejobs[j] == UCHAR_MAX; j++);
+ if(j >= jmax)
+ {
+ register struct process *pw;
+ for(j=1; j < shgd->lim.child_max; j++)
+ {
+ if((pw=job_byjid(j))&& !job_unpost(pw,0))
+ break;
+ }
+ j /= CHAR_BIT;
+ if(j >= jmax)
+ return(-1);
+ }
+ freeword = &job.freejobs[j];
+ j *= CHAR_BIT;
+ for(j++;mask&(*freeword);j++,mask <<=1);
+ *freeword |= mask;
+ return(j);
+}
+
+/*
+ * return a job number
+ */
+
+static void job_free(register int n)
+{
+ register int j = (--n)/CHAR_BIT;
+ register unsigned mask;
+ n -= j*CHAR_BIT;
+ mask = 1 << n;
+ job.freejobs[j] &= ~mask;
+}
+
+static char *job_sigmsg(int sig)
+{
+ static char signo[40];
+#ifdef apollo
+ /*
+ * This code handles the formatting for the apollo specific signal
+ * SIGAPOLLO.
+ */
+ extern char *apollo_error(void);
+
+ if ( sig == SIGAPOLLO )
+ return( apollo_error() );
+#endif /* apollo */
+ if(sig<=shgd->sigmax && shgd->sigmsg[sig])
+ return(shgd->sigmsg[sig]);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ if(sig>=sh.gd->sigruntime[SH_SIGRTMIN] && sig<=sh.gd->sigruntime[SH_SIGRTMAX])
+ {
+ static char sigrt[20];
+ if(sig>sh.gd->sigruntime[SH_SIGRTMIN]+(sh.gd->sigruntime[SH_SIGRTMAX]-sig<=sh.gd->sigruntime[SH_SIGRTMIN])/2)
+ sfsprintf(sigrt,sizeof(sigrt),"SIGRTMAX-%d",sh.gd->sigruntime[SH_SIGRTMAX]-sig);
+ else
+ sfsprintf(sigrt,sizeof(sigrt),"SIGRTMIN+%d",sig-sh.gd->sigruntime[SH_SIGRTMIN]);
+ return(sigrt);
+ }
+#endif
+ sfsprintf(signo,sizeof(signo),sh_translate(e_signo),sig);
+ return(signo);
+}
+
+/*
+ * see whether exit status has been saved and delete it
+ * if pid==0, then oldest saved process is deleted
+ * If pid is not found a -1 is returned.
+ */
+static int job_chksave(register pid_t pid)
+{
+ register struct jobsave *jp = bck.list, *jpold=0;
+ register int r= -1;
+ register int count=bck.count;
+ struct back_save *bp= &bck;
+again:
+ while(jp && count-->0)
+ {
+ if(jp->pid==pid)
+ break;
+ if(pid==0 && !jp->next)
+ break;
+ jpold = jp;
+ jp = jp->next;
+ }
+ if(!jp && pid && (bp=bp->prev))
+ {
+ count = bp->count;
+ jp = bp->list;
+ goto again;
+ }
+ if(jp)
+ {
+ r = 0;
+ if(pid)
+ r = jp->exitval;
+ if(jpold)
+ jpold->next = jp->next;
+ else
+ bp->list = jp->next;
+ bp->count--;
+ if(njob_savelist < NJOB_SAVELIST)
+ {
+ njob_savelist++;
+ jp->next = job_savelist;
+ job_savelist = jp;
+ }
+ else
+ free((void*)jp);
+ }
+ return(r);
+}
+
+void *job_subsave(void)
+{
+ struct back_save *bp = new_of(struct back_save,0);
+ job_lock();
+ *bp = bck;
+ bp->prev = bck.prev;
+ bck.count = 0;
+ bck.list = 0;
+ bck.prev = bp;
+ job_unlock();
+ return((void*)bp);
+}
+
+void job_subrestore(void* ptr)
+{
+ register struct jobsave *jp, *jpnext;
+ register struct back_save *bp = (struct back_save*)ptr;
+ register struct process *pw, *px, *pwnext;
+ struct jobsave *end=NULL;
+ job_lock();
+ for(jp=bck.list; jp; jp=jp->next)
+ {
+ if (!jp->next)
+ end = jp;
+ }
+ if(end)
+ end->next = bp->list;
+ else
+ bck.list = bp->list;
+ bck.count += bp->count;
+ bck.prev = bp->prev;
+ while(bck.count > shgd->lim.child_max)
+ job_chksave(0);
+ for(pw=job.pwlist; pw; pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ if(pw->p_env != sh.curenv || pw->p_pid==sh.pipepid)
+ continue;
+ for(px=pw; px; px=px->p_nxtproc)
+ px->p_flag |= P_DONE;
+ job_unpost(pw,0);
+ }
+
+ free((void*)bp);
+ job_unlock();
+}
+
+int sh_waitsafe(void)
+{
+ return(job.waitsafe);
+}
+
+void job_fork(pid_t parent)
+{
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__,getpid(),job.in_critical,parent);
+#endif /* DEBUG */
+ switch (parent)
+ {
+ case -1:
+ job_lock();
+ jobfork++;
+ break;
+ case 0:
+ jobfork=0;
+ job_unlock();
+ job.waitsafe = 0;
+ job.in_critical = 0;
+ break;
+ default:
+ jobfork=0;
+ job_unlock();
+ break;
+ }
+}
+
diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c
new file mode 100644
index 0000000..cbefd16
--- /dev/null
+++ b/src/cmd/ksh93/sh/lex.c
@@ -0,0 +1,2516 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * KornShell lexical analyzer
+ *
+ * Written by David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <stak.h>
+#include <fcin.h>
+#include <nval.h>
+#include "FEATURE/options"
+
+#if KSHELL
+# include "defs.h"
+#else
+# include <shell.h>
+# define nv_getval(np) ((np)->nvalue)
+ Shell_t sh = {1};
+#endif /* KSHELL */
+
+#include "argnod.h"
+#include "test.h"
+#include "lexstates.h"
+#include "io.h"
+
+#define TEST_RE 3
+#define SYNBAD 3 /* exit value for syntax errors */
+#define STACK_ARRAY 3 /* size of depth match stack growth */
+
+#if _lib_iswblank < 0 /* set in lexstates.h to enable this code */
+
+int
+local_iswblank(wchar_t wc)
+{
+ static int initialized;
+ static wctype_t wt;
+
+ if (!initialized)
+ {
+ initialized = 1;
+ wt = wctype("blank");
+ }
+ return(iswctype(wc, wt));
+}
+
+#endif
+
+/*
+ * This structure allows for arbitrary depth nesting of (...), {...}, [...]
+ */
+struct lexstate
+{
+ char incase; /* 1 for case pattern, 2 after case */
+ char intest; /* 1 inside [[...]] */
+ char testop1; /* 1 when unary test op legal */
+ char testop2; /* 1 when binary test op legal */
+ char reservok; /* >0 for reserved word legal */
+ char skipword; /* next word can't be reserved */
+ char last_quote; /* last multi-line quote character */
+ char nestedbrace; /* ${var op {...}} */
+};
+
+struct lexdata
+{
+ char nocopy;
+ char paren;
+ char dolparen;
+ char nest;
+ char docword;
+ char nested_tilde;
+ char *docend;
+ char noarg;
+ char balance;
+ char warn;
+ char message;
+ char arith;
+ char *first;
+ int level;
+ int lastc;
+ int lex_max;
+ int *lex_match;
+ int lex_state;
+ int docextra;
+#if SHOPT_KIA
+ off_t kiaoff;
+#endif
+};
+
+#define _SHLEX_PRIVATE \
+ struct lexdata lexd; \
+ struct lexstate lex;
+
+#include "shlex.h"
+
+
+#define pushlevel(lp,c,s) ((lp->lexd.level>=lp->lexd.lex_max?stack_grow(lp):1) &&\
+ ((lp->lexd.lex_match[lp->lexd.level++]=lp->lexd.lastc),\
+ lp->lexd.lastc=(((s)<<CHAR_BIT)|(c))))
+#define oldmode(lp) (lp->lexd.lastc>>CHAR_BIT)
+#define endchar(lp) (lp->lexd.lastc&0xff)
+#define setchar(lp,c) (lp->lexd.lastc = ((lp->lexd.lastc&~0xff)|(c)))
+#define poplevel(lp) (lp->lexd.lastc=lp->lexd.lex_match[--lp->lexd.level])
+
+static char *fmttoken(Lex_t*, int, char*);
+#ifdef SF_BUFCONST
+ static int alias_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
+#else
+ static int alias_exceptf(Sfio_t*, int, Sfdisc_t*);
+#endif
+static void setupalias(Lex_t*,const char*, Namval_t*);
+static int comsub(Lex_t*,int);
+static void nested_here(Lex_t*);
+static int here_copy(Lex_t*, struct ionod*);
+static int stack_grow(Lex_t*);
+static const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL };
+
+#if SHOPT_KIA
+
+static void refvar(Lex_t *lp, int type)
+{
+ register Shell_t *shp = lp->sh;
+ register Stk_t *stkp = shp->stk;
+ off_t off = (fcseek(0)-(type+1))-(lp->lexd.first?lp->lexd.first:fcfirst());
+ unsigned long r;
+ if(lp->lexd.first)
+ {
+ off = (fcseek(0)-(type+1)) - lp->lexd.first;
+ r=kiaentity(lp,lp->lexd.first+lp->lexd.kiaoff+type,off-lp->lexd.kiaoff,'v',-1,-1,lp->current,'v',0,"");
+ }
+ else
+ {
+ int n,offset = stktell(stkp);
+ char *savptr,*begin;
+ off = offset + (fcseek(0)-(type+1)) - fcfirst();
+ if(lp->lexd.kiaoff < offset)
+ {
+ /* variable starts on stak, copy remainder */
+ if(off>offset)
+ sfwrite(stkp,fcfirst()+type,off-offset);
+ n = stktell(stkp)-lp->lexd.kiaoff;
+ begin = stkptr(stkp,lp->lexd.kiaoff);
+ }
+ else
+ {
+ /* variable in data buffer */
+ begin = fcfirst()+(type+lp->lexd.kiaoff-offset);
+ n = off-lp->lexd.kiaoff;
+ }
+ savptr = stkfreeze(stkp,0);
+ r=kiaentity(lp,begin,n,'v',-1,-1,lp->current,'v',0,"");
+ stkset(stkp,savptr,offset);
+ }
+ sfprintf(lp->kiatmp,"p;%..64d;v;%..64d;%d;%d;r;\n",lp->current,r,shp->inlineno,shp->inlineno);
+}
+#endif /* SHOPT_KIA */
+
+/*
+ * This routine gets called when reading across a buffer boundary
+ * If lexd.nocopy is off, then current token is saved on the stack
+ */
+static void lex_advance(Sfio_t *iop, const char *buff, register int size, void *context)
+{
+ register Lex_t *lp = (Lex_t*)context;
+ register Shell_t *shp = lp->sh;
+ register Sfio_t *log= shp->funlog;
+ Stk_t *stkp = shp->stk;
+#if KSHELL
+ /* write to history file and to stderr if necessary */
+ if(iop && !sfstacked(iop))
+ {
+ if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
+ log = shp->gd->hist_ptr->histfp;
+ sfwrite(log, (void*)buff, size);
+ if(sh_isstate(SH_VERBOSE))
+ sfwrite(sfstderr, buff, size);
+ }
+#endif
+ if(lp->lexd.nocopy)
+ return;
+ if(lp->lexd.dolparen && lp->lexd.docword && lp->lexd.docend)
+ {
+ int n = size - (lp->lexd.docend-(char*)buff);
+ sfwrite(shp->strbuf,lp->lexd.docend,n);
+ lp->lexd.docextra += n;
+ if(sffileno(iop)>=0)
+ lp->lexd.docend = sfsetbuf(iop,(Void_t*)iop,0);
+ else
+ lp->lexd.docend = fcfirst();
+ }
+ if(lp->lexd.first)
+ {
+ size -= (lp->lexd.first-(char*)buff);
+ buff = lp->lexd.first;
+ if(!lp->lexd.noarg)
+ lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
+#if SHOPT_KIA
+ lp->lexd.kiaoff += ARGVAL;
+#endif /* SHOPT_KIA */
+ }
+ if(size>0 && (lp->arg||lp->lexd.noarg))
+ {
+ sfwrite(stkp,buff,size);
+ lp->lexd.first = 0;
+ }
+}
+
+/*
+ * fill up another input buffer
+ * preserves lexical state
+ */
+static int lexfill(Lex_t *lp)
+{
+ register int c;
+ Lex_t savelex;
+ struct argnod *ap;
+ int aok,docextra;
+ savelex = *lp;
+ ap = lp->arg;
+ c = fcfill();
+ if(ap)
+ lp->arg = ap;
+ docextra = lp->lexd.docextra;
+ lp->lex = savelex.lex;
+ lp->lexd = savelex.lexd;
+ if(fcfile() || c)
+ lp->lexd.first = 0;
+ aok= lp->aliasok;
+ ap = lp->arg;
+ memcpy(lp, &savelex, offsetof(Lex_t,lexd));
+ lp->arg = ap;
+ lp->aliasok = aok;
+ if(lp->lexd.docword && docextra)
+ {
+ lp->lexd.docextra = docextra;
+ lp->lexd.docend = fcseek(0)-1;
+ }
+ return(c);
+}
+
+/*
+ * mode=1 for reinitialization
+ */
+Lex_t *sh_lexopen(Lex_t *lp, Shell_t *sp, int mode)
+{
+ if(!lp)
+ {
+ lp = (Lex_t*)newof(0,Lex_t,1,0);
+ lp->sh = sp;
+ }
+ fcnotify(lex_advance,lp);
+ lp->lex.intest = lp->lex.incase = lp->lex.skipword = lp->lexd.warn = 0;
+ lp->comp_assign = 0;
+ lp->lex.reservok = 1;
+ if(!sh_isoption(SH_DICTIONARY) && sh_isoption(SH_NOEXEC))
+ lp->lexd.warn=1;
+ if(!mode)
+ {
+ lp->lexd.noarg = lp->lexd.level= lp->lexd.dolparen = lp->lexd.balance = 0;
+ lp->lexd.nocopy = lp->lexd.docword = lp->lexd.nest = lp->lexd.paren = 0;
+ lp->lexd.lex_state = lp->lexd.lastc=0;
+ lp->lexd.docend = 0;
+ lp->lexd.nested_tilde = 0;
+ }
+ lp->comsub = 0;
+ return(lp);
+}
+
+#ifdef DBUG
+extern int lextoken(Lex_t*);
+int sh_lex(Lex_t *lp)
+{
+ Shell_t *shp = lp->sh;
+ register int flag;
+ char *quoted, *macro, *split, *expand;
+ char tokstr[3];
+ register int tok = lextoken(lp);
+ quoted = macro = split = expand = "";
+ if(tok==0 && (flag=lp->arg->argflag))
+ {
+ if(flag&ARG_MAC)
+ macro = "macro:";
+ if(flag&ARG_EXP)
+ expand = "expand:";
+ if(flag&ARG_QUOTED)
+ quoted = "quoted:";
+ }
+ sfprintf(sfstderr,"%d: line %d: %o:%s%s%s%s %s\n",getpid(),shp->inlineno,tok,quoted,
+ macro, split, expand, fmttoken(lp,tok,tokstr));
+ return(tok);
+}
+#define sh_lex lextoken
+#endif
+
+/*
+ * Get the next word and put it on the top of the stak
+ * A pointer to the current word is stored in lp->arg
+ * Returns the token type
+ */
+int sh_lex(Lex_t* lp)
+{
+ register Shell_t *shp = lp->sh;
+ register const char *state;
+ register int n, c, mode=ST_BEGIN, wordflags=0;
+ Stk_t *stkp = shp->stk;
+ int inlevel=lp->lexd.level, assignment=0, ingrave=0;
+ Sfio_t *sp;
+#if SHOPT_MULTIBYTE
+ LEN=1;
+#endif /* SHOPT_MULTIBYTE */
+ if(lp->lexd.paren)
+ {
+ lp->lexd.paren = 0;
+ return(lp->token=LPAREN);
+ }
+ if(lp->lex.incase)
+ lp->assignok = 0;
+ else
+ lp->assignok |= lp->lex.reservok;
+ if(lp->comp_assign==2)
+ lp->comp_assign = lp->lex.reservok = 0;
+ lp->lexd.arith = (lp->lexd.nest==1);
+ if(lp->lexd.nest)
+ {
+ pushlevel(lp,lp->lexd.nest,ST_NONE);
+ lp->lexd.nest = 0;
+ mode = lp->lexd.lex_state;
+ }
+ else if(lp->lexd.docword)
+ {
+ if(fcgetc(c)=='-' || c=='#')
+ {
+ lp->lexd.docword++;
+ lp->digits=(c=='#'?3:1);
+ }
+ else if(c=='<')
+ {
+ lp->digits=2;
+ lp->lexd.docword=0;
+ }
+ else if(c>0)
+ fcseek(-LEN);
+ }
+ if(!lp->lexd.dolparen)
+ {
+ lp->arg = 0;
+ if(mode!=ST_BEGIN)
+ lp->lexd.first = fcseek(0);
+ else
+ lp->lexd.first = 0;
+ }
+ lp->lastline = lp->sh->inlineno;
+ if(lp->noreserv)
+ lp->lex.reservok = 0;
+ while(1)
+ {
+ /* skip over characters in the current state */
+ state = sh_lexstates[mode];
+ while((n=STATE(state,c))==0);
+ switch(n)
+ {
+ case S_BREAK:
+ fcseek(-LEN);
+ goto breakloop;
+ case S_EOF:
+ sp = fcfile();
+ if((n=lexfill(lp)) > 0)
+ {
+ fcseek(-1);
+ continue;
+ }
+ /* check for zero byte in file */
+ if(n==0 && fcfile())
+ {
+ if(shp->readscript)
+ {
+ char *cp = error_info.id;
+ errno = ENOEXEC;
+ error_info.id = shp->readscript;
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,cp);
+ }
+ else
+ {
+ lp->token = -1;
+ sh_syntax(lp);
+ }
+ }
+ /* end-of-file */
+ if(mode==ST_BEGIN)
+ return(lp->token=EOFSYM);
+ if(mode >ST_NORM && lp->lexd.level>0)
+ {
+ switch(c=endchar(lp))
+ {
+ case '$':
+ if(mode==ST_LIT)
+ {
+ c = '\'';
+ break;
+ }
+ mode = oldmode(lp);
+ poplevel(lp);
+ continue;
+ case RBRACT:
+ c = LBRACT;
+ break;
+ case 1: /* for ((...)) */
+ case RPAREN:
+ c = LPAREN;
+ break;
+ default:
+ c = LBRACE;
+ break;
+ case '"': case '`': case '\'':
+ lp->lexd.balance = c;
+ break;
+ }
+ if(sp && !(sfset(sp,0,0)&SF_STRING))
+ {
+ lp->lasttok = c;
+ lp->token = EOFSYM;
+ sh_syntax(lp);
+ }
+ lp->lexd.balance = c;
+ }
+ goto breakloop;
+ case S_COM:
+ /* skip one or more comment line(s) */
+ lp->lex.reservok = !lp->lex.intest;
+ if((n=lp->lexd.nocopy) && lp->lexd.dolparen)
+ lp->lexd.nocopy--;
+ do
+ {
+ while(fcgetc(c)>0 && c!='\n');
+ if(c<=0 || lp->heredoc)
+ {
+ shp->inlineno++;
+ break;
+ }
+ while(shp->inlineno++,fcpeek(0)=='\n')
+ fcseek(1);
+ while(state[c=fcpeek(0)]==0)
+ fcseek(1);
+ }
+ while(c=='#');
+ lp->lexd.nocopy = n;
+ if(c<0)
+ return(lp->token=EOFSYM);
+ n = S_NLTOK;
+ shp->inlineno--;
+ /* FALL THRU */
+ case S_NLTOK:
+ /* check for here-document */
+ if(lp->heredoc)
+ {
+ if(!lp->lexd.dolparen)
+ lp->lexd.nocopy++;
+ c = shp->inlineno;
+ if(here_copy(lp,lp->heredoc)<=0 && lp->lasttok)
+ {
+ lp->lasttok = IODOCSYM;
+ lp->token = EOFSYM;
+ lp->lastline = c;
+ sh_syntax(lp);
+ }
+ if(!lp->lexd.dolparen)
+ lp->lexd.nocopy--;
+ lp->heredoc = 0;
+ }
+ lp->lex.reservok = !lp->lex.intest;
+ lp->lex.skipword = 0;
+ /* FALL THRU */
+ case S_NL:
+ /* skip over new-lines */
+ lp->lex.last_quote = 0;
+ while(shp->inlineno++,fcget()=='\n');
+ fcseek(-LEN);
+ if(n==S_NLTOK)
+ {
+ lp->comp_assign = 0;
+ return(lp->token='\n');
+ }
+ case S_BLNK:
+ if(lp->lex.incase<=TEST_RE)
+ continue;
+ /* implicit RPAREN for =~ test operator */
+ if(inlevel+1==lp->lexd.level)
+ {
+ if(lp->lex.intest)
+ fcseek(-LEN);
+ c = RPAREN;
+ goto do_pop;
+ }
+ continue;
+ case S_OP:
+ /* return operator token */
+ if(c=='<' || c=='>')
+ {
+ if(lp->lex.testop2)
+ lp->lex.testop2 = 0;
+ else
+ {
+ lp->digits = (c=='>');
+ lp->lex.skipword = 1;
+ lp->aliasok = lp->lex.reservok;
+ lp->lex.reservok = 0;
+ }
+ }
+ else
+ {
+ lp->lex.reservok = !lp->lex.intest;
+ if(c==RPAREN)
+ {
+ if(!lp->lexd.dolparen)
+ lp->lex.incase = 0;
+ return(lp->token=c);
+ }
+ lp->lex.testop1 = lp->lex.intest;
+ }
+ if(fcgetc(n)>0)
+ fcseek(-LEN);
+ if(state[n]==S_OP || n=='#')
+ {
+ if(n==c)
+ {
+ if(c=='<')
+ lp->lexd.docword=1;
+ else if(n==LPAREN)
+ {
+ if(lp->lex.intest)
+ return(c);
+ lp->lexd.nest=1;
+ lp->lastline = shp->inlineno;
+ lp->lexd.lex_state = ST_NESTED;
+ fcseek(1);
+ return(sh_lex(lp));
+ }
+ c |= SYMREP;
+ }
+ else if(c=='(' || c==')')
+ return(lp->token=c);
+ else if(c=='&')
+ {
+ if(!sh_isoption(SH_POSIX) && n=='>' && (sh_isoption(SH_BASH) || sh_isstate(SH_PROFILE)))
+ {
+ if(!sh_isoption(SH_BASH) && !lp->nonstandard)
+ {
+ lp->nonstandard = 1;
+ errormsg(SH_DICT,ERROR_warn(0),e_lexnonstandard,shp->inlineno);
+ }
+ lp->digits = -1;
+ c = '>';
+ }
+ else if(n=='|')
+ c |= SYMPIPE;
+ else
+ n = 0;
+ }
+ else if(n=='&')
+ c |= SYMAMP;
+ else if(c!='<' && c!='>')
+ n = 0;
+ else if(n==LPAREN)
+ {
+ c |= SYMLPAR;
+ lp->lex.reservok = 1;
+ lp->lex.skipword = 0;
+ }
+ else if(n=='|')
+ c |= SYMPIPE;
+ else if(c=='<' && n=='>')
+ {
+ lp->digits = 1;
+ c = IORDWRSYM;
+ fcgetc(n);
+ if(fcgetc(n)==';')
+ {
+ lp->token = c = IORDWRSYMT;
+ if(lp->inexec)
+ sh_syntax(lp);
+ }
+ else if(n>0)
+ fcseek(-LEN);
+ n= 0;
+ }
+ else if(n=='#' && (c=='<'||c=='>'))
+ c |= SYMSHARP;
+ else if(n==';' && c=='>')
+ {
+ c |= SYMSEMI;
+ if(lp->inexec)
+ {
+ lp->token = c;
+ sh_syntax(lp);
+ }
+ }
+ else
+ n = 0;
+ if(n)
+ {
+ fcseek(1);
+ lp->lex.incase = (c==BREAKCASESYM || c==FALLTHRUSYM);
+ }
+ else
+ {
+ if(lp->lexd.warn && (n=fcpeek(0))!=RPAREN && n!=' ' && n!='\t')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexspace,shp->inlineno,c,n);
+ }
+ }
+ if(c==LPAREN && lp->comp_assign && !lp->lex.intest && !lp->lex.incase)
+ lp->comp_assign = 2;
+ else
+ lp->comp_assign = 0;
+ return(lp->token=c);
+ case S_ESC:
+ /* check for \<new-line> */
+ fcgetc(n);
+ c=2;
+#if SHOPT_CRNL
+ if(n=='\r')
+ {
+ if(fcgetc(n)=='\n')
+ c=3;
+ else
+ {
+ n='\r';
+ fcseek(-LEN);
+ }
+ }
+#endif /* SHOPT_CRNL */
+ if(n=='\n')
+ {
+ Sfio_t *sp;
+ struct argnod *ap;
+ shp->inlineno++;
+ /* synchronize */
+ if(!(sp=fcfile()))
+ state=fcseek(0);
+ fcclose();
+ ap = lp->arg;
+ if(sp)
+ fcfopen(sp);
+ else
+ fcsopen((char*)state);
+ /* remove \new-line */
+ n = stktell(stkp)-c;
+ stkseek(stkp,n);
+ lp->arg = ap;
+ if(n<=ARGVAL)
+ {
+ mode = 0;
+ lp->lexd.first = 0;
+ }
+ continue;
+ }
+ wordflags |= ARG_QUOTED;
+ if(mode==ST_DOL)
+ goto err;
+#ifndef STR_MAXIMAL
+ else if(mode==ST_NESTED && lp->lexd.warn &&
+ endchar(lp)==RBRACE &&
+ sh_lexstates[ST_DOL][n]==S_DIG
+ )
+ errormsg(SH_DICT,ERROR_warn(0),e_lexfuture,shp->inlineno,n);
+#endif /* STR_MAXIMAL */
+ break;
+ case S_NAME:
+ if(!lp->lex.skipword)
+ lp->lex.reservok *= 2;
+ /* FALL THRU */
+ case S_TILDE:
+ if(c=='~' && mode==ST_NESTED)
+ {
+ if(endchar(lp)==RBRACE)
+ {
+ lp->lexd.nested_tilde++;
+ goto tilde;
+ }
+ continue;
+ }
+ case S_RES:
+ if(!lp->lexd.dolparen)
+ lp->lexd.first = fcseek(0)-LEN;
+ else if(lp->lexd.docword)
+ lp->lexd.docend = fcseek(0)-LEN;
+ mode = ST_NAME;
+ if(c=='.')
+ fcseek(-LEN);
+ if(n!=S_TILDE)
+ continue;
+ tilde:
+ fcgetc(n);
+ if(n>0)
+ {
+ if(c=='~' && n==LPAREN)
+ {
+ if(lp->lexd.nested_tilde)
+ lp->lexd.nested_tilde++;
+ else if(lp->lex.incase)
+ lp->lex.incase = TEST_RE;
+ }
+ fcseek(-LEN);
+ if(lp->lexd.nested_tilde)
+ {
+ lp->lexd.nested_tilde--;
+ continue;
+ }
+ }
+ if(n==LPAREN)
+ goto epat;
+ wordflags = ARG_MAC;
+ mode = ST_NORM;
+ continue;
+ case S_REG:
+ if(mode==ST_BEGIN)
+ {
+ do_reg:
+ /* skip new-line joining */
+ if(c=='\\' && fcpeek(0)=='\n')
+ {
+ shp->inlineno++;
+ fcseek(1);
+ continue;
+ }
+ fcseek(-LEN);
+ if(!lp->lexd.dolparen)
+ lp->lexd.first = fcseek(0);
+ else if(lp->lexd.docword)
+ lp->lexd.docend = fcseek(0);
+ if(c=='[' && lp->assignok>=SH_ASSIGN)
+ {
+ mode = ST_NAME;
+ continue;
+ }
+ }
+ mode = ST_NORM;
+ continue;
+ case S_LIT:
+ if(oldmode(lp)==ST_NONE && !lp->lexd.noarg) /* in ((...)) */
+ {
+ if((c=fcpeek(0))==LPAREN || c==RPAREN || c=='$' || c==LBRACE || c==RBRACE || c=='[' || c==']')
+ {
+ if(fcpeek(1)=='\'')
+ fcseek(2);
+ }
+ continue;
+ }
+ wordflags |= ARG_QUOTED;
+ if(mode==ST_DOL)
+ {
+ if(endchar(lp)!='$')
+ goto err;
+ if(oldmode(lp)==ST_QUOTE) /* $' within "" or `` */
+ {
+ if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
+ mode = ST_LIT;
+ }
+ }
+ if(mode!=ST_LIT)
+ {
+ if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline && fcpeek(-2)!='$')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
+ lp->lex.last_quote = 0;
+ lp->lastline = shp->inlineno;
+ if(mode!=ST_DOL)
+ pushlevel(lp,'\'',mode);
+ mode = ST_LIT;
+ continue;
+ }
+ /* check for multi-line single-quoted string */
+ else if(shp->inlineno > lp->lastline)
+ lp->lex.last_quote = '\'';
+ mode = oldmode(lp);
+ poplevel(lp);
+ break;
+ case S_ESC2:
+ /* \ inside '' */
+ if(endchar(lp)=='$')
+ {
+ fcgetc(n);
+ if(n=='\n')
+ shp->inlineno++;
+ }
+ continue;
+ case S_GRAVE:
+ if(lp->lexd.warn && (mode!=ST_QUOTE || endchar(lp)!='`'))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete1,shp->inlineno);
+ wordflags |=(ARG_MAC|ARG_EXP);
+ if(mode==ST_QUOTE)
+ ingrave = !ingrave;
+ /* FALL THRU */
+ case S_QUOTE:
+ if(oldmode(lp)==ST_NONE && lp->lexd.arith) /* in ((...)) */
+ {
+ if(n!=S_GRAVE || fcpeek(0)=='\'')
+ continue;
+ }
+ if(n==S_QUOTE)
+ wordflags |=ARG_QUOTED;
+ if(mode!=ST_QUOTE)
+ {
+ if(c!='"' || mode!=ST_QNEST)
+ {
+ if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
+ lp->lex.last_quote=0;
+ lp->lastline = shp->inlineno;
+ pushlevel(lp,c,mode);
+ }
+ ingrave ^= (c=='`');
+ mode = ST_QUOTE;
+ continue;
+ }
+ else if((n=endchar(lp))==c)
+ {
+ if(shp->inlineno > lp->lastline)
+ lp->lex.last_quote = c;
+ mode = oldmode(lp);
+ poplevel(lp);
+ }
+ else if(c=='"' && n==RBRACE)
+ mode = ST_QNEST;
+ break;
+ case S_DOL:
+ /* don't check syntax inside `` */
+ if(mode==ST_QUOTE && ingrave)
+ continue;
+#if SHOPT_KIA
+ if(lp->lexd.first)
+ lp->lexd.kiaoff = fcseek(0)-lp->lexd.first;
+ else
+ lp->lexd.kiaoff = stktell(stkp)+fcseek(0)-fcfirst();
+#endif /* SHOPT_KIA */
+ pushlevel(lp,'$',mode);
+ mode = ST_DOL;
+ continue;
+ case S_PAR:
+ do_comsub:
+ wordflags |= ARG_MAC;
+ mode = oldmode(lp);
+ poplevel(lp);
+ fcseek(-LEN);
+ wordflags |= comsub(lp,c);
+ continue;
+ case S_RBRA:
+ if((n=endchar(lp)) == '$')
+ goto err;
+ if(mode!=ST_QUOTE || n==RBRACE)
+ {
+ mode = oldmode(lp);
+ poplevel(lp);
+ }
+ break;
+ case S_EDOL:
+ /* end $identifier */
+#if SHOPT_KIA
+ if(lp->kiafile)
+ refvar(lp,0);
+#endif /* SHOPT_KIA */
+ if(lp->lexd.warn && c==LBRACT && !lp->lex.intest && !lp->lexd.arith && oldmode(lp)!= ST_NESTED)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexusebrace,shp->inlineno);
+ fcseek(-LEN);
+ mode = oldmode(lp);
+ poplevel(lp);
+ break;
+ case S_DOT:
+ /* make sure next character is alpha */
+ if(fcgetc(n)>0)
+ {
+ if(n=='.')
+ fcgetc(n);
+ if(n>0)
+ fcseek(-LEN);
+ }
+ if(isaletter(n) || n==LBRACT)
+ continue;
+ if(mode==ST_NAME)
+ {
+ if(n=='=')
+ continue;
+ break;
+ }
+ else if(n==RBRACE)
+ continue;
+ if(isastchar(n))
+ continue;
+ goto err;
+ case S_SPC1:
+ wordflags |= ARG_MAC;
+ if(endchar(lp)==RBRACE)
+ {
+ setchar(lp,c);
+ continue;
+ }
+ /* FALL THRU */
+ case S_ALP:
+ if(c=='.' && endchar(lp)=='$')
+ goto err;
+ case S_SPC2:
+ case S_DIG:
+ wordflags |= ARG_MAC;
+ switch(endchar(lp))
+ {
+ case '$':
+ if(n==S_ALP) /* $identifier */
+ mode = ST_DOLNAME;
+ else
+ {
+ mode = oldmode(lp);
+ poplevel(lp);
+ }
+ break;
+#if SHOPT_TYPEDEF
+ case '@':
+#endif /* SHOPT_TYPEDEF */
+ case '!':
+ if(n!=S_ALP)
+ goto dolerr;
+ case '#':
+ if(c=='#')
+ n = S_ALP;
+ case RBRACE:
+ if(n==S_ALP)
+ {
+ setchar(lp,RBRACE);
+ if(c=='.')
+ fcseek(-LEN);
+ mode = ST_BRACE;
+ }
+ else
+ {
+ if(fcgetc(c)>0)
+ fcseek(-LEN);
+ if(state[c]==S_ALP)
+ goto err;
+ if(n==S_DIG)
+ setchar(lp,'0');
+ else
+ setchar(lp,'!');
+ }
+ break;
+ case '0':
+ if(n==S_DIG)
+ break;
+ default:
+ goto dolerr;
+ }
+ break;
+ dolerr:
+ case S_ERR:
+ if((n=endchar(lp)) == '$')
+ goto err;
+ if(c=='*' || (n=sh_lexstates[ST_BRACE][c])!=S_MOD1 && n!=S_MOD2)
+ {
+ /* see whether inside `...` */
+ mode = oldmode(lp);
+ poplevel(lp);
+ if((n = endchar(lp)) != '`')
+ goto err;
+ pushlevel(lp,RBRACE,mode);
+ }
+ else
+ setchar(lp,RBRACE);
+ mode = ST_NESTED;
+ continue;
+ case S_MOD1:
+ if(oldmode(lp)==ST_QUOTE || oldmode(lp)==ST_NONE)
+ {
+ /* allow ' inside "${...}" */
+ if(c==':' && fcgetc(n)>0)
+ {
+ n = state[n];
+ fcseek(-LEN);
+ }
+ if(n==S_MOD1)
+ {
+ mode = ST_QUOTE;
+ continue;
+ }
+ }
+ /* FALL THRU */
+ case S_MOD2:
+#if SHOPT_KIA
+ if(lp->kiafile)
+ refvar(lp,1);
+#endif /* SHOPT_KIA */
+ if(c!=':' && fcgetc(n)>0)
+ {
+ if(n!=c)
+ c = 0;
+ if(!c || (fcgetc(n)>0))
+ {
+ fcseek(-LEN);
+ if(n==LPAREN)
+ {
+ if(c!='%')
+ {
+ lp->token = n;
+ sh_syntax(lp);
+ }
+ else if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexquote,shp->inlineno,'%');
+ }
+ }
+ }
+ lp->lex.nestedbrace = 0;
+ mode = ST_NESTED;
+ continue;
+ case S_LBRA:
+ if((c=endchar(lp)) == '$')
+ {
+ if(fcgetc(c)>0)
+ fcseek(-LEN);
+ setchar(lp,RBRACE);
+ if(state[c]!=S_ERR && c!=RBRACE)
+ continue;
+ if((n=sh_lexstates[ST_BEGIN][c])==0 || n==S_OP || n==S_NLTOK)
+ {
+ c = LBRACE;
+ goto do_comsub;
+ }
+ }
+ err:
+ if(iswalpha(c))
+ continue;
+ n = endchar(lp);
+ mode = oldmode(lp);
+ poplevel(lp);
+ if(n!='$')
+ {
+ lp->token = c;
+ sh_syntax(lp);
+ }
+ else
+ {
+ if(lp->lexd.warn && c!='/' && sh_lexstates[ST_NORM][c]!=S_BREAK && (c!='"' || mode==ST_QUOTE))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
+ else if(c=='"' && mode!=ST_QUOTE && !ingrave)
+ wordflags |= ARG_MESSAGE;
+ fcseek(-LEN);
+ }
+ continue;
+ case S_META:
+ if(lp->lexd.warn && endchar(lp)==RBRACE && !lp->lexd.nested_tilde)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
+ continue;
+ case S_PUSH:
+ pushlevel(lp,RPAREN,mode);
+ mode = ST_NESTED;
+ continue;
+ case S_POP:
+ do_pop:
+ if(c==RBRACE && mode==ST_NESTED && lp->lex.nestedbrace)
+ {
+ lp->lex.nestedbrace--;
+ continue;
+ }
+ if(lp->lexd.level <= inlevel)
+ break;
+ if(lp->lexd.level==inlevel+1 && lp->lex.incase>=TEST_RE && !lp->lex.intest)
+ {
+ fcseek(-LEN);
+ goto breakloop;
+ }
+ n = endchar(lp);
+ if(c==RBRACT && !(n==RBRACT || n==RPAREN))
+ continue;
+ if((c==RBRACE||c==RPAREN) && n==RPAREN)
+ {
+ if(fcgetc(n)==LPAREN)
+ {
+ if(c!=RPAREN)
+ fcseek(-LEN);
+ continue;
+ }
+ if(n>0)
+ fcseek(-LEN);
+ n = RPAREN;
+ }
+ if(c==RBRACE)
+ lp->lexd.nested_tilde = 0;
+ if(c==';' && n!=';')
+ {
+ if(lp->lexd.warn && n==RBRACE)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
+ continue;
+ }
+ if(mode==ST_QNEST)
+ {
+ if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexescape,shp->inlineno,c);
+ continue;
+ }
+ mode = oldmode(lp);
+ poplevel(lp);
+ /* quotes in subscript need expansion */
+ if(mode==ST_NAME && (wordflags&ARG_QUOTED))
+ wordflags |= ARG_MAC;
+ /* check for ((...)) */
+ if(n==1 && c==RPAREN)
+ {
+ if(fcgetc(n)==RPAREN)
+ {
+ if(mode==ST_NONE && !lp->lexd.dolparen)
+ goto breakloop;
+ lp->lex.reservok = 1;
+ lp->lex.skipword = 0;
+ return(lp->token=EXPRSYM);
+ }
+ /* backward compatibility */
+ {
+ if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno);
+ if(!(state=lp->lexd.first))
+ state = fcfirst();
+ else
+ {
+ n = state-fcseek(0);
+ fcseek(n);
+ }
+ lp->lexd.paren = 1;
+ }
+ return(lp->token=LPAREN);
+ }
+ if(mode==ST_NONE)
+ return(0);
+ if(c!=n)
+ {
+ lp->token = c;
+ sh_syntax(lp);
+ }
+ if(c==RBRACE && (mode==ST_NAME||mode==ST_NORM))
+ goto epat;
+ continue;
+ case S_EQ:
+ assignment = lp->assignok;
+ /* FALL THRU */
+ case S_COLON:
+ if(assignment)
+ {
+ if(fcgetc(c)=='~')
+ wordflags |= ARG_MAC;
+ else if(c!=LPAREN && assignment==SH_COMPASSIGN)
+ assignment = 0;
+ if(c!=EOF)
+ fcseek(-LEN);
+ }
+ break;
+ case S_LABEL:
+ if(lp->lex.reservok && !lp->lex.incase)
+ {
+ c = fcget();
+ fcseek(-LEN);
+ if(state[c]==S_BREAK)
+ {
+ assignment = -1;
+ goto breakloop;
+ }
+ }
+ break;
+ case S_BRACT:
+ /* check for possible subscript */
+ if((n=endchar(lp))==RBRACT || n==RPAREN ||
+ (mode==ST_BRACE) ||
+ (oldmode(lp)==ST_NONE) ||
+ (mode==ST_NAME && (lp->assignok||lp->lexd.level)))
+ {
+ if(mode==ST_NAME)
+ {
+ fcgetc(n);
+ if(n>0)
+ {
+ if(n==']')
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1, shp->inlineno, "[]", "empty subscript");
+ fcseek(-LEN);
+ }
+ }
+ pushlevel(lp,RBRACT,mode);
+ wordflags |= ARG_QUOTED;
+ mode = ST_NESTED;
+ continue;
+ }
+ wordflags |= ARG_EXP;
+ break;
+ case S_BRACE:
+ {
+ int isfirst;
+ if(lp->lexd.dolparen)
+ {
+ if(mode==ST_BEGIN && (lp->lex.reservok||lp->comsub))
+ {
+ if(lp->comsub)
+ return(lp->token=c);
+ fcgetc(n);
+ if(n>0)
+ fcseek(-LEN);
+ else
+ n = '\n';
+ if(n==RBRACT || sh_lexstates[ST_NORM][n])
+ return(lp->token=c);
+ }
+ break;
+ }
+ else if(mode==ST_NESTED && endchar(lp)==RBRACE)
+ {
+ lp->lex.nestedbrace++;
+ continue;
+ }
+ else if(mode==ST_BEGIN)
+ {
+ if(lp->comsub && c==RBRACE)
+ return(lp->token=c);
+ goto do_reg;
+ }
+ isfirst = (lp->lexd.first&&fcseek(0)==lp->lexd.first+1);
+ fcgetc(n);
+ /* check for {} */
+ if(c==LBRACE && n==RBRACE)
+ break;
+ if(n>0)
+ fcseek(-LEN);
+ else if(lp->lex.reservok)
+ break;
+ /* check for reserved word { or } */
+ if(lp->lex.reservok && state[n]==S_BREAK && isfirst)
+ break;
+ if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK
+ && !lp->lex.incase && !lp->lex.intest
+ && !lp->lex.skipword)
+ {
+ wordflags |= ARG_EXP;
+ }
+ if(c==RBRACE && n==LPAREN)
+ goto epat;
+ break;
+ }
+ case S_PAT:
+ wordflags |= ARG_EXP;
+ /* FALL THRU */
+ case S_EPAT:
+ epat:
+ if(fcgetc(n)==LPAREN && c!='[')
+ {
+ if(lp->lex.incase==TEST_RE)
+ {
+ lp->lex.incase++;
+ pushlevel(lp,RPAREN,ST_NORM);
+ mode = ST_NESTED;
+ }
+ wordflags |= ARG_EXP;
+ pushlevel(lp,RPAREN,mode);
+ mode = ST_NESTED;
+ continue;
+ }
+ if(lp->lexd.warn && c=='[' && n=='^')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexcharclass,shp->inlineno);
+ if(n>0)
+ fcseek(-LEN);
+ if(n=='=' && c=='+' && mode==ST_NAME)
+ continue;
+ break;
+ }
+ lp->comp_assign = 0;
+ if(mode==ST_NAME)
+ mode = ST_NORM;
+ else if(mode==ST_NONE)
+ return(0);
+ }
+breakloop:
+ if(lp->lexd.nocopy)
+ {
+ lp->lexd.balance = 0;
+ return(0);
+ }
+ if(lp->lexd.dolparen)
+ {
+ lp->lexd.balance = 0;
+ if(lp->lexd.docword)
+ nested_here(lp);
+ lp->lexd.message = (wordflags&ARG_MESSAGE);
+ return(lp->token=0);
+ }
+ if(!(state=lp->lexd.first))
+ state = fcfirst();
+ n = fcseek(0)-(char*)state;
+ if(!lp->arg)
+ lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
+ if(n>0)
+ sfwrite(stkp,state,n);
+ /* add balancing character if necessary */
+ if(lp->lexd.balance)
+ {
+ sfputc(stkp,lp->lexd.balance);
+ lp->lexd.balance = 0;
+ }
+ sfputc(stkp,0);
+ stkseek(stkp,stktell(stkp)-1);
+ state = stkptr(stkp,ARGVAL);
+ n = stktell(stkp)-ARGVAL;
+ lp->lexd.first=0;
+ if(n==1)
+ {
+ /* check for numbered redirection */
+ n = state[0];
+ if((c=='<' || c=='>') && isadigit(n))
+ {
+ c = sh_lex(lp);
+ lp->digits = (n-'0');
+ return(c);
+ }
+ if(n==LBRACT)
+ c = 0;
+ else if(n==RBRACE && lp->comsub)
+ return(lp->token=n);
+ else if(n=='~')
+ c = ARG_MAC;
+ else
+ c = (wordflags&ARG_EXP);
+ n = 1;
+ }
+ else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND))
+ {
+ if(!strchr(state,','))
+ {
+ stkseek(stkp,stktell(stkp)-1);
+ lp->arg = (struct argnod*)stkfreeze(stkp,1);
+ return(lp->token=IOVNAME);
+ }
+ c = wordflags;
+ }
+ else
+ c = wordflags;
+ if(assignment<0)
+ {
+ stkseek(stkp,stktell(stkp)-1);
+ lp->arg = (struct argnod*)stkfreeze(stkp,1);
+ lp->lex.reservok = 1;
+ return(lp->token=LABLSYM);
+ }
+ if(assignment || (lp->lex.intest&&!lp->lex.incase) || mode==ST_NONE)
+ c &= ~ARG_EXP;
+ if((c&ARG_EXP) && (c&ARG_QUOTED))
+ c |= ARG_MAC;
+ if(mode==ST_NONE)
+ {
+ /* eliminate trailing )) */
+ stkseek(stkp,stktell(stkp)-2);
+ }
+ if(c&ARG_MESSAGE)
+ {
+ if(sh_isoption(SH_DICTIONARY))
+ lp->arg = sh_endword(shp,2);
+ c |= ARG_MAC;
+ }
+ if(c==0 || (c&(ARG_MAC|ARG_EXP|ARG_MESSAGE)))
+ {
+ lp->arg = (struct argnod*)stkfreeze(stkp,1);
+ lp->arg->argflag = (c?c:ARG_RAW);
+ }
+ else if(mode==ST_NONE)
+ lp->arg = sh_endword(shp,-1);
+ else
+ lp->arg = sh_endword(shp,0);
+ state = lp->arg->argval;
+ lp->comp_assign = assignment;
+ if(assignment)
+ lp->arg->argflag |= ARG_ASSIGN;
+ else if(!lp->lex.skipword)
+ lp->assignok = 0;
+ lp->arg->argchn.cp = 0;
+ lp->arg->argnxt.ap = 0;
+ if(mode==ST_NONE)
+ return(lp->token=EXPRSYM);
+ if(lp->lex.intest)
+ {
+ if(lp->lex.testop1)
+ {
+ lp->lex.testop1 = 0;
+ if(n==2 && state[0]=='-' && state[2]==0 &&
+ strchr(test_opchars,state[1]))
+ {
+ if(lp->lexd.warn && state[1]=='a')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete2,shp->inlineno);
+ lp->digits = state[1];
+ lp->token = TESTUNOP;
+ }
+ else if(n==1 && state[0]=='!' && state[1]==0)
+ {
+ lp->lex.testop1 = 1;
+ lp->token = '!';
+ }
+ else
+ {
+ lp->lex.testop2 = 1;
+ lp->token = 0;
+ }
+ return(lp->token);
+ }
+ lp->lex.incase = 0;
+ c = sh_lookup(state,shtab_testops);
+ switch(c)
+ {
+ case TEST_END:
+ lp->lex.testop2 = lp->lex.intest = 0;
+ lp->lex.reservok = 1;
+ lp->token = ETESTSYM;
+ return(lp->token);
+
+ case TEST_SEQ:
+ if(lp->lexd.warn && state[1]==0)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete3,shp->inlineno);
+ /* FALL THRU */
+ default:
+ if(lp->lex.testop2)
+ {
+ if(lp->lexd.warn && (c&TEST_ARITH))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state);
+ if(c&TEST_PATTERN)
+ lp->lex.incase = 1;
+ else if(c==TEST_REP)
+ lp->lex.incase = TEST_RE;
+ lp->lex.testop2 = 0;
+ lp->digits = c;
+ lp->token = TESTBINOP;
+ return(lp->token);
+ }
+
+ case TEST_OR: case TEST_AND:
+ case 0:
+ return(lp->token=0);
+ }
+ }
+ if(lp->lex.reservok /* && !lp->lex.incase*/ && n<=2)
+ {
+ /* check for {, }, ! */
+ c = state[0];
+ if(n==1 && (c=='{' || c=='}' || c=='!'))
+ {
+ if(lp->lexd.warn && c=='{' && lp->lex.incase==2)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno);
+ if(lp->lex.incase==1 && c==RBRACE)
+ lp->lex.incase = 0;
+ return(lp->token=c);
+ }
+ else if(!lp->lex.incase && c==LBRACT && state[1]==LBRACT)
+ {
+ lp->lex.intest = lp->lex.testop1 = 1;
+ lp->lex.testop2 = lp->lex.reservok = 0;
+ return(lp->token=BTESTSYM);
+ }
+ }
+ c = 0;
+ if(!lp->lex.skipword)
+ {
+ if(n>1 && lp->lex.reservok==1 && mode==ST_NAME &&
+ (c=sh_lookup(state,shtab_reserved)))
+ {
+ if(lp->lex.incase)
+ {
+ if(lp->lex.incase >1)
+ lp->lex.incase = 1;
+ else if(c==ESACSYM)
+ lp->lex.incase = 0;
+ else
+ c = 0;
+ }
+ else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM)
+ {
+ lp->lex.skipword = 1;
+ lp->lex.incase = 2*(c==CASESYM);
+ }
+ else
+ lp->lex.skipword = 0;
+ if(c==INSYM)
+ lp->lex.reservok = 0;
+ else if(c==TIMESYM)
+ {
+ /* yech - POSIX requires time -p */
+ while(fcgetc(n)==' ' || n=='\t');
+ if(n>0)
+ fcseek(-LEN);
+ if(n=='-')
+ c=0;
+ }
+ return(lp->token=c);
+ }
+ if(!(wordflags&ARG_QUOTED) && (lp->lex.reservok||lp->aliasok))
+ {
+ /* check for aliases */
+ Namval_t* np;
+ if(!lp->lex.incase && !assignment && fcpeek(0)!=LPAREN &&
+ (np=nv_search(state,shp->alias_tree,HASH_SCOPE))
+ && !nv_isattr(np,NV_NOEXPAND)
+#if KSHELL
+ && (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE))
+#endif /* KSHELL */
+ && (state=nv_getval(np)))
+ {
+ setupalias(lp,state,np);
+ nv_onattr(np,NV_NOEXPAND);
+ lp->lex.reservok = 1;
+ lp->assignok |= lp->lex.reservok;
+ return(sh_lex(lp));
+ }
+ }
+ lp->lex.reservok = 0;
+ }
+ lp->lex.skipword = lp->lexd.docword = 0;
+ return(lp->token=c);
+}
+
+/*
+ * read to end of command substitution
+ */
+static int comsub(register Lex_t *lp, int endtok)
+{
+ register int n,c,count=1;
+ register int line=lp->sh->inlineno;
+ char *first,*cp=fcseek(0),word[5];
+ int off, messages=0, assignok=lp->assignok, csub;
+ struct lexstate save;
+ save = lp->lex;
+ csub = lp->comsub;
+ sh_lexopen(lp,lp->sh,1);
+ lp->lexd.dolparen++;
+ lp->lex.incase=0;
+ pushlevel(lp,0,0);
+ lp->comsub = (endtok==LBRACE);
+ if(first=lp->lexd.first)
+ off = cp-first;
+ else
+ off = cp-fcfirst();
+ if(off<0)
+ c=*cp, *cp=0;
+ n = sh_lex(lp);
+ if(off<0)
+ *cp = c;
+ if(n==endtok || off<0)
+ {
+ if(endtok==LPAREN && lp->lexd.paren)
+ {
+
+ if(first==lp->lexd.first)
+ {
+ n = cp+1-(char*)fcseek(0);
+ fcseek(n);
+ }
+ count++;
+ lp->lexd.paren = 0;
+ fcgetc(c);
+ }
+ while(1)
+ {
+ /* look for case and esac */
+ n=0;
+ while(1)
+ {
+ fcgetc(c);
+ /* skip leading white space */
+ if(n==0 && !sh_lexstates[ST_BEGIN][c])
+ continue;
+ if(n==4)
+ break;
+ if(sh_lexstates[ST_NAME][c])
+ goto skip;
+ word[n++] = c;
+ }
+ if(sh_lexstates[ST_NAME][c]==S_BREAK)
+ {
+ if(memcmp(word,"case",4)==0)
+ lp->lex.incase=1;
+ else if(memcmp(word,"esac",4)==0)
+ lp->lex.incase=0;
+ }
+ skip:
+ if(c && (c!='#' || n==0))
+ fcseek(-LEN);
+ if(c==RBRACE && lp->lex.incase)
+ lp->lex.incase=0;
+ c=sh_lex(lp);
+ switch(c)
+ {
+ case LBRACE:
+ if(endtok==LBRACE && !lp->lex.incase)
+ {
+ lp->comsub = 0;
+ count++;
+ }
+ break;
+ case RBRACE:
+ rbrace:
+ if(endtok==LBRACE && --count<=0)
+ goto done;
+ if(count==1)
+ lp->comsub = endtok==LBRACE;
+ break;
+ case IPROCSYM: case OPROCSYM:
+ case LPAREN:
+ if(endtok==LPAREN && !lp->lex.incase)
+ count++;
+ break;
+ case RPAREN:
+ if(lp->lex.incase)
+ lp->lex.incase=0;
+ else if(endtok==LPAREN && --count<=0)
+ goto done;
+ break;
+ case EOFSYM:
+ lp->lastline = line;
+ lp->lasttok = endtok;
+ sh_syntax(lp);
+ case IOSEEKSYM:
+ if(fcgetc(c)!='#' && c>0)
+ fcseek(-LEN);
+ break;
+ case IODOCSYM:
+ lp->lexd.docextra = 0;
+ sh_lex(lp);
+ break;
+ case 0:
+ lp->lex.reservok = 0;
+ messages |= lp->lexd.message;
+ break;
+ case ';':
+ do
+ fcgetc(c);
+ while(!sh_lexstates[ST_BEGIN][c]);
+ if(c==RBRACE && endtok==LBRACE)
+ goto rbrace;
+ if(c>0)
+ fcseek(-LEN);
+ /* fall through*/
+ default:
+ lp->lex.reservok = 1;
+ }
+ }
+ }
+done:
+ poplevel(lp);
+ lp->comsub = csub;
+ lp->lastline = line;
+ lp->lexd.dolparen--;
+ lp->lex = save;
+ lp->assignok = (endchar(lp)==RBRACT?assignok:0);
+ if(lp->heredoc)
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax5,lp->sh->inlineno,lp->heredoc->ioname);
+ return(messages);
+}
+
+/*
+ * here-doc nested in $(...)
+ * allocate ionode with delimiter filled in without disturbing stak
+ */
+static void nested_here(register Lex_t *lp)
+{
+ register struct ionod *iop;
+ register int n=0,offset;
+ struct argnod *arg = lp->arg;
+ Stk_t *stkp = lp->sh->stk;
+ char *base;
+ if(offset=stktell(stkp))
+ base = stkfreeze(stkp,0);
+ if(lp->lexd.docend)
+ n = fcseek(0)-lp->lexd.docend;
+ iop = newof(0,struct ionod,1,lp->lexd.docextra+n+ARGVAL);
+ iop->iolst = lp->heredoc;
+ stkseek(stkp,ARGVAL);
+ if(lp->lexd.docextra)
+ {
+ sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
+ sfmove(lp->sh->strbuf,stkp,lp->lexd.docextra,-1);
+ sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
+ }
+ sfwrite(stkp,lp->lexd.docend,n);
+ lp->arg = sh_endword(lp->sh,0);
+ iop->ioname = (char*)(iop+1);
+ strcpy(iop->ioname,lp->arg->argval);
+ iop->iofile = (IODOC|IORAW);
+ if(lp->lexd.docword>1)
+ iop->iofile |= IOSTRIP;
+ lp->heredoc = iop;
+ lp->arg = arg;
+ lp->lexd.docword = 0;
+ if(offset)
+ stkset(stkp,base,offset);
+ else
+ stkseek(stkp,0);
+}
+
+/*
+ * skip to <close> character
+ * if <copy> is non,zero, then the characters are copied to the stack
+ * <state> is the initial lexical state
+ */
+void sh_lexskip(Lex_t *lp,int close, register int copy, int state)
+{
+ register char *cp;
+ lp->lexd.nest = close;
+ lp->lexd.lex_state = state;
+ lp->lexd.noarg = 1;
+ if(copy)
+ fcnotify(lex_advance,lp);
+ else
+ lp->lexd.nocopy++;
+ sh_lex(lp);
+ lp->lexd.noarg = 0;
+ if(copy)
+ {
+ fcnotify(0,lp);
+ if(!(cp=lp->lexd.first))
+ cp = fcfirst();
+ if((copy = fcseek(0)-cp) > 0)
+ sfwrite(lp->sh->stk,cp,copy);
+ }
+ else
+ lp->lexd.nocopy--;
+}
+
+#if SHOPT_CRNL
+ ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n)
+ {
+ const char *cp = (const char*)buff, *next=cp, *ep = cp + n;
+ int m=0,k;
+ while(next = (const char*)memchr(next,'\r',ep-next))
+ if(*++next=='\n')
+ {
+ if(k=next-cp-1)
+ {
+ if((k=sfwrite(sp,cp,k)) < 0)
+ return(m>0?m:-1);
+ m += k;
+ }
+ cp = next;
+ }
+ if((k=sfwrite(sp,cp,ep-cp)) < 0)
+ return(m>0?m:-1);
+ return(m+k);
+ }
+# define sfwrite _sfwrite
+#endif /* SHOPT_CRNL */
+
+/*
+ * read in here-document from script
+ * quoted here documents, and here-documents without special chars are
+ * noted with the IOQUOTE flag
+ * returns 1 for complete here-doc, 0 for EOF
+ */
+
+static int here_copy(Lex_t *lp,register struct ionod *iop)
+{
+ register const char *state;
+ register int c,n;
+ register char *bufp,*cp;
+ register Sfio_t *sp=lp->sh->heredocs, *funlog;
+ int stripcol=0,stripflg, nsave, special=0;
+ if(funlog=lp->sh->funlog)
+ {
+ if(fcfill()>0)
+ fcseek(-LEN);
+ lp->sh->funlog = 0;
+ }
+ if(iop->iolst)
+ here_copy(lp,iop->iolst);
+ iop->iooffset = sfseek(sp,(off_t)0,SEEK_END);
+ iop->iosize = 0;
+ iop->iodelim=iop->ioname;
+ /* check for and strip quoted characters in delimiter string */
+ if(stripflg=iop->iofile&IOSTRIP)
+ {
+ while(*iop->iodelim=='\t')
+ iop->iodelim++;
+ /* skip over leading tabs in document */
+ if(iop->iofile&IOLSEEK)
+ {
+ iop->iofile &= ~IOLSEEK;
+ while(fcgetc(c)=='\t' || c==' ')
+ {
+ if(c==' ')
+ stripcol++;
+ else
+ stripcol += 8 - stripcol%8;
+ }
+ }
+ else
+ while(fcgetc(c)=='\t');
+ if(c>0)
+ fcseek(-LEN);
+ }
+ if(iop->iofile&IOQUOTE)
+ state = sh_lexstates[ST_LIT];
+ else
+ state = sh_lexstates[ST_QUOTE];
+ bufp = fcseek(0);
+ n = S_NL;
+ while(1)
+ {
+ if(n!=S_NL)
+ {
+ /* skip over regular characters */
+#if SHOPT_MULTIBYTE
+ do
+ {
+ if(fcleft()< MB_LEN_MAX && mbsize(fcseek(0))<0)
+ {
+ n = S_EOF;
+ LEN = -fcleft();
+ break;
+ }
+ }
+#endif /* SHOPT_MULTIBYTE */
+
+ while((n=STATE(state,c))==0);
+ }
+ if(n==S_EOF || !(c=fcget()))
+ {
+ if(LEN < 0)
+ c = fclast()-bufp;
+ else
+ c= (fcseek(0)-1)-bufp;
+ if(!lp->lexd.dolparen && c)
+ {
+ if(n==S_ESC)
+ c--;
+ if(!lp->lexd.dolparen && (c=sfwrite(sp,bufp,c))>0)
+ iop->iosize += c;
+ }
+#if SHOPT_MULTIBYTE
+ if(LEN==0)
+ LEN=1;
+ if(LEN < 0)
+ {
+ n = LEN;
+ c = fcmbget(&LEN);
+ LEN += n;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ c = lexfill(lp);
+ if(c<0)
+ break;
+ if(n==S_ESC)
+ {
+#if SHOPT_CRNL
+ if(c=='\r' && (c=fcget())!=NL)
+ fcseek(-LEN);
+#endif /* SHOPT_CRNL */
+ if(c==NL)
+ fcseek(1);
+ else if(!lp->lexd.dolparen)
+ {
+ iop->iosize++;
+ sfputc(sp,'\\');
+ }
+ }
+ bufp = fcseek(-LEN);
+ }
+ else
+ fcseek(-LEN);
+ switch(n)
+ {
+ case S_NL:
+ lp->sh->inlineno++;
+ if((stripcol && c==' ') || (stripflg && c=='\t'))
+ {
+ if(!lp->lexd.dolparen)
+ {
+ /* write out line */
+ n = fcseek(0)-bufp;
+ if((n=sfwrite(sp,bufp,n))>0)
+ iop->iosize += n;
+ }
+ /* skip over tabs */
+ if(stripcol)
+ {
+ int col=0;
+ do
+ {
+ fcgetc(c);
+ if(c==' ')
+ col++;
+ else
+ col += 8 - col%8;
+ if(col>stripcol)
+ break;
+ }
+ while (c==' ' || c=='\t');
+ }
+ else while(c=='\t')
+ fcgetc(c);
+ if(c<=0)
+ goto done;
+ bufp = fcseek(-LEN);
+ }
+ if(c!=iop->iodelim[0])
+ break;
+ cp = fcseek(0);
+ nsave = n = 0;
+ while(1)
+ {
+ if(!(c=fcget()))
+ {
+ if(!lp->lexd.dolparen && (c=cp-bufp))
+ {
+ if((c=sfwrite(sp,cp=bufp,c))>0)
+ iop->iosize+=c;
+ }
+ nsave = n;
+ if((c=lexfill(lp))<=0)
+ {
+ c = iop->iodelim[n]==0;
+ goto done;
+ }
+ }
+#if SHOPT_CRNL
+ if(c=='\r' && (c=fcget())!=NL)
+ {
+ if(c)
+ fcseek(-LEN);
+ c='\r';
+ }
+#endif /* SHOPT_CRNL */
+ if(c==NL)
+ lp->sh->inlineno++;
+ if(iop->iodelim[n]==0 && (c==NL||c==RPAREN))
+ {
+ if(!lp->lexd.dolparen && (n=cp-bufp))
+ {
+ if((n=sfwrite(sp,bufp,n))>0)
+ iop->iosize += n;
+ }
+ lp->sh->inlineno--;
+ if(c==RPAREN)
+ fcseek(-LEN);
+ goto done;
+ }
+ if(iop->iodelim[n++]!=c)
+ {
+ /*
+ * The match for delimiter failed.
+ * nsave>0 only when a buffer boundary
+ * was crossed while checking the
+ * delimiter
+ */
+ if(!lp->lexd.dolparen && nsave>0)
+ {
+ if((n=sfwrite(sp,iop->iodelim,nsave))>0)
+ iop->iosize += n;
+ bufp = fcfirst();
+ }
+ if(c==NL)
+ fcseek(-LEN);
+ break;
+ }
+ }
+ break;
+ case S_ESC:
+ n=1;
+#if SHOPT_CRNL
+ if(c=='\r')
+ {
+ fcseek(1);
+ if(c=fcget())
+ fcseek(-LEN);
+ if(c==NL)
+ n=2;
+ else
+ {
+ special++;
+ break;
+ }
+ }
+#endif /* SHOPT_CRNL */
+ if(c==NL)
+ {
+ /* new-line joining */
+ lp->sh->inlineno++;
+ if(!lp->lexd.dolparen && (n=(fcseek(0)-bufp)-n)>=0)
+ {
+ if(n && (n=sfwrite(sp,bufp,n))>0)
+ iop->iosize += n;
+ bufp = fcseek(0)+1;
+ }
+ }
+ else
+ special++;
+ fcget();
+ break;
+
+ case S_GRAVE:
+ case S_DOL:
+ special++;
+ break;
+ }
+ n=0;
+ }
+done:
+ lp->sh->funlog = funlog;
+ if(lp->lexd.dolparen)
+ free((void*)iop);
+ else if(!special)
+ iop->iofile |= IOQUOTE;
+ return(c);
+}
+
+/*
+ * generates string for given token
+ */
+static char *fmttoken(Lex_t *lp, register int sym, char *tok)
+{
+ int n=1;
+ if(sym < 0)
+ return((char*)sh_translate(e_lexzerobyte));
+ if(sym==0)
+ return(lp->arg?lp->arg->argval:"?");
+ if(lp->lex.intest && lp->arg && *lp->arg->argval)
+ return(lp->arg->argval);
+ if(sym&SYMRES)
+ {
+ register const Shtable_t *tp=shtab_reserved;
+ while(tp->sh_number && tp->sh_number!=sym)
+ tp++;
+ return((char*)tp->sh_name);
+ }
+ if(sym==EOFSYM)
+ return((char*)sh_translate(e_endoffile));
+ if(sym==NL)
+ return((char*)sh_translate(e_newline));
+ tok[0] = sym;
+ if(sym&SYMREP)
+ tok[n++] = sym;
+ else
+ {
+ switch(sym&SYMMASK)
+ {
+ case SYMAMP:
+ sym = '&';
+ break;
+ case SYMPIPE:
+ sym = '|';
+ break;
+ case SYMGT:
+ sym = '>';
+ break;
+ case SYMLPAR:
+ sym = LPAREN;
+ break;
+ case SYMSHARP:
+ sym = '#';
+ break;
+ case SYMSEMI:
+ if(tok[0]=='<')
+ tok[n++] = '>';
+ sym = ';';
+ break;
+ default:
+ sym = 0;
+ }
+ tok[n++] = sym;
+ }
+ tok[n] = 0;
+ return(tok);
+}
+
+/*
+ * print a bad syntax message
+ */
+
+void sh_syntax(Lex_t *lp)
+{
+ register Shell_t *shp = lp->sh;
+ register const char *cp = sh_translate(e_unexpected);
+ register char *tokstr;
+ register int tok = lp->token;
+ char tokbuf[3];
+ Sfio_t *sp;
+ if((tok==EOFSYM) && lp->lasttok)
+ {
+ tok = lp->lasttok;
+ cp = sh_translate(e_unmatched);
+ }
+ else
+ lp->lastline = shp->inlineno;
+ tokstr = fmttoken(lp,tok,tokbuf);
+ if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd])))
+ {
+ /* clear out any pending input */
+ register Sfio_t *top;
+ while(fcget()>0);
+ fcclose();
+ while(top=sfstack(sp,SF_POPSTACK))
+ sfclose(top);
+ }
+ else
+ fcclose();
+ shp->inlineno = lp->inlineno;
+ shp->st.firstline = lp->firstline;
+#if KSHELL
+ if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE))
+#else
+ if(shp->inlineno!=1)
+#endif
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp);
+ else
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp);
+}
+
+static char *stack_shift(Stk_t *stkp, register char *sp,char *dp)
+{
+ register char *ep;
+ register int offset = stktell(stkp);
+ register int left = offset-(sp-stkptr(stkp,0));
+ register int shift = (dp+1-sp);
+ offset += shift;
+ stkseek(stkp,offset);
+ sp = stkptr(stkp,offset);
+ ep = sp - shift;
+ while(left--)
+ *--sp = *--ep;
+ return(sp);
+}
+
+/*
+ * Assumes that current word is unfrozen on top of the stak
+ * If <mode> is zero, gets rid of quoting and consider argument as string
+ * and returns pointer to frozen arg
+ * If mode==1, just replace $"..." strings with international strings
+ * The result is left on the stak
+ * If mode==2, the each $"" string is printed on standard output
+ */
+struct argnod *sh_endword(Shell_t *shp,int mode)
+{
+ register const char *state = sh_lexstates[ST_NESTED];
+ register int n;
+ register char *sp,*dp;
+ register int inquote=0, inlit=0; /* set within quoted strings */
+ struct argnod* argp=0;
+ char *ep=0, *xp=0;
+ int bracket=0;
+ Stk_t *stkp=shp->stk;
+ sfputc(stkp,0);
+ sp = stkptr(stkp,ARGVAL);
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ do
+ {
+ int len;
+ switch(len = mbsize(sp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ case 1:
+ n=state[*sp++];
+ break;
+ default:
+ /*
+ * None of the state tables contain
+ * entries for multibyte characters,
+ * however, they should be treated
+ * the same as any other alph
+ * character. Therefore, we'll use
+ * the state of the 'a' character.
+ */
+ n=state['a'];
+ sp += len;
+ }
+ }
+ while(n == 0);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((n=state[*sp++])==0);
+ dp = sp;
+ if(mode<0)
+ inquote = 1;
+ while(1)
+ {
+ switch(n)
+ {
+ case S_EOF:
+ stkseek(stkp,dp-stkptr(stkp,0));
+ if(mode<=0)
+ {
+ argp = (struct argnod*)stkfreeze(stkp,0);
+ argp->argflag = ARG_RAW|ARG_QUOTED;
+ }
+ return(argp);
+ case S_LIT:
+ if(!(inquote&1))
+ {
+ inlit = !inlit;
+ if(mode==0 || (mode<0 && bracket))
+ {
+ dp--;
+ if(ep)
+ {
+ *dp = 0;
+ stresc(ep);
+ dp = ep+ strlen(ep);
+ }
+ ep = 0;
+ }
+ }
+ break;
+ case S_QUOTE:
+ if(mode<0 && !bracket)
+ break;
+ if(!inlit)
+ {
+ if(mode<=0)
+ dp--;
+ inquote = inquote^1;
+ if(ep)
+ {
+ char *msg;
+ if(mode==2)
+ {
+ sfprintf(sfstdout,"%.*s\n",dp-ep,ep);
+ ep = 0;
+ break;
+ }
+ *--dp = 0;
+#if ERROR_VERSION >= 20000317L
+ msg = ERROR_translate(0,error_info.id,0,ep);
+#else
+# if ERROR_VERSION >= 20000101L
+ msg = ERROR_translate(error_info.id,ep);
+# else
+ msg = ERROR_translate(ep,2);
+# endif
+#endif
+ n = strlen(msg);
+ dp = ep+n;
+ if(sp-dp <= 1)
+ {
+ sp = stack_shift(stkp,sp,dp);
+ dp = sp-1;
+ ep = dp-n;
+ }
+ memmove(ep,msg,n);
+ *dp++ = '"';
+ }
+ ep = 0;
+ }
+ break;
+ case S_DOL: /* check for $'...' and $"..." */
+ if(inlit)
+ break;
+ if(*sp==LPAREN || *sp==LBRACE)
+ {
+ inquote <<= 1;
+ break;
+ }
+ if(inquote&1)
+ break;
+ if(*sp=='\'' || *sp=='"')
+ {
+ if(*sp=='"')
+ inquote |= 1;
+ else
+ inlit = 1;
+ sp++;
+ if((mode==0||(mode<0&&bracket)) || (inquote&1))
+ {
+ if(mode==2)
+ ep = dp++;
+ else if(mode==1)
+ (ep=dp)[-1] = '"';
+ else
+ ep = --dp;
+ }
+ }
+ break;
+ case S_ESC:
+#if SHOPT_CRNL
+ if(*sp=='\r' && sp[1]=='\n')
+ sp++;
+#endif /* SHOPT_CRNL */
+ if(inlit || mode>0)
+ {
+ if(mode<0)
+ {
+ if(dp>=sp)
+ {
+ sp = stack_shift(stkp,sp,dp+1);
+ dp = sp-2;
+ }
+ *dp++ = '\\';
+ }
+ if(ep)
+ *dp++ = *sp++;
+ break;
+ }
+ n = *sp;
+#if SHOPT_DOS
+ if(!(inquote&1) && sh_lexstates[ST_NORM][n]==0)
+ break;
+#endif /* SHOPT_DOS */
+ if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE))
+ {
+ if(n=='\n')
+ dp--;
+ else
+ dp[-1] = n;
+ sp++;
+ }
+ break;
+ case S_POP:
+ if(sp[-1]!=RBRACT)
+ break;
+ if(!inlit && !(inquote&1))
+ {
+ inquote >>= 1;
+ if(xp)
+ dp = sh_checkid(xp,dp);
+ xp = 0;
+ if(--bracket<=0 && mode<0)
+ inquote = 1;
+ }
+ else if((inlit||inquote) && mode<0)
+ {
+ dp[-1] = '\\';
+ if(dp>=sp)
+ {
+ sp = stack_shift(stkp,sp,dp);
+ dp = sp-1;
+ }
+ *dp++ = ']';
+ }
+ break;
+ case S_BRACT:
+ if(dp[-2]=='.')
+ xp = dp;
+ if(mode<0)
+ {
+ if(inlit || (bracket&&inquote))
+ {
+ dp[-1] = '\\';
+ if(dp>=sp)
+ {
+ sp = stack_shift(stkp,sp,dp);
+ dp = sp-1;
+ }
+ *dp++ = '[';
+ }
+ else if(bracket++==0)
+ inquote = 0;
+ }
+ break;
+ }
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ do
+ {
+ int len;
+ switch(len = mbsize(sp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ case 1:
+ n=state[*dp++ = *sp++];
+ break;
+ default:
+ /*
+ * None of the state tables contain
+ * entries for multibyte characters,
+ * however, they should be treated
+ * the same as any other alph
+ * character. Therefore, we'll use
+ * the state of the 'a' character.
+ */
+ while(len--)
+ *dp++ = *sp++;
+ n=state['a'];
+ }
+ }
+ while(n == 0);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((n=state[*dp++ = *sp++])==0);
+ }
+}
+
+struct alias
+{
+ Sfdisc_t disc;
+ Namval_t *np;
+ int nextc;
+ int line;
+ char buf[2];
+ Lex_t *lp;
+};
+
+/*
+ * This code gets called whenever an end of string is found with alias
+ */
+
+#ifndef SF_ATEXIT
+# define SF_ATEXIT 0
+#endif
+/*
+ * This code gets called whenever an end of string is found with alias
+ */
+#ifdef SF_BUFCONST
+static int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle)
+#else
+static int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle)
+#endif
+{
+ register struct alias *ap = (struct alias*)handle;
+ register Namval_t *np;
+ register Lex_t *lp;
+ if(type==0 || type==SF_ATEXIT || !ap)
+ return(0);
+ lp = ap->lp;
+ np = ap->np;
+ if(type!=SF_READ)
+ {
+ if(type==SF_CLOSING)
+ {
+ register Sfdisc_t *dp = sfdisc(iop,SF_POPDISC);
+ if(dp!=handle)
+ sfdisc(iop,dp);
+ }
+ else if(type==SF_FINAL)
+ free((void*)ap);
+ goto done;
+ }
+ if(ap->nextc)
+ {
+ /* if last character is a blank, then next work can be alias */
+ register int c = fcpeek(-1);
+ if(isblank(c))
+ lp->aliasok = 1;
+ *ap->buf = ap->nextc;
+ ap->nextc = 0;
+ sfsetbuf(iop,ap->buf,1);
+ return(1);
+ }
+done:
+ if(np)
+ nv_offattr(np,NV_NOEXPAND);
+ return(0);
+}
+
+
+static void setupalias(Lex_t *lp, const char *string,Namval_t *np)
+{
+ register Sfio_t *iop, *base;
+ struct alias *ap = (struct alias*)malloc(sizeof(struct alias));
+ ap->disc = alias_disc;
+ ap->lp = lp;
+ ap->buf[1] = 0;
+ if(ap->np = np)
+ {
+#if SHOPT_KIA
+ if(lp->kiafile)
+ {
+ unsigned long r;
+ r=kiaentity(lp,nv_name(np),-1,'p',0,0,lp->current,'a',0,"");
+ sfprintf(lp->kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",lp->current,r,lp->sh->inlineno,lp->sh->inlineno);
+ }
+#endif /* SHOPT_KIA */
+ if((ap->nextc=fcget())==0)
+ ap->nextc = ' ';
+ }
+ else
+ ap->nextc = 0;
+ iop = sfopen(NIL(Sfio_t*),(char*)string,"s");
+ sfdisc(iop, &ap->disc);
+ lp->lexd.nocopy++;
+ if(!(base=fcfile()))
+ base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
+ fcclose();
+ sfstack(base,iop);
+ fcfopen(base);
+ lp->lexd.nocopy--;
+}
+
+/*
+ * grow storage stack for nested constructs by STACK_ARRAY
+ */
+static int stack_grow(Lex_t *lp)
+{
+ lp->lexd.lex_max += STACK_ARRAY;
+ if(lp->lexd.lex_match)
+ lp->lexd.lex_match = (int*)realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max);
+ else
+ lp->lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY);
+ return(lp->lexd.lex_match!=0);
+}
+
diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c
new file mode 100644
index 0000000..9adf5f5
--- /dev/null
+++ b/src/cmd/ksh93/sh/macro.c
@@ -0,0 +1,2814 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Shell macro expander
+ * expands ~
+ * expands ${...}
+ * expands $(...)
+ * expands $((...))
+ * expands `...`
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include <pwd.h>
+#include <ctype.h>
+#include "name.h"
+#include "variables.h"
+#include "shlex.h"
+#include "io.h"
+#include "jobs.h"
+#include "shnodes.h"
+#include "path.h"
+#include "national.h"
+#include "streval.h"
+
+#undef STR_GROUP
+#ifndef STR_GROUP
+# define STR_GROUP 0
+#endif
+
+#if SHOPT_MULTIBYTE
+# undef isascii
+# define isacii(c) ((c)<=UCHAR_MAX)
+#else
+# define mbchar(p) (*(unsigned char*)p++)
+#endif /* SHOPT_MULTIBYTE */
+
+#if _WINIX
+ static int Skip;
+#endif /*_WINIX */
+
+static int _c_;
+typedef struct _mac_
+{
+ Shell_t *shp; /* pointer to shell interpreter */
+ Sfio_t *sp; /* stream pointer for here-document */
+ struct argnod **arghead; /* address of head of argument list */
+ char *ifsp; /* pointer to IFS value */
+ int fields; /* number of fields */
+ short quoted; /* set when word has quotes */
+ unsigned char ifs; /* first char of IFS */
+ char atmode; /* when processing $@ */
+ char quote; /* set within double quoted contexts */
+ char lit; /* set within single quotes */
+ char split; /* set when word splittin is possible */
+ char pattern; /* set when file expansion follows */
+ char patfound; /* set if pattern character found */
+ char assign; /* set for assignments */
+ char arith; /* set for ((...)) */
+ char let; /* set when expanding let arguments */
+ char zeros; /* strip leading zeros when set */
+ char arrayok; /* $x[] ok for arrays */
+ char subcopy; /* set when copying subscript */
+ int dotdot; /* set for .. in subscript */
+ void *nvwalk; /* for name space walking*/
+} Mac_t;
+
+#undef ESCAPE
+#define ESCAPE '\\'
+#define isescchar(s) ((s)>S_QUOTE)
+#define isqescchar(s) ((s)>=S_QUOTE)
+#define isbracechar(c) ((c)==RBRACE || (_c_=sh_lexstates[ST_BRACE][c])==S_MOD1 ||_c_==S_MOD2)
+#define ltos(x) fmtbase((long)(x),0,0)
+
+/* type of macro expansions */
+#define M_BRACE 1 /* ${var} */
+#define M_TREE 2 /* ${var.} */
+#define M_SIZE 3 /* ${#var} */
+#define M_VNAME 4 /* ${!var} */
+#define M_SUBNAME 5 /* ${!var[sub]} */
+#define M_NAMESCAN 6 /* ${!var*} */
+#define M_NAMECOUNT 7 /* ${#var*} */
+#define M_TYPE 8 /* ${@var} */
+
+static int substring(const char*, const char*, int[], int);
+static void copyto(Mac_t*, int, int);
+static void comsubst(Mac_t*, Shnode_t*, int);
+static int varsub(Mac_t*);
+static void mac_copy(Mac_t*,const char*, int);
+static void tilde_expand2(Shell_t*,int);
+static char *sh_tilde(Shell_t*,const char*);
+static char *special(Shell_t *,int);
+static void endfield(Mac_t*,int);
+static void mac_error(Namval_t*);
+static char *mac_getstring(char*);
+static int charlen(const char*,int);
+#if SHOPT_MULTIBYTE
+ static char *lastchar(const char*,const char*);
+#endif /* SHOPT_MULTIBYTE */
+
+void *sh_macopen(Shell_t *shp)
+{
+ void *addr = newof(0,Mac_t,1,0);
+ Mac_t *mp = (Mac_t*)addr;
+ mp->shp = shp;
+ return(addr);
+}
+
+/*
+ * perform only parameter substitution and catch failures
+ */
+char *sh_mactry(Shell_t *shp,register char *string)
+{
+ if(string)
+ {
+ int jmp_val;
+ int savexit = shp->savexit;
+ struct checkpt buff;
+ sh_pushcontext(shp,&buff,SH_JMPSUB);
+ jmp_val = sigsetjmp(buff.buff,0);
+ if(jmp_val == 0)
+ string = sh_mactrim(shp,string,0);
+ sh_popcontext(shp,&buff);
+ shp->savexit = savexit;
+ return(string);
+ }
+ return("");
+}
+
+/*
+ * Perform parameter expansion, command substitution, and arithmetic
+ * expansion on <str>.
+ * If <mode> greater than 1 file expansion is performed if the result
+ * yields a single pathname.
+ * If <mode> negative, than expansion rules for assignment are applied.
+ */
+char *sh_mactrim(Shell_t *shp, char *str, register int mode)
+{
+ register Mac_t *mp = (Mac_t*)shp->mac_context;
+ Stk_t *stkp = shp->stk;
+ Mac_t savemac;
+ savemac = *mp;
+ stkseek(stkp,0);
+ mp->arith = (mode==3);
+ mp->let = 0;
+ shp->argaddr = 0;
+ mp->pattern = (mode==1||mode==2);
+ mp->patfound = 0;
+ mp->assign = 0;
+ if(mode<0)
+ mp->assign = -mode;
+ mp->quoted = mp->lit = mp->split = mp->quote = 0;
+ mp->sp = 0;
+ if(mp->ifsp=nv_getval(sh_scoped(shp,IFSNOD)))
+ mp->ifs = *mp->ifsp;
+ else
+ mp->ifs = ' ';
+ stkseek(stkp,0);
+ fcsopen(str);
+ copyto(mp,0,mp->arith);
+ str = stkfreeze(stkp,1);
+ if(mode==2)
+ {
+ /* expand only if unique */
+ struct argnod *arglist=0;
+ if((mode=path_expand(shp,str,&arglist))==1)
+ str = arglist->argval;
+ else if(mode>1)
+ errormsg(SH_DICT,ERROR_exit(1),e_ambiguous,str);
+ sh_trim(str);
+ }
+ *mp = savemac;
+ return(str);
+}
+
+/*
+ * Perform all the expansions on the argument <argp>
+ */
+int sh_macexpand(Shell_t* shp, register struct argnod *argp, struct argnod **arghead,int flag)
+{
+ register int flags = argp->argflag;
+ register char *str = argp->argval;
+ register Mac_t *mp = (Mac_t*)shp->mac_context;
+ char **saveargaddr = shp->argaddr;
+ Mac_t savemac;
+ Stk_t *stkp = shp->stk;
+ savemac = *mp;
+ mp->sp = 0;
+ if(mp->ifsp=nv_getval(sh_scoped(shp,IFSNOD)))
+ mp->ifs = *mp->ifsp;
+ else
+ mp->ifs = ' ';
+ if((flag&ARG_OPTIMIZE) && !shp->indebug && !(flags&ARG_MESSAGE))
+ shp->argaddr = (char**)&argp->argchn.ap;
+ else
+ shp->argaddr = 0;
+ mp->arghead = arghead;
+ mp->quoted = mp->lit = mp->quote = 0;
+ mp->arith = ((flag&ARG_ARITH)!=0);
+ mp->let = ((flag&ARG_LET)!=0);
+ mp->split = !(flag&ARG_ASSIGN);
+ mp->assign = !mp->split;
+ mp->pattern = mp->split && !(flag&ARG_NOGLOB) && !sh_isoption(SH_NOGLOB);
+ mp->arrayok = mp->arith || (flag&ARG_ARRAYOK);
+ str = argp->argval;
+ fcsopen(str);
+ mp->fields = 0;
+ mp->atmode = 0;
+ if(!arghead)
+ {
+ mp->split = 0;
+ mp->pattern = ((flag&ARG_EXP)!=0);
+ stkseek(stkp,0);
+ }
+ else
+ {
+ stkseek(stkp,ARGVAL);
+ *stkptr(stkp,ARGVAL-1) = 0;
+ }
+ mp->patfound = 0;
+ if(mp->pattern)
+ mp->arrayok = 0;
+ copyto(mp,0,mp->arith);
+ if(!arghead)
+ {
+ argp->argchn.cp = stkfreeze(stkp,1);
+ if(shp->argaddr)
+ argp->argflag |= ARG_MAKE;
+ }
+ else
+ {
+ endfield(mp,mp->quoted|mp->atmode);
+ flags = mp->fields;
+ if(flags==1 && shp->argaddr)
+ argp->argchn.ap = *arghead;
+ }
+ shp->argaddr = saveargaddr;
+ *mp = savemac;
+ return(flags);
+}
+
+/*
+ * Expand here document which is stored in <infile> or <string>
+ * The result is written to <outfile>
+ */
+void sh_machere(Shell_t *shp,Sfio_t *infile, Sfio_t *outfile, char *string)
+{
+ register int c,n;
+ register const char *state = sh_lexstates[ST_QUOTE];
+ register char *cp;
+ register Mac_t *mp = (Mac_t*)shp->mac_context;
+ Lex_t *lp = (Lex_t*)mp->shp->lex_context;
+ Fcin_t save;
+ Mac_t savemac;
+ Stk_t *stkp = shp->stk;
+ savemac = *mp;
+ stkseek(stkp,0);
+ shp->argaddr = 0;
+ mp->sp = outfile;
+ mp->split = mp->assign = mp->pattern = mp->patfound = mp->lit = mp->arith = mp->let = 0;
+ mp->quote = 1;
+ mp->ifsp = nv_getval(sh_scoped(shp,IFSNOD));
+ mp->ifs = ' ';
+ fcsave(&save);
+ if(infile)
+ fcfopen(infile);
+ else
+ fcsopen(string);
+ fcnotify(0,lp);
+ cp = fcseek(0);
+ while(1)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ do
+ {
+ ssize_t len;
+ switch(len = mbsize(cp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ case 1:
+ n=state[*(unsigned char*)cp++];
+ break;
+ default:
+ /* use state of alpha character */
+ n=state['a'];
+ cp += len;
+ }
+ }
+ while(n == 0);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((n=state[*(unsigned char*)cp++])==0);
+ if(n==S_NL || n==S_QUOTE || n==S_RBRA)
+ continue;
+ if(c=(cp-1)-fcseek(0))
+ sfwrite(outfile,fcseek(0),c);
+ cp = fcseek(c+1);
+ switch(n)
+ {
+ case S_EOF:
+ if((n=fcfill()) <=0)
+ {
+ /* ignore 0 byte when reading from file */
+ if(n==0 && fcfile())
+ continue;
+ fcrestore(&save);
+ *mp = savemac;
+ return;
+ }
+ cp = fcseek(-1);
+ continue;
+ case S_ESC:
+ fcgetc(c);
+ cp=fcseek(-1);
+ if(c>0)
+ cp++;
+ if(!isescchar(state[c]))
+ sfputc(outfile,ESCAPE);
+ continue;
+ case S_GRAVE:
+ comsubst(mp,(Shnode_t*)0,0);
+ break;
+ case S_DOL:
+ c = fcget();
+ if(c=='.')
+ goto regular;
+ again:
+ switch(n=sh_lexstates[ST_DOL][c])
+ {
+ case S_ALP: case S_SPC1: case S_SPC2:
+ case S_DIG: case S_LBRA:
+ {
+ Fcin_t save2;
+ int offset = stktell(stkp);
+ int offset2;
+ fcnotify(0,lp);
+ sfputc(stkp,c);
+ if(n==S_LBRA)
+ {
+ c = fcget();
+ fcseek(-1);
+ if(sh_lexstates[ST_NORM][c]==S_BREAK)
+ {
+ comsubst(mp,(Shnode_t*)0,2);
+ break;
+ }
+ sh_lexskip(lp,RBRACE,1,ST_BRACE);
+ }
+ else if(n==S_ALP)
+ {
+ while(fcgetc(c),isaname(c))
+ sfputc(stkp,c);
+ fcseek(-1);
+ }
+ sfputc(stkp,0);
+ offset2 = stktell(stkp);
+ fcsave(&save2);
+ fcsopen(stkptr(stkp,offset));
+ varsub(mp);
+ if(c=stktell(stkp)-offset2)
+ sfwrite(outfile,(char*)stkptr(stkp,offset2),c);
+ fcrestore(&save2);
+ stkseek(stkp,offset);
+ break;
+ }
+ case S_PAR:
+ comsubst(mp,(Shnode_t*)0,1);
+ break;
+ case S_EOF:
+ if((c=fcfill()) > 0)
+ goto again;
+ /* FALL THRU */
+ default:
+ regular:
+ sfputc(outfile,'$');
+ fcseek(-1);
+ break;
+ }
+ }
+ cp = fcseek(0);
+ }
+}
+
+/*
+ * expand argument but do not trim pattern characters
+ */
+char *sh_macpat(Shell_t *shp,register struct argnod *arg, int flags)
+{
+ register char *sp = arg->argval;
+ if((arg->argflag&ARG_RAW))
+ return(sp);
+ sh_stats(STAT_ARGEXPAND);
+ if(flags&ARG_OPTIMIZE)
+ arg->argchn.ap=0;
+ if(!(sp=arg->argchn.cp))
+ {
+ sh_macexpand(shp,arg,NIL(struct argnod**),flags|ARG_ARRAYOK);
+ sp = arg->argchn.cp;
+ if(!(flags&ARG_OPTIMIZE) || !(arg->argflag&ARG_MAKE))
+ arg->argchn.cp = 0;
+ arg->argflag &= ~ARG_MAKE;
+ }
+ else
+ sh_stats(STAT_ARGHITS);
+ return(sp);
+}
+
+/*
+ * Process the characters up to <endch> or end of input string
+ */
+static void copyto(register Mac_t *mp,int endch, int newquote)
+{
+ register int c,n;
+ register const char *state = sh_lexstates[ST_MACRO];
+ register char *cp,*first;
+ Lex_t *lp = (Lex_t*)mp->shp->lex_context;
+ int tilde = -1;
+ int oldquote = mp->quote;
+ int ansi_c = 0;
+ int paren = 0;
+ int ere = 0;
+ int brace = 0;
+ Sfio_t *sp = mp->sp;
+ Stk_t *stkp = mp->shp->stk;
+ char *resume = 0;
+ mp->sp = NIL(Sfio_t*);
+ mp->quote = newquote;
+ first = cp = fcseek(0);
+ if(!mp->quote && *cp=='~' && cp[1]!=LPAREN)
+ tilde = stktell(stkp);
+ /* handle // operator specially */
+ if(mp->pattern==2 && *cp=='/')
+ cp++;
+ while(1)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ ssize_t len;
+ do
+ {
+ switch(len = mbsize(cp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ len = 1;
+ case 1:
+ n = state[*(unsigned char*)cp++];
+ break;
+ default:
+ /* treat as if alpha */
+ cp += len;
+ n=state['a'];
+ }
+ }
+ while(n == 0);
+ c = (cp-len) - first;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ {
+ while((n=state[*(unsigned char*)cp++])==0);
+ c = (cp-1) - first;
+ }
+ switch(n)
+ {
+ case S_ESC:
+ if(ansi_c)
+ {
+ /* process ANSI-C escape character */
+ char *addr= --cp;
+ if(c)
+ sfwrite(stkp,first,c);
+ c = chresc(cp,&addr);
+ cp = addr;
+ first = fcseek(cp-first);
+#if SHOPT_MULTIBYTE
+ if(c > UCHAR_MAX && mbwide())
+ {
+ int i;
+ unsigned char mb[8];
+
+ n = mbconv((char*)mb, c);
+ for(i=0;i<n;i++)
+ sfputc(stkp,mb[i]);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ sfputc(stkp,c);
+ if(c==ESCAPE && mp->pattern)
+ sfputc(stkp,ESCAPE);
+ break;
+ }
+ else if(sh_isoption(SH_BRACEEXPAND) && mp->pattern==4 && (*cp==',' || *cp==LBRACE || *cp==RBRACE || *cp=='.'))
+ break;
+ else if(mp->split && endch && !mp->quote && !mp->lit)
+ {
+ if(c)
+ mac_copy(mp,first,c);
+ cp = fcseek(c+2);
+ if(c= cp[-1])
+ {
+ sfputc(stkp,c);
+ if(c==ESCAPE)
+ sfputc(stkp,ESCAPE);
+ }
+ else
+ cp--;
+ first = cp;
+ break;
+ }
+ n = state[*(unsigned char*)cp];
+ if(n==S_ENDCH && *cp!=endch)
+ n = S_PAT;
+ if(mp->pattern)
+ {
+ /* preserve \digit for pattern matching */
+ /* also \alpha for extended patterns */
+ if(!mp->lit && !mp->quote)
+ {
+ int nc = *(unsigned char*)cp;
+ if((n==S_DIG || ((paren+ere) && (sh_lexstates[ST_DOL][nc]==S_ALP) || nc=='<' || nc=='>')))
+ break;
+ if(ere && mp->pattern==1 && strchr(".[()*+?{|^$&!",*cp))
+ break;
+ }
+ /* followed by file expansion */
+ if(!mp->lit && (n==S_ESC || (!mp->quote &&
+ (n==S_PAT||n==S_ENDCH||n==S_SLASH||n==S_BRACT||*cp=='-'))))
+ {
+ cp += (n!=S_EOF);
+ if(ere && n==S_ESC && *cp =='\\' && cp[1]=='$')
+ {
+ /* convert \\\$ into \$' */
+ sfwrite(stkp,first,c+1);
+ cp = first = fcseek(c+3);
+ }
+ break;
+ }
+ if(!(ere && *cp=='$') && (mp->lit || (mp->quote && !isqescchar(n) && n!=S_ENDCH)))
+ {
+ /* add \ for file expansion */
+ sfwrite(stkp,first,c+1);
+ first = fcseek(c);
+ break;
+ }
+ }
+ if(mp->lit)
+ break;
+ if(!mp->quote || isqescchar(n) || n==S_ENDCH)
+ {
+ /* eliminate \ */
+ if(c)
+ sfwrite(stkp,first,c);
+ /* check new-line joining */
+ first = fcseek(c+1);
+ }
+ cp += (n!=S_EOF);
+ break;
+ case S_GRAVE: case S_DOL:
+ if(mp->lit)
+ break;
+ if(c)
+ {
+ if(mp->split && !mp->quote && endch)
+ mac_copy(mp,first,c);
+ else
+ sfwrite(stkp,first,c);
+ }
+ first = fcseek(c+1);
+ c = mp->pattern;
+ if(n==S_GRAVE)
+ comsubst(mp,(Shnode_t*)0,0);
+ else if((n= *cp) == '"' && !mp->quote)
+ {
+ int off = stktell(stkp);
+ char *dp;
+ cp = first = fcseek(1);
+ mp->quote = 1;
+ if(!ERROR_translating())
+ break;
+ while(n=c, c= *++cp)
+ {
+ if(c=='\\' && n==c)
+ c = 0;
+ else if(c=='"' && n!='\\')
+ break;
+ }
+ n = cp-first;
+ sfwrite(stkp,first,n);
+ sfputc(stkp,0);
+ cp = stkptr(stkp,off);
+ dp = (char*)sh_translate(cp);
+ stkseek(stkp,off);
+ if(dp==cp)
+ {
+ cp = first;
+ break;
+ }
+ resume = fcseek(n);
+ fcclose();
+ fcsopen(dp);
+ cp = first = fcseek(0);
+ break;
+ }
+ else if(n==0 || !varsub(mp))
+ {
+ if(n=='\'' && !mp->quote)
+ ansi_c = 1;
+ else if(mp->quote || n!='"')
+ sfputc(stkp,'$');
+ }
+ cp = first = fcseek(0);
+ if(mp->quote && cp)
+ mp->pattern = c;
+ break;
+ case S_ENDCH:
+ if((mp->lit || cp[-1]!=endch || mp->quote!=newquote))
+ goto pattern;
+ if(endch==RBRACE && *cp==LPAREN && mp->pattern && brace)
+ goto pattern;
+ case S_EOF:
+ if(c)
+ {
+ if(mp->split && !mp->quote && !mp->lit && endch)
+ mac_copy(mp,first,c);
+ else
+ sfwrite(stkp,first,c);
+ }
+ if(n==S_EOF && resume)
+ {
+ fcclose();
+ fcsopen(resume);
+ resume = 0;
+ cp = first = fcseek(0);
+ continue;
+ }
+ c += (n!=S_EOF);
+ first = fcseek(c);
+ if(tilde>=0)
+ tilde_expand2(mp->shp,tilde);
+ goto done;
+ case S_QUOTE:
+ if(mp->lit || mp->arith)
+ break;
+ case S_LIT:
+ if(mp->arith)
+ {
+ if((*cp=='`' || *cp=='[') && cp[1]=='\'')
+ cp +=2;
+ break;
+ }
+ if(n==S_LIT && mp->quote)
+ break;
+ if(c)
+ {
+ if(mp->split && endch && !mp->quote && !mp->lit)
+ mac_copy(mp,first,c);
+ else
+ sfwrite(stkp,first,c);
+ }
+ first = fcseek(c+1);
+ if(n==S_LIT)
+ {
+ if(mp->quote)
+ continue;
+ if(mp->lit)
+ mp->lit = ansi_c = 0;
+ else
+ mp->lit = 1;
+ }
+ else
+ mp->quote = !mp->quote;
+ mp->quoted++;
+ break;
+ case S_BRACT:
+ if(mp->arith || (((mp->assign&1) || endch==RBRACT) &&
+ !(mp->quote || mp->lit)))
+ {
+ int offset=0,oldpat = mp->pattern;
+ int oldarith = mp->arith, oldsub=mp->subcopy;
+ sfwrite(stkp,first,++c);
+ if(mp->assign&1)
+ {
+ if(first[c-2]=='.')
+ offset = stktell(stkp);
+ if(isastchar(*cp) && cp[1]==']')
+ errormsg(SH_DICT,ERROR_exit(1),
+e_badsubscript,*cp);
+ }
+ first = fcseek(c);
+ mp->pattern = 4;
+ mp->arith = 0;
+ mp->subcopy = 0;
+ copyto(mp,RBRACT,0);
+ mp->subcopy = oldsub;
+ mp->arith = oldarith;
+ mp->pattern = oldpat;
+ sfputc(stkp,RBRACT);
+ if(offset)
+ {
+ cp = stkptr(stkp,stktell(stkp));
+ if(sh_checkid(stkptr(stkp,offset),cp)!=cp)
+ stkseek(stkp,stktell(stkp)-2);
+ }
+ cp = first = fcseek(0);
+ break;
+ }
+ case S_PAT:
+ if(mp->pattern && !(mp->quote || mp->lit))
+ {
+ mp->patfound = mp->pattern;
+ if((n=cp[-1])==LPAREN)
+ {
+ paren++;
+ if((cp-first)>1 && cp[-2]=='~')
+ {
+ char *p = cp;
+ while((c=mbchar(p)) && c!=RPAREN)
+ if(c=='A'||c=='E'||c=='K'||c=='P'||c=='X')
+ {
+ ere = 1;
+ break;
+ }
+ }
+ }
+ else if(n==RPAREN)
+ --paren;
+ }
+ goto pattern;
+ case S_COM:
+ if(mp->pattern==4 && (mp->quote || mp->lit))
+ {
+ if(c)
+ {
+ sfwrite(stkp,first,c);
+ first = fcseek(c);
+ }
+ sfputc(stkp,ESCAPE);
+ }
+ break;
+ case S_BRACE:
+ if(!(mp->quote || mp->lit))
+ {
+ mp->patfound = mp->split && sh_isoption(SH_BRACEEXPAND);
+ brace = 1;
+ }
+ pattern:
+ if(!mp->pattern || !(mp->quote || mp->lit))
+ {
+ /* mark beginning of {a,b} */
+ if(n==S_BRACE && endch==0 && mp->pattern)
+ mp->pattern=4;
+ if(n==S_SLASH && mp->pattern==2)
+ mp->pattern=3;
+ break;
+ }
+ if(mp->pattern==3)
+ break;
+ if(c)
+ sfwrite(stkp,first,c);
+ first = fcseek(c);
+ sfputc(stkp,ESCAPE);
+ break;
+ case S_EQ:
+ if(mp->assign==1)
+ {
+ if(*cp=='~' && !endch && !mp->quote && !mp->lit)
+ tilde = stktell(stkp)+(c+1);
+ mp->assign = 2;
+ }
+ break;
+ case S_SLASH:
+ case S_COLON:
+ if(tilde >=0)
+ {
+ if(c)
+ sfwrite(stkp,first,c);
+ first = fcseek(c);
+ tilde_expand2(mp->shp,tilde);
+#if _WINIX
+ if(Skip)
+ {
+ first = cp = fcseek(Skip);
+ Skip = 0;
+ }
+#endif /*_WINIX */
+ tilde = -1;
+ c=0;
+ }
+ if(n==S_COLON && mp->assign==2 && *cp=='~' && endch==0 && !mp->quote &&!mp->lit)
+ tilde = stktell(stkp)+(c+1);
+ else if(n==S_SLASH && mp->pattern==2)
+#if 0
+ goto pattern;
+#else
+ {
+ if(mp->quote || mp->lit)
+ goto pattern;
+ sfwrite(stkp,first,c+1);
+ first = fcseek(c+1);
+ c = stktell(stkp);
+ sh_lexskip(lp,RBRACE,0,ST_NESTED);
+ stkseek(stkp,c);
+ cp = fcseek(-1);
+ sfwrite(stkp,first,cp-first);
+ first=cp;
+ }
+#endif
+ break;
+ case S_DOT:
+ if(*cp=='.' && mp->subcopy==1)
+ {
+ sfwrite(stkp,first,c);
+ sfputc(stkp,0);
+ mp->dotdot = stktell(stkp);
+ cp = first = fcseek(c+2);
+ }
+ break;
+ }
+ }
+done:
+ mp->sp = sp;
+ mp->quote = oldquote;
+}
+
+/*
+ * copy <str> to stack performing sub-expression substitutions
+ */
+static void mac_substitute(Mac_t *mp, register char *cp,char *str,register int subexp[],int subsize)
+{
+ register int c,n;
+ register char *first=cp;
+ while(1)
+ {
+ while((c= *cp++) && c!=ESCAPE);
+ if(c==0)
+ break;
+ if((n= *cp++)=='\\' || n==RBRACE || (n>='0' && n<='9' && (n-='0')<subsize))
+ {
+ c = cp-first-2;
+ if(c)
+ mac_copy(mp,first,c);
+ first=cp;
+ if(n=='\\' || n==RBRACE)
+ {
+ first--;
+ continue;
+ }
+ if((c=subexp[2*n])>=0)
+ {
+ if((n=subexp[2*n+1]-c)>0)
+ mac_copy(mp,str+c,n);
+ }
+ }
+ else if(n==0)
+ break;
+ }
+ if(n=cp-first-1)
+ mac_copy(mp,first,n);
+}
+
+#if SHOPT_FILESCAN
+#define MAX_OFFSETS (sizeof(shp->offsets)/sizeof(shp->offsets[0]))
+#define MAX_ARGN (32*1024)
+
+/*
+ * compute the arguments $1 ... $n and $# from the current line as needed
+ * save line offsets in the offsets array.
+ */
+static char *getdolarg(Shell_t *shp, int n, int *size)
+{
+ register int c=S_DELIM, d=shp->ifstable['\\'];
+ register unsigned char *first,*last,*cp = (unsigned char*)shp->cur_line;
+ register int m=shp->offsets[0],delim=0;
+ if(m==0)
+ return(0);
+ if(m<0)
+ m = 0;
+ else if(n<=m)
+ m = n-1;
+ else
+ m--;
+ if(m >= MAX_OFFSETS-1)
+ m = MAX_OFFSETS-2;
+ cp += shp->offsets[m+1];
+ n -= m;
+ shp->ifstable['\\'] = 0;
+ shp->ifstable[0] = S_EOF;
+ while(1)
+ {
+ if(c==S_DELIM)
+ while(shp->ifstable[*cp++]==S_SPACE);
+ first = --cp;
+ if(++m < MAX_OFFSETS)
+ shp->offsets[m] = (first-(unsigned char*)shp->cur_line);
+ while((c=shp->ifstable[*cp++])==0);
+ last = cp-1;
+ if(c==S_SPACE)
+ while((c=shp->ifstable[*cp++])==S_SPACE);
+ if(--n==0 || c==S_EOF)
+ {
+ if(last==first && c==S_EOF && (!delim || (m>1)))
+ {
+ n++;
+ m--;
+ }
+ break;
+ }
+ delim = (c==S_DELIM);
+ }
+ shp->ifstable['\\'] = d;
+ if(m > shp->offsets[0])
+ shp->offsets[0] = m;
+ if(n)
+ first = last = 0;
+ if(size)
+ *size = last-first;
+ return((char*)first);
+}
+#endif /* SHOPT_FILESCAN */
+
+/*
+ * get the prefix after name reference resolution
+ */
+static char *prefix(Shell_t *shp, char *id)
+{
+ Namval_t *np;
+ register char *sub=0, *cp = strchr(id,'.');
+ if(cp)
+ {
+ *cp = 0;
+ np = nv_search(id, shp->var_tree,0);
+ *cp = '.';
+ if(isastchar(cp[1]))
+ cp[1] = 0;
+ if(np && nv_isref(np))
+ {
+ int n;
+ char *sp;
+ shp->argaddr = 0;
+ while(nv_isref(np) && np->nvalue.cp)
+ {
+ sub = nv_refsub(np);
+ np = nv_refnode(np);
+ if(sub)
+ nv_putsub(np,sub,0L);
+ }
+ id = (char*)malloc(strlen(cp)+1+(n=strlen(sp=nv_name(np)))+ (sub?strlen(sub)+3:1));
+ memcpy(id,sp,n);
+ if(sub)
+ {
+ id[n++] = '[';
+ strcpy(&id[n],sub);
+ n+= strlen(sub)+1;
+ id[n-1] = ']';
+ }
+ strcpy(&id[n],cp);
+ return(id);
+ }
+ }
+ return(strdup(id));
+}
+
+/*
+ * copy to ']' onto the stack and return offset to it
+ */
+static int subcopy(Mac_t *mp, int flag)
+{
+ int split = mp->split;
+ int xpattern = mp->pattern;
+ int loc = stktell(mp->shp->stk);
+ int xarith = mp->arith;
+ int arrayok = mp->arrayok;
+ mp->split = 0;
+ mp->arith = 0;
+ mp->pattern = flag?4:0;
+ mp->arrayok=1;
+ mp->subcopy++;
+ mp->dotdot = 0;
+ copyto(mp,RBRACT,0);
+ mp->subcopy = 0;
+ mp->pattern = xpattern;
+ mp->split = split;
+ mp->arith = xarith;
+ mp->arrayok = arrayok;
+ return(loc);
+}
+
+/*
+ * if name is a discipline function, run the function and put the results
+ * on the stack so that ${x.foo} behaves like ${ x.foo;}
+ */
+int sh_macfun(Shell_t *shp, const char *name, int offset)
+{
+ Namval_t *np, *nq;
+ np = nv_bfsearch(name,shp->fun_tree,&nq,(char**)0);
+ if(np)
+ {
+ /* treat ${x.foo} as ${x.foo;} */
+ union
+ {
+ struct comnod com;
+ Shnode_t node;
+ } t;
+ union
+ {
+ struct argnod arg;
+ struct dolnod dol;
+ char buff[sizeof(struct dolnod)+sizeof(char*)];
+ } d;
+ memset(&t,0,sizeof(t));
+ memset(&d,0,sizeof(d));
+ t.node.com.comarg = &d.arg;
+ t.node.com.comline = shp->inlineno;
+ d.dol.dolnum = 1;
+ d.dol.dolval[0] = strdup(name);
+ stkseek(shp->stk,offset);
+ comsubst((Mac_t*)shp->mac_context,&t.node,2);
+ free(d.dol.dolval[0]);
+ return(1);
+ }
+ return(0);
+}
+
+static int namecount(Mac_t *mp,const char *prefix)
+{
+ int count = 0;
+ mp->nvwalk = nv_diropen((Namval_t*)0,prefix);
+ while(nv_dirnext(mp->nvwalk))
+ count++;
+ nv_dirclose(mp->nvwalk);
+ return(count);
+}
+
+static char *nextname(Mac_t *mp,const char *prefix, int len)
+{
+ char *cp;
+ if(len==0)
+ {
+ mp->nvwalk = nv_diropen((Namval_t*)0,prefix);
+ return((char*)mp->nvwalk);
+ }
+ if(!(cp=nv_dirnext(mp->nvwalk)))
+ nv_dirclose(mp->nvwalk);
+ return(cp);
+}
+
+/*
+ * This routine handles $param, ${parm}, and ${param op word}
+ * The input stream is assumed to be a string
+ */
+static int varsub(Mac_t *mp)
+{
+ register int c;
+ register int type=0; /* M_xxx */
+ register char *v,*argp=0;
+ register Namval_t *np = NIL(Namval_t*);
+ register int dolg=0, mode=0;
+ Lex_t *lp = (Lex_t*)mp->shp->lex_context;
+ Namarr_t *ap=0;
+ int dolmax=0, vsize= -1, offset= -1, nulflg, replen=0, bysub=0;
+ char idbuff[3], *id = idbuff, *pattern=0, *repstr=0, *arrmax=0;
+ char *idx = 0;
+ int var=1,addsub=0,oldpat=mp->pattern,idnum=0,flag=0,d;
+ Stk_t *stkp = mp->shp->stk;
+retry1:
+ mp->zeros = 0;
+ idbuff[0] = 0;
+ idbuff[1] = 0;
+ c = fcmbget(&LEN);
+ switch(isascii(c)?sh_lexstates[ST_DOL][c]:S_ALP)
+ {
+ case S_RBRA:
+ if(type<M_SIZE)
+ goto nosub;
+ /* This code handles ${#} */
+ c = mode;
+ mode = type = 0;
+ /* FALL THRU */
+ case S_SPC1:
+ if(type==M_BRACE)
+ {
+ if(isaletter(mode=fcpeek(0)) || mode=='.')
+ {
+ if(c=='#')
+ type = M_SIZE;
+#ifdef SHOPT_TYPEDEF
+ else if(c=='@')
+ {
+ type = M_TYPE;
+ goto retry1;
+ }
+#endif /* SHOPT_TYPEDEF */
+ else
+ type = M_VNAME;
+ mode = c;
+ goto retry1;
+ }
+ else if(c=='#' && (isadigit(mode)||fcpeek(1)==RBRACE))
+ {
+ type = M_SIZE;
+ mode = c;
+ goto retry1;
+ }
+ }
+ /* FALL THRU */
+ case S_SPC2:
+ var = 0;
+ *id = c;
+ v = special(mp->shp,c);
+ if(isastchar(c))
+ {
+ mode = c;
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line)
+ {
+ v = getdolarg(mp->shp,1,(int*)0);
+ dolmax = MAX_ARGN;
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ dolmax = mp->shp->st.dolc+1;
+ mp->atmode = (v && mp->quoted && c=='@');
+ dolg = (v!=0);
+ }
+ break;
+ case S_LBRA:
+ if(type)
+ goto nosub;
+ type = M_BRACE;
+ goto retry1;
+ case S_PAR:
+ if(type)
+ goto nosub;
+ comsubst(mp,(Shnode_t*)0,1);
+ return(1);
+ case S_DIG:
+ var = 0;
+ c -= '0';
+ mp->shp->argaddr = 0;
+ if(type)
+ {
+ register int d;
+ while((d=fcget()),isadigit(d))
+ c = 10*c + (d-'0');
+ fcseek(-1);
+ }
+ idnum = c;
+ if(c==0)
+ v = special(mp->shp,c);
+#if SHOPT_FILESCAN
+ else if(mp->shp->cur_line)
+ {
+ mp->shp->used_pos = 1;
+ v = getdolarg(mp->shp,c,&vsize);
+ }
+#endif /* SHOPT_FILESCAN */
+ else if(c <= mp->shp->st.dolc)
+ {
+ mp->shp->used_pos = 1;
+ v = mp->shp->st.dolv[c];
+ }
+ else
+ v = 0;
+ break;
+ case S_ALP:
+ if(c=='.' && type==0)
+ goto nosub;
+ offset = stktell(stkp);
+ do
+ {
+ register int d;
+ np = 0;
+ do
+ {
+ if(LEN==1)
+ sfputc(stkp,c);
+ else
+ sfwrite(stkp,fcseek(0)-LEN,LEN);
+ }
+ while((d=c,(c=fcmbget(&LEN)),isaname(c))||type && c=='.');
+ while(c==LBRACT && (type||mp->arrayok))
+ {
+ mp->shp->argaddr=0;
+ if((c=fcmbget(&LEN),isastchar(c)) && fcpeek(0)==RBRACT && d!='.')
+ {
+ if(type==M_VNAME)
+ type = M_SUBNAME;
+ idbuff[0] = mode = c;
+ fcget();
+ c = fcmbget(&LEN);
+ if(c=='.' || c==LBRACT)
+ {
+ sfputc(stkp,LBRACT);
+ sfputc(stkp,mode);
+ sfputc(stkp,RBRACT);
+ }
+ else
+ flag = NV_ARRAY;
+ break;
+ }
+ else
+ {
+ fcseek(-LEN);
+ c = stktell(stkp);
+ if(d!='.')
+ sfputc(stkp,LBRACT);
+ v = stkptr(stkp,subcopy(mp,1));
+ if(type && mp->dotdot)
+ {
+ mode = '@';
+ v[-1] = 0;
+ if(type==M_VNAME)
+ type = M_SUBNAME;
+ else if(type==M_SIZE)
+ goto nosub;
+ }
+ else if(d!='.')
+ sfputc(stkp,RBRACT);
+ c = fcmbget(&LEN);
+ if(c==0 && type==M_VNAME)
+ type = M_SUBNAME;
+ }
+ }
+ }
+ while(type && c=='.');
+ if(type!=M_VNAME && c==RBRACE && type && fcpeek(-2)=='.')
+ {
+ /* ${x.} or ${x..} */
+ if(fcpeek(-3) == '.')
+ {
+ stkseek(stkp,stktell(stkp)-2);
+ nv_local = 1;
+ }
+ else
+ {
+ stkseek(stkp,stktell(stkp)-1);
+ type = M_TREE;
+ }
+ }
+ sfputc(stkp,0);
+ id=stkptr(stkp,offset);
+ if(isastchar(c) && type)
+ {
+ if(type==M_VNAME || type==M_SIZE)
+ {
+ idbuff[0] = mode = c;
+ if((d=fcpeek(0))==c)
+ idbuff[1] = fcget();
+ if(type==M_VNAME)
+ type = M_NAMESCAN;
+ else
+ type = M_NAMECOUNT;
+ break;
+ }
+ goto nosub;
+ }
+ flag |= NV_NOASSIGN|NV_VARNAME|NV_NOADD;
+ if(c=='=' || c=='?' || (c==':' && ((d=fcpeek(0))=='=' || d=='?')))
+ {
+ if(c=='=' || (c==':' && d=='='))
+ flag |= NV_ASSIGN;
+ flag &= ~NV_NOADD;
+ }
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line && *id=='R' && strcmp(id,"REPLY")==0)
+ {
+ mp->shp->argaddr=0;
+ np = REPLYNOD;
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ {
+ if(mp->shp->argaddr)
+ flag &= ~NV_NOADD;
+ np = nv_open(id,mp->shp->var_tree,flag|NV_NOFAIL);
+ if(!np)
+ {
+ sfprintf(mp->shp->strbuf,"%s%c",id,0);
+ id = sfstruse(mp->shp->strbuf);
+ }
+ }
+ if(isastchar(mode))
+ var = 0;
+ if((!np || nv_isnull(np)) && type==M_BRACE && c==RBRACE && !(flag&NV_ARRAY) && strchr(id,'.'))
+ {
+ if(sh_macfun(mp->shp,id,offset))
+ {
+ fcmbget(&LEN);
+ return(1);
+ }
+ }
+ if(np && (flag&NV_NOADD) && nv_isnull(np))
+ {
+ if(nv_isattr(np,NV_NOFREE))
+ nv_offattr(np,NV_NOFREE);
+#if SHOPT_FILESCAN
+ else if(np!=REPLYNOD || !mp->shp->cur_line)
+#else
+ else
+#endif /* SHOPT_FILESCAN */
+ np = 0;
+ }
+ ap = np?nv_arrayptr(np):0;
+ if(type)
+ {
+ if(mp->dotdot)
+ {
+ Namval_t *nq;
+#if SHOPT_FIXEDARRAY
+ if(ap && !ap->fixed && (nq=nv_opensub(np)))
+#else
+ if(ap && (nq=nv_opensub(np)))
+#endif /* SHOPT_FIXEDARRAY */
+ ap = nv_arrayptr(np=nq);
+ if(ap)
+ {
+ nv_putsub(np,v,ARRAY_SCAN);
+ v = stkptr(stkp,mp->dotdot);
+ dolmax =1;
+ if(array_assoc(ap))
+ arrmax = strdup(v);
+ else if((dolmax = (int)sh_arith(mp->shp,v))<0)
+ dolmax += array_maxindex(np);
+ if(type==M_SUBNAME)
+ bysub = 1;
+ }
+ else
+ {
+ if((int)sh_arith(mp->shp,v))
+ np = 0;
+ }
+ }
+ else if(ap && (isastchar(mode)||type==M_TREE) && !(ap->nelem&ARRAY_SCAN) && type!=M_SIZE)
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ if(!isbracechar(c))
+ goto nosub;
+ else
+ fcseek(-LEN);
+ }
+ else
+ fcseek(-1);
+ if(type<=1 && np && nv_isvtree(np) && mp->pattern==1 && !mp->split)
+ {
+ int cc=fcmbget(&LEN),peek=LEN;
+ if(type && cc=='}')
+ {
+ cc = fcmbget(&LEN);
+ peek++;
+ }
+ if(mp->quote && cc=='"')
+ {
+ cc = fcmbget(&LEN);
+ peek++;
+ }
+ fcseek(-peek);
+ if(cc==0)
+ mp->assign = 1;
+ }
+ if((type==M_VNAME||type==M_SUBNAME) && mp->shp->argaddr && strcmp(nv_name(np),id))
+ mp->shp->argaddr = 0;
+ c = (type>M_BRACE && isastchar(mode));
+ if(np && (type==M_TREE || !c || !ap))
+ {
+ char *savptr;
+ c = *((unsigned char*)stkptr(stkp,offset-1));
+ savptr = stkfreeze(stkp,0);
+ if(type==M_VNAME || (type==M_SUBNAME && ap))
+ {
+ type = M_BRACE;
+ v = nv_name(np);
+ if(ap && !mp->dotdot && !(ap->nelem&ARRAY_UNDEF))
+ addsub = 1;
+ }
+#ifdef SHOPT_TYPEDEF
+ else if(type==M_TYPE)
+ {
+ Namval_t *nq = nv_type(np);
+ type = M_BRACE;
+ if(nq)
+ nv_typename(nq,mp->shp->strbuf);
+ else
+ nv_attribute(np,mp->shp->strbuf,"typeset",1);
+ v = sfstruse(mp->shp->strbuf);
+ }
+#endif /* SHOPT_TYPEDEF */
+#if SHOPT_FILESCAN
+ else if(mp->shp->cur_line && np==REPLYNOD)
+ v = mp->shp->cur_line;
+#endif /* SHOPT_FILESCAN */
+ else if(type==M_TREE)
+ v = nv_getvtree(np,(Namfun_t*)0);
+ else
+ {
+ if(type && fcpeek(0)=='+')
+ {
+ if(ap)
+ v = nv_arrayisset(np,ap)?(char*)"x":0;
+ else
+ v = nv_isnull(np)?0:(char*)"x";
+ }
+ else
+ v = nv_getval(np);
+ mp->atmode = (v && mp->quoted && mode=='@');
+ /* special case --- ignore leading zeros */
+ if( (mp->arith||mp->let) && (np->nvfun || nv_isattr(np,(NV_LJUST|NV_RJUST|NV_ZFILL))) && !nv_isattr(np,NV_INTEGER) && (offset==0 || !isalnum(c)))
+ mp->zeros = 1;
+ }
+ if(savptr==stakptr(0))
+ stkseek(stkp,offset);
+ else
+ stkset(stkp,savptr,offset);
+ }
+ else
+ {
+ if(sh_isoption(SH_NOUNSET) && !isastchar(mode) && (type==M_VNAME || type==M_SIZE))
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ v = 0;
+ if(type==M_VNAME)
+ {
+ v = id;
+ type = M_BRACE;
+ }
+ else if(type==M_TYPE)
+ type = M_BRACE;
+ }
+ stkseek(stkp,offset);
+ if(ap)
+ {
+#if SHOPT_OPTIMIZE
+ if(mp->shp->argaddr)
+ nv_optimize(np);
+#endif
+ if(isastchar(mode) && array_elem(ap)> !c)
+ dolg = -1;
+ else
+ dolg = 0;
+ }
+ break;
+ case S_EOF:
+ fcseek(-1);
+ default:
+ goto nosub;
+ }
+ c = fcmbget(&LEN);
+ if(type>M_TREE)
+ {
+ if(c!=RBRACE)
+ mac_error(np);
+ if(type==M_NAMESCAN || type==M_NAMECOUNT)
+ {
+ mp->shp->last_root = mp->shp->var_tree;
+ id = idx = prefix(mp->shp,id);
+ stkseek(stkp,offset);
+ if(type==M_NAMECOUNT)
+ {
+ c = namecount(mp,id);
+ v = ltos(c);
+ }
+ else
+ {
+ dolmax = strlen(id);
+ dolg = -1;
+ nextname(mp,id,0);
+ v = nextname(mp,id,dolmax);
+ }
+ }
+ else if(type==M_SUBNAME)
+ {
+ if(dolg<0)
+ {
+ v = nv_getsub(np);
+ bysub=1;
+ }
+ else if(v)
+ {
+ if(!ap || isastchar(mode))
+ v = "0";
+ else
+ v = nv_getsub(np);
+ }
+ }
+ else
+ {
+ if(!isastchar(mode))
+ c = charlen(v,vsize);
+ else if(dolg>0)
+ {
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line)
+ {
+ getdolarg(mp->shp,MAX_ARGN,(int*)0);
+ c = mp->shp->offsets[0];
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ c = mp->shp->st.dolc;
+ }
+ else if(dolg<0)
+ c = array_elem(ap);
+ else
+ c = (v!=0);
+ dolg = dolmax = 0;
+ v = ltos(c);
+ }
+ c = RBRACE;
+ }
+ nulflg = 0;
+ if(type && c==':')
+ {
+ c = fcmbget(&LEN);
+ if(isascii(c) &&sh_lexstates[ST_BRACE][c]==S_MOD1 && c!='*' && c!= ':')
+ nulflg=1;
+ else if(c!='%' && c!='#')
+ {
+ fcseek(-LEN);
+ c = ':';
+ }
+ }
+ if(type)
+ {
+ if(!isbracechar(c))
+ {
+ if(!nulflg)
+ mac_error(np);
+ fcseek(-LEN);
+ c = ':';
+ }
+ if(c!=RBRACE)
+ {
+ int newops = (c=='#' || c == '%' || c=='/');
+ offset = stktell(stkp);
+ if(newops && sh_isoption(SH_NOUNSET) && *id && id!=idbuff && (!np || nv_isnull(np)))
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ if(c=='/' ||c==':' || ((!v || (nulflg && *v==0)) ^ (c=='+'||c=='#'||c=='%')))
+ {
+ int newquote = mp->quote;
+ int split = mp->split;
+ int quoted = mp->quoted;
+ int arith = mp->arith;
+ int zeros = mp->zeros;
+ int assign = mp->assign;
+ if(newops)
+ {
+ type = fcget();
+ if(type=='%' || type=='#')
+ {
+ int d = fcmbget(&LEN);
+ fcseek(-LEN);
+ if(d=='(')
+ type = 0;
+ }
+ fcseek(-1);
+ mp->pattern = 1+(c=='/');
+ mp->split = 0;
+ mp->quoted = 0;
+ mp->assign &= ~1;
+ mp->arith = mp->zeros = 0;
+ newquote = 0;
+ }
+ else if(c=='?' || c=='=')
+ mp->split = mp->pattern = 0;
+ copyto(mp,RBRACE,newquote);
+ if(!oldpat)
+ mp->patfound = 0;
+ mp->pattern = oldpat;
+ mp->split = split;
+ mp->quoted = quoted;
+ mp->arith = arith;
+ mp->zeros = zeros;
+ mp->assign = assign;
+ /* add null byte */
+ sfputc(stkp,0);
+ stkseek(stkp,stktell(stkp)-1);
+ }
+ else
+ {
+ sh_lexskip(lp,RBRACE,0,(!newops&&mp->quote)?ST_QUOTE:ST_NESTED);
+ stkseek(stkp,offset);
+ }
+ argp=stkptr(stkp,offset);
+ }
+ }
+ else
+ {
+ fcseek(-1);
+ c=0;
+ }
+ if(c==':') /* ${name:expr1[:expr2]} */
+ {
+ char *ptr;
+ type = (int)sh_strnum(argp,&ptr,1);
+ if(isastchar(mode))
+ {
+ if(id==idbuff) /* ${@} or ${*} */
+ {
+ if(type<0 && (type+= dolmax)<0)
+ type = 0;
+ if(type==0)
+ v = special(mp->shp,dolg=0);
+#if SHOPT_FILESCAN
+ else if(mp->shp->cur_line)
+ {
+ v = getdolarg(mp->shp,dolg=type,&vsize);
+ if(!v)
+ dolmax = type;
+ }
+#endif /* SHOPT_FILESCAN */
+ else if(type < dolmax)
+ v = mp->shp->st.dolv[dolg=type];
+ else
+ v = 0;
+ }
+ else if(ap)
+ {
+ if(type<0)
+ {
+ if(array_assoc(ap))
+ type = -type;
+ else
+ type += array_maxindex(np);
+ }
+ if(array_assoc(ap))
+ {
+ while(type-- >0 && (v=0,nv_nextsub(np)))
+ v = nv_getval(np);
+ }
+ else if(type > 0)
+ {
+ if(nv_putsub(np,NIL(char*),type|ARRAY_SCAN))
+ v = nv_getval(np);
+ else
+ v = 0;
+ }
+ }
+ else if(type>0)
+ v = 0;
+ if(!v)
+ mp->atmode = 0;
+ }
+ else if(v)
+ {
+ vsize = charlen(v,vsize);
+ if(type<0 && (type += vsize)<0)
+ type = 0;
+ if(vsize < type)
+ v = 0;
+#if SHOPT_MULTIBYTE
+ else if(mbwide())
+ {
+ mbinit();
+ for(c=type;c;c--)
+ mbchar(v);
+ c = ':';
+ }
+#endif /* SHOPT_MULTIBYTE */
+ else
+ v += type;
+ vsize = v?strlen(v):0;
+ }
+ if(*ptr==':')
+ {
+ if((type = (int)sh_strnum(ptr+1,&ptr,1)) <=0)
+ v = 0;
+ else if(isastchar(mode))
+ {
+ if(dolg>=0)
+ {
+ if(dolg+type < dolmax)
+ dolmax = dolg+type;
+ }
+ else
+ dolmax = type;
+ }
+ else if(type < vsize)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ char *vp = v;
+ mbinit();
+ while(type-->0)
+ {
+ if((c=mbsize(vp))<1)
+ c = 1;
+ vp += c;
+ }
+ type = vp-v;
+ c = ':';
+ }
+#endif /* SHOPT_MULTIBYTE */
+ vsize = type;
+ }
+ else
+ vsize = v?strlen(v):0;
+ }
+ if(*ptr)
+ mac_error(np);
+ stkseek(stkp,offset);
+ argp = 0;
+ }
+ /* check for substring operations */
+ else if(c == '#' || c == '%' || c=='/')
+ {
+ if(c=='/')
+ {
+ if(type=='/' || type=='#' || type=='%')
+ {
+ c = type;
+ type = '/';
+ argp++;
+ }
+ else
+ type = 0;
+ }
+ else
+ {
+ if(type==c) /* ## or %% */
+ argp++;
+ else
+ type = 0;
+ }
+ pattern = strdup(argp);
+ if((type=='/' || c=='/') && (repstr = mac_getstring(pattern)))
+ {
+ Mac_t savemac;
+ char *first = fcseek(0);
+ int n = stktell(stkp);
+ savemac = *mp;
+ fcsopen(repstr);
+ mp->pattern = 3;
+ mp->split = 0;
+ copyto(mp,0,0);
+ sfputc(stkp,0);
+ repstr = strdup(stkptr(stkp,n));
+ replen = strlen(repstr);
+ stkseek(stkp,n);
+ *mp = savemac;
+ fcsopen(first);
+ }
+ if(v || c=='/' && offset>=0)
+ stkseek(stkp,offset);
+ }
+ /* check for quoted @ */
+ if(mode=='@' && mp->quote && !v && c!='-')
+ mp->quoted-=2;
+retry2:
+ if(v && (!nulflg || *v ) && c!='+')
+ {
+ register int d = (mode=='@'?' ':mp->ifs);
+ int match[2*(MATCH_MAX+1)], nmatch, nmatch_prev, vsize_last;
+ char *vlast;
+ while(1)
+ {
+ if(!v)
+ v= "";
+ if(c=='/' || c=='#' || c== '%')
+ {
+ int index = 0;
+ flag = (type || c=='/')?(STR_GROUP|STR_MAXIMAL):STR_GROUP;
+ if(c!='/')
+ flag |= STR_LEFT;
+ nmatch = 0;
+ while(1)
+ {
+ vsize = strlen(v);
+ nmatch_prev = nmatch;
+ if(c=='%')
+ nmatch=substring(v,pattern,match,flag&STR_MAXIMAL);
+ else
+ nmatch=strgrpmatch(v,pattern,match,elementsof(match)/2,flag);
+ if(nmatch && replen>0)
+ sh_setmatch(mp->shp,v,vsize,nmatch,match,index++);
+ if(nmatch)
+ {
+ vlast = v;
+ vsize_last = vsize;
+ vsize = match[0];
+ }
+ else if(c=='#')
+ vsize = 0;
+ if(vsize)
+ mac_copy(mp,v,vsize);
+ if(nmatch && replen>0 && (match[1] || !nmatch_prev))
+ mac_substitute(mp,repstr,v,match,nmatch);
+ if(nmatch==0)
+ v += vsize;
+ else
+ v += match[1];
+ if(*v && c=='/' && type)
+ {
+ /* avoid infinite loop */
+ if(nmatch && match[1]==0)
+ {
+ nmatch = 0;
+ mac_copy(mp,v,1);
+ v++;
+ }
+ continue;
+ }
+ vsize = -1;
+ break;
+ }
+ if(replen==0)
+ sh_setmatch(mp->shp,vlast,vsize_last,nmatch,match,index++);
+ }
+ if(vsize)
+ mac_copy(mp,v,vsize>0?vsize:strlen(v));
+ if(addsub)
+ {
+ mp->shp->instance++;
+ sfprintf(mp->shp->strbuf,"[%s]",nv_getsub(np));
+ mp->shp->instance--;
+ v = sfstruse(mp->shp->strbuf);
+ mac_copy(mp, v, strlen(v));
+ }
+ if(dolg==0 && dolmax==0)
+ break;
+ if(mp->dotdot)
+ {
+ if(nv_nextsub(np) == 0)
+ break;
+ if(bysub)
+ v = nv_getsub(np);
+ else
+ v = nv_getval(np);
+ if(array_assoc(ap))
+ {
+ if(strcmp(bysub?v:nv_getsub(np),arrmax)>0)
+ break;
+ }
+ else
+ {
+ if(nv_aindex(np) > dolmax)
+ break;
+ }
+ }
+ else if(dolg>=0)
+ {
+ if(++dolg >= dolmax)
+ break;
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line)
+ {
+ if(dolmax==MAX_ARGN && isastchar(mode))
+ break;
+ if(!(v=getdolarg(mp->shp,dolg,&vsize)))
+ {
+ dolmax = dolg;
+ break;
+ }
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ v = mp->shp->st.dolv[dolg];
+ }
+ else if(!np)
+ {
+ if(!(v = nextname(mp,id,dolmax)))
+ break;
+ }
+ else
+ {
+ if(dolmax && --dolmax <=0)
+ {
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ break;
+ }
+ if(ap)
+ ap->nelem |= ARRAY_SCAN;
+ if(nv_nextsub(np) == 0)
+ break;
+ if(bysub)
+ v = nv_getsub(np);
+ else
+ v = nv_getval(np);
+ }
+ if(mp->split && (!mp->quote || mode=='@'))
+ {
+ if(!np)
+ mp->pattern = 0;
+ endfield(mp,mp->quoted);
+ mp->atmode = mode=='@';
+ mp->pattern = oldpat;
+ }
+ else if(d)
+ {
+ if(mp->sp)
+ sfputc(mp->sp,d);
+ else
+ sfputc(stkp,d);
+ }
+ }
+ if(arrmax)
+ free((void*)arrmax);
+ }
+ else if(argp)
+ {
+ if(c=='/' && replen>0 && pattern && strmatch("",pattern))
+ mac_substitute(mp,repstr,v,0,0);
+ if(c=='?')
+ {
+ if(np)
+ id = nv_name(np);
+ else if(idnum)
+ id = ltos(idnum);
+ if(*argp)
+ {
+ sfputc(stkp,0);
+ errormsg(SH_DICT,ERROR_exit(1),"%s: %s",id,argp);
+ }
+ else if(v)
+ errormsg(SH_DICT,ERROR_exit(1),e_nullset,id);
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ }
+ else if(c=='=')
+ {
+ if(np)
+ {
+ if(mp->shp->subshell)
+ np = sh_assignok(np,1);
+ nv_putval(np,argp,0);
+ v = nv_getval(np);
+ nulflg = 0;
+ stkseek(stkp,offset);
+ goto retry2;
+ }
+ else
+ mac_error(np);
+ }
+ }
+ else if(var && sh_isoption(SH_NOUNSET) && type<=M_TREE && (!np || nv_isnull(np) || (nv_isarray(np) && !np->nvalue.cp)))
+ {
+ if(np)
+ {
+ if(nv_isarray(np))
+ {
+ sfprintf(mp->shp->strbuf,"%s[%s]\0",nv_name(np),nv_getsub(np));
+ id = sfstruse(mp->shp->strbuf);
+ }
+ else
+ id = nv_name(np);
+ nv_close(np);
+ }
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ }
+ if(np)
+ nv_close(np);
+ if(pattern)
+ free(pattern);
+ if(repstr)
+ free(repstr);
+ if(idx)
+ free(idx);
+ return(1);
+nosub:
+ if(type==M_BRACE && sh_lexstates[ST_NORM][c]==S_BREAK)
+ {
+ fcseek(-1);
+ comsubst(mp,(Shnode_t*)0,2);
+ return(1);
+ }
+ if(type)
+ mac_error(np);
+ fcseek(-1);
+ nv_close(np);
+ return(0);
+}
+
+/*
+ * This routine handles command substitution
+ * <type> is 0 for older `...` version
+ */
+static void comsubst(Mac_t *mp,register Shnode_t* t, int type)
+{
+ Sfdouble_t num;
+ register int c;
+ register char *str;
+ Sfio_t *sp;
+ Stk_t *stkp = mp->shp->stk;
+ Fcin_t save;
+ struct slnod *saveslp = mp->shp->st.staklist;
+ struct _mac_ savemac;
+ int savtop = stktell(stkp);
+ char lastc=0, *savptr = stkfreeze(stkp,0);
+#if SHOPT_MULTIBYTE
+ wchar_t lastw=0;
+#endif /* SHOPT_MULTIBYTE */
+ int was_history = sh_isstate(SH_HISTORY);
+ int was_verbose = sh_isstate(SH_VERBOSE);
+ int was_interactive = sh_isstate(SH_INTERACTIVE);
+ int newlines,bufsize,nextnewlines;
+ Namval_t *np;
+ mp->shp->argaddr = 0;
+ savemac = *mp;
+ mp->shp->st.staklist=0;
+#ifdef SHOPT_COSHELL
+ if(mp->shp->inpool)
+ return;
+#endif /*SHOPT_COSHELL */
+ if(type)
+ {
+ sp = 0;
+ fcseek(-1);
+ if(!t)
+ t = sh_dolparen((Lex_t*)mp->shp->lex_context);
+ if(t && t->tre.tretyp==TARITH)
+ {
+ mp->shp->inarith = 1;
+ fcsave(&save);
+ if(t->ar.arcomp)
+ num = arith_exec(t->ar.arcomp);
+ else if((t->ar.arexpr->argflag&ARG_RAW))
+ num = sh_arith(mp->shp,t->ar.arexpr->argval);
+ else
+ num = sh_arith(mp->shp,sh_mactrim(mp->shp,t->ar.arexpr->argval,3));
+ mp->shp->inarith = 0;
+ out_offset:
+ stkset(stkp,savptr,savtop);
+ *mp = savemac;
+ if((Sflong_t)num!=num)
+ sfprintf(mp->shp->strbuf,"%.*Lg",LDBL_DIG,num);
+ else if(num)
+ sfprintf(mp->shp->strbuf,"%lld",(Sflong_t)num);
+ else
+ sfprintf(mp->shp->strbuf,"%Lg",num);
+ str = sfstruse(mp->shp->strbuf);
+ mac_copy(mp,str,strlen(str));
+ mp->shp->st.staklist = saveslp;
+ fcrestore(&save);
+ return;
+ }
+ }
+ else
+ {
+ while(fcgetc(c)!='`' && c)
+ {
+ if(c==ESCAPE)
+ {
+ fcgetc(c);
+ if(!(isescchar(sh_lexstates[ST_QUOTE][c]) ||
+ (c=='"' && mp->quote)))
+ sfputc(stkp,ESCAPE);
+ }
+ sfputc(stkp,c);
+ }
+ c = stktell(stkp);
+ str=stkfreeze(stkp,1);
+ /* disable verbose and don't save in history file */
+ sh_offstate(SH_HISTORY);
+ sh_offstate(SH_VERBOSE);
+ if(mp->sp)
+ sfsync(mp->sp); /* flush before executing command */
+ sp = sfnew(NIL(Sfio_t*),str,c,-1,SF_STRING|SF_READ);
+ c = mp->shp->inlineno;
+ mp->shp->inlineno = error_info.line+mp->shp->st.firstline;
+ t = (Shnode_t*)sh_parse(mp->shp, sp,SH_EOF|SH_NL);
+ mp->shp->inlineno = c;
+ type = 1;
+ }
+#if KSHELL
+ if(t)
+ {
+ fcsave(&save);
+ sfclose(sp);
+ if(t->tre.tretyp==0 && !t->com.comarg && !t->com.comset)
+ {
+ /* special case $(<file) and $(<#file) */
+ register int fd;
+ int r;
+ struct checkpt buff;
+ struct ionod *ip=0;
+ sh_pushcontext(mp->shp,&buff,SH_JMPIO);
+ if((ip=t->tre.treio) &&
+ ((ip->iofile&IOLSEEK) || !(ip->iofile&IOUFD)) &&
+ (r=sigsetjmp(buff.buff,0))==0)
+ fd = sh_redirect(mp->shp,ip,3);
+ else
+ fd = sh_chkopen(e_devnull);
+ sh_popcontext(mp->shp,&buff);
+ if(r==0 && ip && (ip->iofile&IOLSEEK))
+ {
+ if(sp=mp->shp->sftable[fd])
+ num = sftell(sp);
+ else
+ num = lseek(fd, (off_t)0, SEEK_CUR);
+ goto out_offset;
+ }
+ sp = sfnew(NIL(Sfio_t*),(char*)malloc(IOBSIZE+1),IOBSIZE,fd,SF_READ|SF_MALLOC);
+ type = 3;
+ }
+ else
+ sp = sh_subshell(mp->shp,t,sh_isstate(SH_ERREXIT),type);
+ fcrestore(&save);
+ }
+ else
+ sp = sfopen(NIL(Sfio_t*),"","sr");
+ sh_freeup(mp->shp);
+ mp->shp->st.staklist = saveslp;
+ if(was_history)
+ sh_onstate(SH_HISTORY);
+ if(was_verbose)
+ sh_onstate(SH_VERBOSE);
+#else
+ sp = sfpopen(NIL(Sfio_t*),str,"r");
+#endif
+ *mp = savemac;
+ np = sh_scoped(mp->shp,IFSNOD);
+ nv_putval(np,mp->ifsp,NV_RDONLY);
+ mp->ifsp = nv_getval(np);
+ stkset(stkp,savptr,savtop);
+ newlines = 0;
+ sfsetbuf(sp,(void*)sp,0);
+ bufsize = sfvalue(sp);
+ /* read command substitution output and put on stack or here-doc */
+ sfpool(sp, NIL(Sfio_t*), SF_WRITE);
+ sh_offstate(SH_INTERACTIVE);
+ while((str=(char*)sfreserve(sp,SF_UNBOUND,0)) && (c=bufsize=sfvalue(sp))>0)
+ {
+#if SHOPT_CRNL
+ /* eliminate <cr> */
+ register char *dp;
+ char *buff = str;
+ while(c>1 && (*str !='\r'|| str[1]!='\n'))
+ {
+ c--;
+ str++;
+ }
+ dp = str;
+ while(c>1)
+ {
+ str++;
+ c--;
+ while(c>1 && (*str!='\r' || str[1]!='\n'))
+ {
+ c--;
+ *dp++ = *str++;
+ }
+ }
+ if(c)
+ *dp++ = *str++;
+ str = buff;
+ c = dp-str;
+#endif /* SHOPT_CRNL */
+ /* delay appending trailing new-lines */
+ for(nextnewlines=0; c-->0 && str[c]=='\n'; nextnewlines++);
+ if(c < 0)
+ {
+ newlines += nextnewlines;
+ continue;
+ }
+ if(newlines >0)
+ {
+ if(mp->sp)
+ sfnputc(mp->sp,'\n',newlines);
+ else if(!mp->quote && mp->split && mp->shp->ifstable['\n'])
+ endfield(mp,0);
+ else
+ sfnputc(stkp,'\n',newlines);
+ }
+ else if(lastc)
+ {
+#if SHOPT_MULTIBYTE
+ if(lastw)
+ {
+ int n;
+ char mb[8];
+ n = mbconv(mb, lastw);
+ mac_copy(mp,mb,n);
+ lastw = 0;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ mac_copy(mp,&lastc,1);
+ lastc = 0;
+ }
+ newlines = nextnewlines;
+ if(++c < bufsize)
+ str[c] = 0;
+ else
+ {
+ ssize_t len = 1;
+
+ /* can't write past buffer so save last character */
+#if SHOPT_MULTIBYTE
+ if ((len = mbsize(str))>1)
+ {
+ len = mb2wc(lastw,str,len);
+ if (len < 0)
+ {
+ lastw = 0;
+ len = 1;
+ }
+ }
+#endif /* SHOPT_MULTIBYTE */
+ c -= len;
+ lastc = str[c];
+ str[c] = 0;
+ }
+ mac_copy(mp,str,c);
+ }
+ if(was_interactive)
+ sh_onstate(SH_INTERACTIVE);
+ if(--newlines>0 && mp->shp->ifstable['\n']==S_DELIM)
+ {
+ if(mp->sp)
+ sfnputc(mp->sp,'\n',newlines);
+ else if(!mp->quote && mp->split)
+ while(newlines--)
+ endfield(mp,1);
+ else
+ sfnputc(stkp,'\n',newlines);
+ }
+ if(lastc)
+ {
+#if SHOPT_MULTIBYTE
+ if(lastw)
+ {
+ int n;
+ char mb[8];
+ n = mbconv(mb, lastw);
+ mac_copy(mp,mb,n);
+ lastw = 0;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ mac_copy(mp,&lastc,1);
+ lastc = 0;
+ }
+ sfclose(sp);
+ return;
+}
+
+/*
+ * copy <str> onto the stack
+ */
+static void mac_copy(register Mac_t *mp,register const char *str, register int size)
+{
+ register char *state;
+ register const char *cp=str;
+ register int c,n,nopat,len;
+ Stk_t *stkp=mp->shp->stk;
+ int oldpat = mp->pattern;
+ nopat = (mp->quote||(mp->assign==1)||mp->arith);
+ if(mp->zeros)
+ {
+ /* prevent leading 0's from becomming octal constants */
+ while(size>1 && *str=='0')
+ str++,size--;
+ mp->zeros = 0;
+ cp = str;
+ }
+ if(mp->sp)
+ sfwrite(mp->sp,str,size);
+ else if(mp->pattern>=2 || (mp->pattern && nopat) || mp->assign==3)
+ {
+ state = sh_lexstates[ST_MACRO];
+ /* insert \ before file expansion characters */
+ while(size-->0)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide() && (len=mbsize(cp))>1)
+ {
+ cp += len;
+ size -= (len-1);
+ continue;
+ }
+#endif
+ c = state[n= *(unsigned char*)cp++];
+ if(mp->assign==3 && mp->pattern!=4)
+ {
+ if(c==S_BRACT)
+ {
+ nopat = 0;
+ mp->pattern = 4;
+ }
+ continue;
+ }
+ if(nopat&&(c==S_PAT||c==S_ESC||c==S_BRACT||c==S_ENDCH) && mp->pattern!=3)
+ c=1;
+ else if(mp->pattern==4 && (c==S_ESC||c==S_BRACT||c==S_ENDCH || isastchar(n)))
+ {
+ if(c==S_ENDCH && oldpat!=4)
+ {
+ if(*cp==0 || *cp=='.' || *cp=='[')
+ {
+ mp->pattern = oldpat;
+ c=0;
+ }
+ else
+ c=1;
+ }
+ else
+ c=1;
+ }
+ else if(mp->pattern==2 && c==S_SLASH)
+ c=1;
+ else if(mp->pattern==3 && c==S_ESC && (state[*(unsigned char*)cp]==S_DIG||(*cp==ESCAPE)))
+ {
+ if(!(c=mp->quote))
+ cp++;
+ }
+ else
+ c=0;
+ if(c)
+ {
+ if(c = (cp-1) - str)
+ sfwrite(stkp,str,c);
+ sfputc(stkp,ESCAPE);
+ str = cp-1;
+ }
+ }
+ if(c = cp-str)
+ sfwrite(stkp,str,c);
+ }
+ else if(!mp->quote && mp->split && (mp->ifs||mp->pattern))
+ {
+ /* split words at ifs characters */
+ state = mp->shp->ifstable;
+ if(mp->pattern)
+ {
+ char *sp = "&|()";
+ while(c = *sp++)
+ {
+ if(state[c]==0)
+ state[c] = S_EPAT;
+ }
+ sp = "*?[{";
+ while(c = *sp++)
+ {
+ if(state[c]==0)
+ state[c] = S_PAT;
+ }
+ if(state[ESCAPE]==0)
+ state[ESCAPE] = S_ESC;
+ }
+ while(size-->0)
+ {
+ n=state[c= *(unsigned char*)cp++];
+#if SHOPT_MULTIBYTE
+ if(mbwide() && n!=S_MBYTE && (len=mbsize(cp-1))>1)
+ {
+ sfwrite(stkp,cp-1, len);
+ cp += --len;
+ size -= len;
+ continue;
+ }
+#endif
+ if(n==S_ESC || n==S_EPAT)
+ {
+ /* don't allow extended patterns in this case */
+ mp->patfound = mp->pattern;
+ sfputc(stkp,ESCAPE);
+ }
+ else if(n==S_PAT)
+ mp->patfound = mp->pattern;
+ else if(n && mp->ifs)
+ {
+#if SHOPT_MULTIBYTE
+ if(n==S_MBYTE)
+ {
+ if(sh_strchr(mp->ifsp,cp-1)<0)
+ continue;
+ n = mbsize(cp-1) - 1;
+ if(n==-2)
+ n = 0;
+ cp += n;
+ size -= n;
+ n= S_DELIM;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if(n==S_SPACE || n==S_NL)
+ {
+ while(size>0 && ((n=state[c= *(unsigned char*)cp++])==S_SPACE||n==S_NL))
+ size--;
+#if SHOPT_MULTIBYTE
+ if(n==S_MBYTE && sh_strchr(mp->ifsp,cp-1)>=0)
+ {
+ n = mbsize(cp-1) - 1;
+ if(n==-2)
+ n = 0;
+ cp += n;
+ size -= n;
+ n=S_DELIM;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ if(n==S_DELIM)
+ size--;
+ }
+ endfield(mp,n==S_DELIM||mp->quoted);
+ mp->patfound = 0;
+ if(n==S_DELIM)
+ while(size>0 && ((n=state[c= *(unsigned char*)cp++])==S_SPACE||n==S_NL))
+ size--;
+ if(size<=0)
+ break;
+ cp--;
+ continue;
+
+ }
+ sfputc(stkp,c);
+ }
+ if(mp->pattern)
+ {
+ cp = "&|()";
+ while(c = *cp++)
+ {
+ if(state[c]==S_EPAT)
+ state[c] = 0;
+ }
+ cp = "*?[{";
+ while(c = *cp++)
+ {
+ if(state[c]==S_PAT)
+ state[c] = 0;
+ }
+ if(mp->shp->ifstable[ESCAPE]==S_ESC)
+ mp->shp->ifstable[ESCAPE] = 0;
+ }
+ }
+ else
+ sfwrite(stkp,str,size);
+}
+
+/*
+ * Terminate field.
+ * If field is null count field if <split> is non-zero
+ * Do filename expansion of required
+ */
+static void endfield(register Mac_t *mp,int split)
+{
+ register struct argnod *argp;
+ register int count=0;
+ Stk_t *stkp = mp->shp->stk;
+ if(stktell(stkp) > ARGVAL || split)
+ {
+ argp = (struct argnod*)stkfreeze(stkp,1);
+ argp->argnxt.cp = 0;
+ argp->argflag = 0;
+ mp->atmode = 0;
+ if(mp->patfound)
+ {
+ mp->shp->argaddr = 0;
+#if SHOPT_BRACEPAT
+ count = path_generate(mp->shp,argp,mp->arghead);
+#else
+ count = path_expand(mp->shp,argp->argval,mp->arghead);
+#endif /* SHOPT_BRACEPAT */
+ if(count)
+ mp->fields += count;
+ else if(split) /* pattern is null string */
+ *argp->argval = 0;
+ else /* pattern expands to nothing */
+ count = -1;
+ }
+ if(count==0)
+ {
+ argp->argchn.ap = *mp->arghead;
+ *mp->arghead = argp;
+ mp->fields++;
+ }
+ if(count>=0)
+ {
+ (*mp->arghead)->argflag |= ARG_MAKE;
+ if(mp->assign || sh_isoption(SH_NOGLOB))
+ argp->argflag |= ARG_RAW|ARG_EXP;
+ }
+ stkseek(stkp,ARGVAL);
+ }
+ mp->quoted = mp->quote;
+}
+
+/*
+ * Finds the right substring of STRING using the expression PAT
+ * the longest substring is found when FLAG is set.
+ */
+static int substring(register const char *string,const char *pat,int match[], int flag)
+{
+ register const char *sp=string;
+ register int size,len,nmatch,n;
+ int smatch[2*(MATCH_MAX+1)];
+ if(flag)
+ {
+ if(n=strgrpmatch(sp,pat,smatch,elementsof(smatch)/2,STR_RIGHT|STR_MAXIMAL))
+ {
+ memcpy(match,smatch,n*2*sizeof(smatch[0]));
+ return(n);
+ }
+ return(0);
+ }
+ size = len = strlen(sp);
+ sp += size;
+ while(sp>=string)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ sp = lastchar(string,sp);
+#endif /* SHOPT_MULTIBYTE */
+ if(n=strgrpmatch(sp,pat,smatch,elementsof(smatch)/2,STR_RIGHT|STR_LEFT|STR_MAXIMAL))
+ {
+ nmatch = n;
+ memcpy(match,smatch,n*2*sizeof(smatch[0]));
+ size = sp-string;
+ break;
+ }
+ sp--;
+ }
+ if(size==len)
+ return(0);
+ if(nmatch)
+ {
+ nmatch *=2;
+ while(--nmatch>=0)
+ match[nmatch] += size;
+ }
+ return(n);
+}
+
+#if SHOPT_MULTIBYTE
+ static char *lastchar(const char *string, const char *endstring)
+ {
+ register char *str = (char*)string;
+ register int c;
+ mbinit();
+ while(*str)
+ {
+ if((c=mbsize(str))<0)
+ c = 1;
+ if(str+c > endstring)
+ break;
+ str += c;
+ }
+ return(str);
+ }
+#endif /* SHOPT_MULTIBYTE */
+static int charlen(const char *string,int len)
+{
+ if(!string)
+ return(0);
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ register const char *str = string, *strmax=string+len;
+ register int n=0;
+ mbinit();
+ if(len>0)
+ {
+ while(str<strmax && mbchar(str))
+ n++;
+ }
+ else while(mbchar(str))
+ n++;
+ return(n);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ {
+ if(len<0)
+ return(strlen(string));
+ return(len);
+ }
+}
+
+/*
+ * This is the default tilde discipline function
+ */
+static int sh_btilde(int argc, char *argv[], Shbltin_t *context)
+{
+ Shell_t *shp = context->shp;
+ char *cp = sh_tilde(shp,argv[1]);
+ NOT_USED(argc);
+ if(!cp)
+ cp = argv[1];
+ sfputr(sfstdout, cp, '\n');
+ return(0);
+}
+
+/*
+ * <offset> is byte offset for beginning of tilde string
+ */
+static void tilde_expand2(Shell_t *shp, register int offset)
+{
+ char shtilde[10], *av[3], *ptr=stkfreeze(shp->stk,1);
+ Sfio_t *iop, *save=sfstdout;
+ Namval_t *np;
+ static int beenhere=0;
+ strcpy(shtilde,".sh.tilde");
+ np = nv_open(shtilde,shp->fun_tree, NV_VARNAME|NV_NOARRAY|NV_NOASSIGN|NV_NOFAIL);
+ if(np && !beenhere)
+ {
+ beenhere = 1;
+ sh_addbuiltin(shtilde,sh_btilde,0);
+ nv_onattr(np,NV_EXPORT);
+ }
+ av[0] = ".sh.tilde";
+ av[1] = &ptr[offset];
+ av[2] = 0;
+ iop = sftmp((IOBSIZE>PATH_MAX?IOBSIZE:PATH_MAX)+1);
+ sfset(iop,SF_READ,0);
+ sfstdout = iop;
+ if(np)
+ sh_fun(np, (Namval_t*)0, av);
+ else
+ sh_btilde(2, av, &shp->bltindata);
+ sfstdout = save;
+ stkset(shp->stk,ptr, offset);
+ sfseek(iop,(Sfoff_t)0,SEEK_SET);
+ sfset(iop,SF_READ,1);
+ if(ptr = sfreserve(iop, SF_UNBOUND, -1))
+ {
+ Sfoff_t n = sfvalue(iop);
+ while(ptr[n-1]=='\n')
+ n--;
+ if(n==1 && fcpeek(0)=='/' && ptr[n-1])
+ n--;
+ if(n)
+ sfwrite(shp->stk,ptr,n);
+ }
+ else
+ sfputr(shp->stk,av[1],0);
+ sfclose(iop);
+}
+
+/*
+ * This routine is used to resolve ~ expansion.
+ * A ~ by itself is replaced with the users login directory.
+ * A ~- is replaced by the previous working directory in shell.
+ * A ~+ is replaced by the present working directory in shell.
+ * If ~name is replaced with login directory of name.
+ * If string doesn't start with ~ or ~... not found then 0 returned.
+ */
+
+static char *sh_tilde(Shell_t *shp,register const char *string)
+{
+ register char *cp;
+ register int c;
+ register struct passwd *pw;
+ register Namval_t *np=0;
+ static Dt_t *logins_tree;
+ if(*string++!='~')
+ return(NIL(char*));
+ if((c = *string)==0)
+ {
+ if(!(cp=nv_getval(sh_scoped(shp,HOME))))
+ cp = getlogin();
+ return(cp);
+ }
+ if((c=='-' || c=='+') && string[1]==0)
+ {
+ if(c=='+')
+ cp = nv_getval(sh_scoped(shp,PWDNOD));
+ else
+ cp = nv_getval(sh_scoped(shp,OLDPWDNOD));
+ return(cp);
+ }
+#if _WINIX
+ if(fcgetc(c)=='/')
+ {
+ char *str;
+ int n=0,offset=staktell();
+ stakputs(string);
+ do
+ {
+ stakputc(c);
+ n++;
+ }
+ while (fcgetc(c) && c!='/');
+ stakputc(0);
+ if(c)
+ fcseek(-1);
+ str = stakseek(offset);
+ Skip = n;
+ if(logins_tree && (np=nv_search(str,logins_tree,0)))
+ return(nv_getval(np));
+ if(pw = getpwnam(str))
+ {
+ string = str;
+ goto skip;
+ }
+ Skip = 0;
+ }
+#endif /* _WINIX */
+ if(logins_tree && (np=nv_search(string,logins_tree,0)))
+ return(nv_getval(np));
+ if(!(pw = getpwnam(string)))
+ return(NIL(char*));
+#if _WINIX
+skip:
+#endif /* _WINIX */
+ if(!logins_tree)
+ logins_tree = dtopen(&_Nvdisc,Dtbag);
+ if(np=nv_search(string,logins_tree,NV_ADD))
+ {
+ c = shp->subshell;
+ shp->subshell = 0;
+ nv_putval(np, pw->pw_dir,0);
+ shp->subshell = c;
+ }
+ return(pw->pw_dir);
+}
+
+/*
+ * return values for special macros
+ */
+static char *special(Shell_t *shp,register int c)
+{
+ if(c!='$')
+ shp->argaddr = 0;
+ switch(c)
+ {
+ case '@':
+ case '*':
+ return(shp->st.dolc>0?shp->st.dolv[1]:NIL(char*));
+ case '#':
+#if SHOPT_FILESCAN
+ if(shp->cur_line)
+ {
+ getdolarg(shp,MAX_ARGN,(int*)0);
+ return(ltos(shp->offsets[0]));
+ }
+#endif /* SHOPT_FILESCAN */
+ return(ltos(shp->st.dolc));
+ case '!':
+ if(shp->bckpid)
+#if SHOPT_COSHELL
+ return(sh_pid2str(shp,shp->bckpid));
+#else
+ return(ltos(shp->bckpid));
+#endif /* SHOPT_COSHELL */
+ break;
+ case '$':
+ if(nv_isnull(SH_DOLLARNOD))
+ return(ltos(shp->gd->pid));
+ return(nv_getval(SH_DOLLARNOD));
+ case '-':
+ return(sh_argdolminus(shp->arg_context));
+ case '?':
+ return(ltos(shp->savexit));
+ case 0:
+ if(sh_isstate(SH_PROFILE) || shp->fn_depth==0 || !shp->st.cmdname)
+ return(shp->shname);
+ else
+ return(shp->st.cmdname);
+ }
+ return(NIL(char*));
+}
+
+/*
+ * Handle macro expansion errors
+ */
+static void mac_error(Namval_t *np)
+{
+ if(np)
+ nv_close(np);
+ errormsg(SH_DICT,ERROR_exit(1),e_subst,fcfirst());
+}
+
+/*
+ * Given pattern/string, replace / with 0 and return pointer to string
+ * \ characters are stripped from string. The \ are stripped in the
+ * replacement string unless followed by a digit or \.
+ */
+static char *mac_getstring(char *pattern)
+{
+ register char *cp=pattern, *rep=0, *dp;
+ register int c;
+ while(c = *cp++)
+ {
+ if(c==ESCAPE && (!rep || (*cp && strchr("&|()[]*?",*cp))))
+ {
+ c = *cp++;
+ }
+ else if(!rep && c=='/')
+ {
+ cp[-1] = 0;
+ rep = dp = cp;
+ continue;
+ }
+ if(rep)
+ *dp++ = c;
+ }
+ if(rep)
+ *dp = 0;
+ return(rep);
+}
diff --git a/src/cmd/ksh93/sh/main.c b/src/cmd/ksh93/sh/main.c
new file mode 100644
index 0000000..85948a6
--- /dev/null
+++ b/src/cmd/ksh93/sh/main.c
@@ -0,0 +1,787 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Rewritten By David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <stak.h>
+#include <ls.h>
+#include <fcin.h>
+#include "defs.h"
+#include "variables.h"
+#include "path.h"
+#include "io.h"
+#include "jobs.h"
+#include "shlex.h"
+#include "shnodes.h"
+#include "history.h"
+#include "timeout.h"
+#include "FEATURE/time"
+#include "FEATURE/pstat"
+#include "FEATURE/execargs"
+#include "FEATURE/externs"
+#ifdef _hdr_nc
+# include <nc.h>
+#endif /* _hdr_nc */
+
+#define CMD_LENGTH 64
+
+/* These routines are referenced by this module */
+static void exfile(Shell_t*, Sfio_t*,int);
+static void chkmail(Shell_t *shp, char*);
+#if defined(_lib_fork) && !defined(_NEXT_SOURCE)
+ static void fixargs(char**,int);
+#else
+# define fixargs(a,b)
+#endif
+
+#ifndef environ
+ extern char **environ;
+#endif
+
+static struct stat lastmail;
+static time_t mailtime;
+static char beenhere = 0;
+
+#ifdef _lib_sigvec
+ void clearsigmask(register int sig)
+ {
+ struct sigvec vec;
+ if(sigvec(sig,NIL(struct sigvec*),&vec)>=0 && vec.sv_mask)
+ {
+ vec.sv_mask = 0;
+ sigvec(sig,&vec,NIL(struct sigvec*));
+ }
+ }
+#endif /* _lib_sigvec */
+
+#ifdef _lib_fts_notify
+# include <fts.h>
+ /* check for interrupts during tree walks */
+ static int fts_sigcheck(FTS* fp, FTSENT* ep, void* context)
+ {
+ Shell_t *shp = (Shell_t*)context;
+ NOT_USED(fp);
+ NOT_USED(ep);
+ if(shp->trapnote&SH_SIGSET)
+ {
+ errno = EINTR;
+ return(-1);
+ }
+ return(0);
+ }
+#endif /* _lib_fts_notify */
+
+#ifdef PATH_BFPATH
+#define PATHCOMP NIL(Pathcomp_t*)
+#else
+#define PATHCOMP ""
+#endif
+
+/*
+ * search for file and exfile() it if it exists
+ * 1 returned if file found, 0 otherwise
+ */
+
+int sh_source(Shell_t *shp, Sfio_t *iop, const char *file)
+{
+ char* oid;
+ char* nid;
+ int fd;
+
+ if (!file || !*file || (fd = path_open(shp,file, PATHCOMP)) < 0)
+ {
+ REGRESS(source, "sh_source", ("%s:ENOENT", file));
+ return 0;
+ }
+ oid = error_info.id;
+ nid = error_info.id = strdup(file);
+ shp->st.filename = path_fullname(shp,stakptr(PATH_OFFSET));
+ REGRESS(source, "sh_source", ("%s", file));
+ exfile(shp, iop, fd);
+ error_info.id = oid;
+ free(nid);
+ return 1;
+}
+
+#ifdef S_ISSOCK
+#define REMOTE(m) (S_ISSOCK(m)||!(m))
+#else
+#define REMOTE(m) !(m)
+#endif
+
+int sh_main(int ac, char *av[], Shinit_f userinit)
+{
+ register char *name;
+ register int fdin;
+ register Sfio_t *iop;
+ register Shell_t *shp;
+ struct stat statb;
+ int i, rshflag; /* set for restricted shell */
+ char *command;
+ free(malloc(64*1024));
+#ifdef _lib_sigvec
+ /* This is to clear mask that may be left on by rlogin */
+ clearsigmask(SIGALRM);
+ clearsigmask(SIGHUP);
+ clearsigmask(SIGCHLD);
+#endif /* _lib_sigvec */
+#ifdef _hdr_nc
+ _NutConf(_NC_SET_SUFFIXED_SEARCHING, 1);
+#endif /* _hdr_nc */
+ fixargs(av,0);
+ shp = sh_init(ac,av,userinit);
+ time(&mailtime);
+ if(rshflag=sh_isoption(SH_RESTRICTED))
+ sh_offoption(SH_RESTRICTED);
+#ifdef _lib_fts_notify
+ fts_notify(fts_sigcheck,(void*)shp);
+#endif /* _lib_fts_notify */
+ if(sigsetjmp(*((sigjmp_buf*)shp->jmpbuffer),0))
+ {
+ /* begin script execution here */
+ sh_reinit((char**)0);
+ shp->gd->pid = getpid();
+ shp->gd->ppid = getppid();
+ }
+ shp->fn_depth = shp->dot_depth = 0;
+ command = error_info.id;
+ /* set pidname '$$' */
+ srand(shp->gd->pid&0x7fff);
+ if(nv_isnull(PS4NOD))
+ nv_putval(PS4NOD,e_traceprompt,NV_RDONLY);
+ path_pwd(shp,1);
+ iop = (Sfio_t*)0;
+#if SHOPT_BRACEPAT
+ sh_onoption(SH_BRACEEXPAND);
+#endif
+ if((beenhere++)==0)
+ {
+ sh_onstate(SH_PROFILE);
+ ((Lex_t*)shp->lex_context)->nonstandard = 0;
+ if(shp->gd->ppid==1)
+ shp->login_sh++;
+ if(shp->login_sh >= 2)
+ sh_onoption(SH_LOGIN_SHELL);
+ /* decide whether shell is interactive */
+ if(!sh_isoption(SH_INTERACTIVE) && !sh_isoption(SH_TFLAG) && !sh_isoption(SH_CFLAG) &&
+ sh_isoption(SH_SFLAG) && tty_check(0) && tty_check(ERRIO))
+ sh_onoption(SH_INTERACTIVE);
+ if(sh_isoption(SH_INTERACTIVE))
+ {
+ sh_onoption(SH_BGNICE);
+ sh_onoption(SH_RC);
+ }
+ if(!sh_isoption(SH_RC) && (sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX)
+#if SHOPT_REMOTE
+ || !fstat(0, &statb) && REMOTE(statb.st_mode)
+#endif
+ ))
+ sh_onoption(SH_RC);
+ for(i=0; i<elementsof(shp->offoptions.v); i++)
+ shp->options.v[i] &= ~shp->offoptions.v[i];
+ if(sh_isoption(SH_INTERACTIVE))
+ {
+#ifdef SIGXCPU
+ signal(SIGXCPU,SIG_DFL);
+#endif /* SIGXCPU */
+#ifdef SIGXFSZ
+ signal(SIGXFSZ,SIG_DFL);
+#endif /* SIGXFSZ */
+ sh_onoption(SH_MONITOR);
+ }
+ job_init(shp,sh_isoption(SH_LOGIN_SHELL));
+ if(sh_isoption(SH_LOGIN_SHELL))
+ {
+ /* system profile */
+ sh_source(shp, iop, e_sysprofile);
+ if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED))
+ {
+ char **files = shp->gd->login_files;
+ while ((name = *files++) && !sh_source(shp, iop, sh_mactry(shp,name)));
+ }
+ }
+ /* make sure PWD is set up correctly */
+ path_pwd(shp,1);
+ if(!sh_isoption(SH_NOEXEC))
+ {
+ if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC))
+ {
+#if SHOPT_BASH
+ if(sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX))
+ {
+#if SHOPT_SYSRC
+ sh_source(shp, iop, e_bash_sysrc);
+#endif
+ sh_source(shp, iop, shp->gd->rcfile ? shp->gd->rcfile : sh_mactry(shp,(char*)e_bash_rc));
+ }
+ else
+#endif
+ {
+ if(name = sh_mactry(shp,nv_getval(ENVNOD)))
+ name = *name ? strdup(name) : (char*)0;
+#if SHOPT_SYSRC
+ if(!strmatch(name, "?(.)/./*"))
+ sh_source(shp, iop, e_sysrc);
+#endif
+ if(name)
+ {
+ sh_source(shp, iop, name);
+ free(name);
+ }
+ }
+ }
+ else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED))
+ sh_source(shp, iop, e_suidprofile);
+ }
+ shp->st.cmdname = error_info.id = command;
+ sh_offstate(SH_PROFILE);
+ if(rshflag)
+ sh_onoption(SH_RESTRICTED);
+ /* open input file if specified */
+ if(shp->comdiv)
+ {
+ shell_c:
+ iop = sfnew(NIL(Sfio_t*),shp->comdiv,strlen(shp->comdiv),0,SF_STRING|SF_READ);
+ }
+ else
+ {
+ name = error_info.id;
+ error_info.id = shp->shname;
+ if(sh_isoption(SH_SFLAG))
+ fdin = 0;
+ else
+ {
+ char *sp;
+ /* open stream should have been passed into shell */
+ if(strmatch(name,e_devfdNN))
+ {
+#if !_WINIX
+ char *cp;
+ int type;
+#endif
+ fdin = (int)strtol(name+8, (char**)0, 10);
+ if(fstat(fdin,&statb)<0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,name);
+#if !_WINIX
+ /*
+ * try to undo effect of solaris 2.5+
+ * change for argv for setuid scripts
+ */
+ if(((type = sh_type(cp = av[0])) & SH_TYPE_SH) && (!(name = nv_getval(L_ARGNOD)) || !((type = sh_type(cp = name)) & SH_TYPE_SH)))
+ {
+ av[0] = (type & SH_TYPE_LOGIN) ? cp : path_basename(cp);
+ /* exec to change $0 for ps */
+ execv(pathshell(),av);
+ /* exec fails */
+ shp->st.dolv[0] = av[0];
+ fixargs(shp->st.dolv,1);
+ }
+#endif
+ name = av[0];
+ sh_offoption(SH_VERBOSE);
+ sh_offoption(SH_XTRACE);
+ }
+ else
+ {
+ int isdir = 0;
+ if((fdin=sh_open(name,O_RDONLY,0))>=0 &&(fstat(fdin,&statb)<0 || S_ISDIR(statb.st_mode)))
+ {
+ close(fdin);
+ isdir = 1;
+ fdin = -1;
+ }
+ else
+ shp->st.filename = path_fullname(shp,name);
+ sp = 0;
+ if(fdin < 0 && !strchr(name,'/'))
+ {
+#ifdef PATH_BFPATH
+ if(path_absolute(shp,name,NIL(Pathcomp_t*)))
+ sp = stakptr(PATH_OFFSET);
+#else
+ sp = path_absolute(shp,name,NIL(char*));
+#endif
+ if(sp)
+ {
+ if((fdin=sh_open(sp,O_RDONLY,0))>=0)
+ shp->st.filename = path_fullname(shp,sp);
+ }
+ }
+ if(fdin<0)
+ {
+ if(isdir)
+ errno = EISDIR;
+ error_info.id = av[0];
+ if(sp || errno!=ENOENT)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_open,name);
+ /* try sh -c 'name "$@"' */
+ sh_onoption(SH_CFLAG);
+ shp->comdiv = (char*)malloc(strlen(name)+7);
+ name = strcopy(shp->comdiv,name);
+ if(shp->st.dolc)
+ strcopy(name," \"$@\"");
+ goto shell_c;
+ }
+ if(fdin==0)
+ fdin = sh_iomovefd(fdin);
+ }
+ shp->readscript = shp->shname;
+ }
+ error_info.id = name;
+ shp->comdiv--;
+#if SHOPT_ACCT
+ sh_accinit();
+ if(fdin != 0)
+ sh_accbegin(error_info.id);
+#endif /* SHOPT_ACCT */
+ }
+ }
+ else
+ {
+ fdin = shp->infd;
+ fixargs(shp->st.dolv,1);
+ }
+ if(sh_isoption(SH_INTERACTIVE))
+ sh_onstate(SH_INTERACTIVE);
+ nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
+ exfile(shp,iop,fdin);
+ sh_done(shp,0);
+ /* NOTREACHED */
+ return(0);
+}
+
+/*
+ * iop is not null when the input is a string
+ * fdin is the input file descriptor
+ */
+
+static void exfile(register Shell_t *shp, register Sfio_t *iop,register int fno)
+{
+ time_t curtime;
+ Shnode_t *t;
+ int maxtry=IOMAXTRY, tdone=0, execflags;
+ int states,jmpval;
+ struct checkpt buff;
+ sh_pushcontext(shp,&buff,SH_JMPERREXIT);
+ /* open input stream */
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ if(!iop)
+ {
+ if(fno > 0)
+ {
+ int r;
+ if(fno < 10 && ((r=sh_fcntl(fno,F_DUPFD,10))>=10))
+ {
+ shp->fdstatus[r] = shp->fdstatus[fno];
+ sh_close(fno);
+ fno = r;
+ }
+ fcntl(fno,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fno] |= IOCLEX;
+ iop = sh_iostream((void*)shp,fno);
+ }
+ else
+ iop = sfstdin;
+ }
+ else
+ fno = -1;
+ shp->infd = fno;
+ if(sh_isstate(SH_INTERACTIVE))
+ {
+ if(nv_isnull(PS1NOD))
+ nv_putval(PS1NOD,(shp->gd->euserid?e_stdprompt:e_supprompt),NV_RDONLY);
+ sh_sigdone();
+ if(sh_histinit((void*)shp))
+ sh_onoption(SH_HISTORY);
+ }
+ else
+ {
+ if(!sh_isstate(SH_PROFILE))
+ {
+ buff.mode = SH_JMPEXIT;
+ sh_onoption(SH_TRACKALL);
+ sh_offoption(SH_MONITOR);
+ }
+ sh_offstate(SH_INTERACTIVE);
+ sh_offstate(SH_MONITOR);
+ sh_offstate(SH_HISTORY);
+ sh_offoption(SH_HISTORY);
+ }
+ states = sh_getstate();
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval)
+ {
+ Sfio_t *top;
+ sh_iorestore((void*)shp,0,jmpval);
+ hist_flush(shp->gd->hist_ptr);
+ sfsync(shp->outpool);
+ shp->st.execbrk = shp->st.breakcnt = 0;
+ /* check for return from profile or env file */
+ if(sh_isstate(SH_PROFILE) && (jmpval==SH_JMPFUN || jmpval==SH_JMPEXIT))
+ {
+ sh_setstate(states);
+ goto done;
+ }
+ if(!sh_isoption(SH_INTERACTIVE) || sh_isstate(SH_FORKED) || (jmpval > SH_JMPERREXIT && job_close(shp) >=0))
+ {
+ sh_offstate(SH_INTERACTIVE);
+ sh_offstate(SH_MONITOR);
+ goto done;
+ }
+ /* skip over remaining input */
+ if(top = fcfile())
+ {
+ while(fcget()>0);
+ fcclose();
+ while(top=sfstack(iop,SF_POPSTACK))
+ sfclose(top);
+ }
+ /* make sure that we own the terminal */
+#ifdef SIGTSTP
+ tcsetpgrp(job.fd,shp->gd->pid);
+#endif /* SIGTSTP */
+ }
+ /* error return here */
+ sfclrerr(iop);
+ sh_setstate(states);
+ shp->st.optindex = 1;
+ opt_info.offset = 0;
+ shp->st.loopcnt = 0;
+ shp->trapnote = 0;
+ shp->intrap = 0;
+ error_info.line = 1;
+ shp->inlineno = 1;
+ shp->binscript = 0;
+ if(sfeof(iop))
+ goto eof_or_error;
+ /* command loop */
+ while(1)
+ {
+ shp->nextprompt = 1;
+ sh_freeup(shp);
+ stakset(NIL(char*),0);
+ exitset();
+ sh_offstate(SH_STOPOK);
+ sh_offstate(SH_ERREXIT);
+ sh_offstate(SH_VERBOSE);
+ sh_offstate(SH_TIMING);
+ sh_offstate(SH_GRACE);
+ sh_offstate(SH_TTYWAIT);
+ if(sh_isoption(SH_VERBOSE))
+ sh_onstate(SH_VERBOSE);
+ sh_onstate(SH_ERREXIT);
+ /* -eim flags don't apply to profiles */
+ if(sh_isstate(SH_PROFILE))
+ {
+ sh_offstate(SH_INTERACTIVE);
+ sh_offstate(SH_ERREXIT);
+ sh_offstate(SH_MONITOR);
+ }
+ if(sh_isstate(SH_INTERACTIVE) && !tdone)
+ {
+ register char *mail;
+#ifdef JOBS
+ sh_offstate(SH_MONITOR);
+ if(sh_isoption(SH_MONITOR))
+ sh_onstate(SH_MONITOR);
+ if(job.pwlist)
+ {
+ job_walk(sfstderr,job_list,JOB_NFLAG,(char**)0);
+ job_wait((pid_t)0);
+ }
+#endif /* JOBS */
+ if((mail=nv_getval(MAILPNOD)) || (mail=nv_getval(MAILNOD)))
+ {
+ time(&curtime);
+ if ((curtime - mailtime) >= sh_mailchk)
+ {
+ chkmail(shp,mail);
+ mailtime = curtime;
+ }
+ }
+ if(shp->gd->hist_ptr)
+ hist_eof(shp->gd->hist_ptr);
+ /* sets timeout for command entry */
+ shp->timeout = shp->st.tmout;
+#if SHOPT_TIMEOUT
+ if(shp->timeout <= 0 || shp->timeout > SHOPT_TIMEOUT)
+ shp->timeout = SHOPT_TIMEOUT;
+#endif /* SHOPT_TIMEOUT */
+ shp->inlineno = 1;
+ error_info.line = 1;
+ shp->exitval = 0;
+ shp->trapnote = 0;
+ if(buff.mode == SH_JMPEXIT)
+ {
+ buff.mode = SH_JMPERREXIT;
+#ifdef DEBUG
+ errormsg(SH_DICT,ERROR_warn(0),"%d: mode changed to JMP_EXIT",getpid());
+#endif
+ }
+ }
+ errno = 0;
+ if(tdone || !sfreserve(iop,0,0))
+ {
+ eof_or_error:
+ if(sh_isstate(SH_INTERACTIVE) && !sferror(iop))
+ {
+ if(--maxtry>0 && sh_isoption(SH_IGNOREEOF) &&
+ !sferror(sfstderr) && (shp->fdstatus[fno]&IOTTY))
+ {
+ sfclrerr(iop);
+ errormsg(SH_DICT,0,e_logout);
+ continue;
+ }
+ else if(job_close(shp)<0)
+ continue;
+ }
+ if(errno==0 && sferror(iop) && --maxtry>0)
+ {
+ sfclrlock(iop);
+ sfclrerr(iop);
+ continue;
+ }
+ goto done;
+ }
+ maxtry = IOMAXTRY;
+ if(sh_isstate(SH_INTERACTIVE) && shp->gd->hist_ptr)
+ {
+ job_wait((pid_t)0);
+ hist_eof(shp->gd->hist_ptr);
+ sfsync(sfstderr);
+ }
+ if(sh_isoption(SH_HISTORY))
+ sh_onstate(SH_HISTORY);
+ job.waitall = job.curpgid = 0;
+ error_info.flags |= ERROR_INTERACTIVE;
+ t = (Shnode_t*)sh_parse(shp,iop,0);
+ if(!sh_isstate(SH_INTERACTIVE) && !sh_isoption(SH_CFLAG))
+ error_info.flags &= ~ERROR_INTERACTIVE;
+ shp->readscript = 0;
+ if(sh_isstate(SH_INTERACTIVE) && shp->gd->hist_ptr)
+ hist_flush(shp->gd->hist_ptr);
+ sh_offstate(SH_HISTORY);
+ if(t)
+ {
+ execflags = sh_state(SH_ERREXIT)|sh_state(SH_INTERACTIVE);
+ /* The last command may not have to fork */
+ if(!sh_isstate(SH_PROFILE) && sh_isoption(SH_CFLAG) &&
+ (fno<0 || !(shp->fdstatus[fno]&(IOTTY|IONOSEEK)))
+ && !sfreserve(iop,0,0))
+ {
+ execflags |= sh_state(SH_NOFORK);
+ }
+ shp->st.execbrk = 0;
+ sh_exec(t,execflags);
+ if(shp->forked)
+ {
+ sh_offstate(SH_INTERACTIVE);
+ goto done;
+ }
+ /* This is for sh -t */
+ if(sh_isoption(SH_TFLAG) && !sh_isstate(SH_PROFILE))
+ tdone++;
+ }
+ }
+done:
+ sh_popcontext(shp,&buff);
+ if(sh_isstate(SH_INTERACTIVE))
+ {
+ sfputc(sfstderr,'\n');
+ job_close(shp);
+ }
+ if(jmpval == SH_JMPSCRIPT)
+ siglongjmp(*shp->jmplist,jmpval);
+ else if(jmpval == SH_JMPEXIT)
+ sh_done(shp,0);
+ if(fno>0)
+ sh_close(fno);
+ if(shp->st.filename)
+ free((void*)shp->st.filename);
+ shp->st.filename = 0;
+}
+
+
+/* prints out messages if files in list have been modified since last call */
+static void chkmail(Shell_t *shp, char *files)
+{
+ register char *cp,*sp,*qp;
+ register char save;
+ struct argnod *arglist=0;
+ int offset = staktell();
+ char *savstak=stakptr(0);
+ struct stat statb;
+ if(*(cp=files) == 0)
+ return;
+ sp = cp;
+ do
+ {
+ /* skip to : or end of string saving first '?' */
+ for(qp=0;*sp && *sp != ':';sp++)
+ if((*sp == '?' || *sp=='%') && qp == 0)
+ qp = sp;
+ save = *sp;
+ *sp = 0;
+ /* change '?' to end-of-string */
+ if(qp)
+ *qp = 0;
+ do
+ {
+ /* see if time has been modified since last checked
+ * and the access time <= the modification time
+ */
+ if(stat(cp,&statb) >= 0 && statb.st_mtime >= mailtime
+ && statb.st_atime <= statb.st_mtime)
+ {
+ /* check for directory */
+ if(!arglist && S_ISDIR(statb.st_mode))
+ {
+ /* generate list of directory entries */
+ path_complete(shp,cp,"/*",&arglist);
+ }
+ else
+ {
+ /*
+ * If the file has shrunk,
+ * or if the size is zero
+ * then don't print anything
+ */
+ if(statb.st_size &&
+ ( statb.st_ino != lastmail.st_ino
+ || statb.st_dev != lastmail.st_dev
+ || statb.st_size > lastmail.st_size))
+ {
+ /* save and restore $_ */
+ char *save = shp->lastarg;
+ shp->lastarg = cp;
+ errormsg(SH_DICT,0,sh_mactry(shp,qp?qp+1:(char*)e_mailmsg));
+ shp->lastarg = save;
+ }
+ lastmail = statb;
+ break;
+ }
+ }
+ if(arglist)
+ {
+ cp = arglist->argval;
+ arglist = arglist->argchn.ap;
+ }
+ else
+ cp = 0;
+ }
+ while(cp);
+ if(qp)
+ *qp = '?';
+ *sp++ = save;
+ cp = sp;
+ }
+ while(save);
+ stakset(savstak,offset);
+}
+
+#undef EXECARGS
+#undef PSTAT
+#if defined(_hdr_execargs) && defined(pdp11)
+# include <execargs.h>
+# define EXECARGS 1
+#endif
+
+#if defined(_lib_pstat) && defined(_sys_pstat)
+# include <sys/pstat.h>
+# define PSTAT 1
+#endif
+
+#if defined(_lib_fork) && !defined(_NEXT_SOURCE)
+/*
+ * fix up command line for ps command
+ * mode is 0 for initialization
+ */
+static void fixargs(char **argv, int mode)
+{
+#if EXECARGS
+ *execargs=(char *)argv;
+#else
+ static char *buff;
+ static int command_len;
+ register char *cp;
+ int offset=0,size;
+# ifdef PSTAT
+ union pstun un;
+ if(mode==0)
+ {
+ struct pst_static st;
+ un.pst_static = &st;
+ if(pstat(PSTAT_STATIC, un, sizeof(struct pst_static), 1, 0)<0)
+ return;
+ command_len = st.command_length;
+ return;
+ }
+ stakseek(command_len+2);
+ buff = stakseek(0);
+# else
+ if(mode==0)
+ {
+ buff = argv[0];
+ while(cp = *argv++)
+ command_len += strlen(cp)+1;
+ if(environ && *environ==buff+command_len)
+ {
+ for(argv=environ; cp = *argv; cp++)
+ {
+ if(command_len > CMD_LENGTH)
+ {
+ command_len = CMD_LENGTH;
+ break;
+ }
+ *argv++ = strdup(cp);
+ command_len += strlen(cp)+1;
+ }
+ }
+ command_len -= 1;
+ return;
+ }
+# endif /* PSTAT */
+ if(command_len==0)
+ return;
+ while((cp = *argv++) && offset < command_len)
+ {
+ if(offset + (size=strlen(cp)) >= command_len)
+ size = command_len - offset;
+ memcpy(buff+offset,cp,size);
+ offset += size;
+ buff[offset++] = ' ';
+ }
+ buff[offset-1] = 0;
+# ifdef PSTAT
+ un.pst_command = stakptr(0);
+ pstat(PSTAT_SETCMD,un,0,0,0);
+# endif /* PSTAT */
+#endif /* EXECARGS */
+}
+#endif /* _lib_fork */
diff --git a/src/cmd/ksh93/sh/name.c b/src/cmd/ksh93/sh/name.c
new file mode 100644
index 0000000..77793f4
--- /dev/null
+++ b/src/cmd/ksh93/sh/name.c
@@ -0,0 +1,3684 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Labs
+ *
+ */
+
+#define putenv ___putenv
+
+#include "defs.h"
+#include "variables.h"
+#include "path.h"
+#include "lexstates.h"
+#include "timeout.h"
+#include "FEATURE/externs"
+#include "streval.h"
+
+#define NVCACHE 8 /* must be a power of 2 */
+#define Empty ((char*)(e_sptbnl+3))
+static char *savesub = 0;
+static char Null[1];
+static Namval_t NullNode;
+static Dt_t *Refdict;
+static Dtdisc_t _Refdisc =
+{
+ offsetof(struct Namref,np),sizeof(struct Namval_t*),sizeof(struct Namref)
+};
+
+#if !_lib_pathnative && _lib_uwin_path
+
+#define _lib_pathnative 1
+
+extern int uwin_path(const char*, char*, int);
+
+size_t
+pathnative(const char* path, char* buf, size_t siz)
+{
+ return uwin_path(path, buf, siz);
+}
+
+#endif /* _lib_pathnative */
+
+static void attstore(Namval_t*,void*);
+#ifndef _ENV_H
+ static void pushnam(Namval_t*,void*);
+ static char *staknam(Namval_t*, char*);
+#endif
+static void rightjust(char*, int, int);
+static char *lastdot(char*, int);
+
+struct adata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ char *mapname;
+ char **argnam;
+ int attsize;
+ char *attval;
+};
+
+#if SHOPT_TYPEDEF
+ struct sh_type
+ {
+ void *previous;
+ Namval_t **nodes;
+ Namval_t *rp;
+ short numnodes;
+ short maxnodes;
+ };
+#endif /*SHOPT_TYPEDEF */
+
+#if NVCACHE
+ struct Namcache
+ {
+ struct Cache_entry
+ {
+ Dt_t *root;
+ Dt_t *last_root;
+ char *name;
+ Namval_t *np;
+ Namval_t *last_table;
+ int flags;
+ short size;
+ short len;
+ } entries[NVCACHE];
+ short index;
+ short ok;
+ };
+ static struct Namcache nvcache;
+#endif
+
+char nv_local = 0;
+#ifndef _ENV_H
+static void(*nullscan)(Namval_t*,void*);
+#endif
+
+#if ( SFIO_VERSION <= 20010201L )
+# define _data data
+#endif
+
+#if !SHOPT_MULTIBYTE
+# define mbchar(p) (*(unsigned char*)p++)
+#endif /* SHOPT_MULTIBYTE */
+
+/* ======== name value pair routines ======== */
+
+#include "shnodes.h"
+#include "builtins.h"
+
+static char *getbuf(size_t len)
+{
+ static char *buf;
+ static size_t buflen;
+ if(buflen < len)
+ {
+ if(buflen==0)
+ buf = (char*)malloc(len);
+ else
+ buf = (char*)realloc(buf,len);
+ buflen = len;
+ }
+ return(buf);
+}
+
+#ifdef _ENV_H
+void sh_envput(Env_t* ep,Namval_t *np)
+{
+ int offset = staktell();
+ Namarr_t *ap = nv_arrayptr(np);
+ char *val;
+ if(ap)
+ {
+ if(ap->nelem&ARRAY_UNDEF)
+ nv_putsub(np,"0",0L);
+ else if(!(val=nv_getsub(np)) || strcmp(val,"0"))
+ return;
+ }
+ if(!(val = nv_getval(np)))
+ return;
+ stakputs(nv_name(np));
+ stakputc('=');
+ stakputs(val);
+ stakseek(offset);
+ env_add(ep,stakptr(offset),ENV_STRDUP);
+}
+#endif
+
+/*
+ * output variable name in format for re-input
+ */
+void nv_outname(Sfio_t *out, char *name, int len)
+{
+ const char *cp=name, *sp;
+ int c, offset = staktell();
+ while(sp= strchr(cp,'['))
+ {
+ if(len>0 && cp+len <= sp)
+ break;
+ sfwrite(out,cp,++sp-cp);
+ stakseek(offset);
+ while(c= *sp++)
+ {
+ if(c==']')
+ break;
+ else if(c=='\\')
+ {
+ if(*sp=='[' || *sp==']' || *sp=='\\')
+ c = *sp++;
+ }
+ stakputc(c);
+ }
+ stakputc(0);
+ sfputr(out,sh_fmtq(stakptr(offset)),-1);
+ if(len>0)
+ {
+ sfputc(out,']');
+ return;
+ }
+ cp = sp-1;
+ }
+ if(*cp)
+ {
+ if(len>0)
+ sfwrite(out,cp,len);
+ else
+ sfputr(out,cp,-1);
+ }
+ stakseek(offset);
+}
+
+#if SHOPT_TYPEDEF
+Namval_t *nv_addnode(Namval_t* np, int remove)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct sh_type *sp = (struct sh_type*)shp->mktype;
+ register int i;
+ register char *name=0;
+ if(sp->numnodes==0 && !nv_isnull(np) && shp->last_table)
+ {
+ /* could be an redefine */
+ Dt_t *root = nv_dict(shp->last_table);
+ sp->rp = np;
+ nv_delete(np,root,NV_NOFREE);
+ np = nv_search(sp->rp->nvname,root,NV_ADD);
+ }
+ if(sp->numnodes && memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1))
+ {
+ name = (sp->nodes[0])->nvname;
+ i = strlen(name);
+ if(memcmp(np->nvname,name,i))
+ return(np);
+ }
+ if(sp->rp && sp->numnodes)
+ {
+ /* check for a redefine */
+ if(name && np->nvname[i]=='.' && np->nvname[i+1]=='_' && np->nvname[i+2]==0)
+ sp->rp = 0;
+ else
+ {
+ Dt_t *root = nv_dict(shp->last_table);
+ nv_delete(sp->nodes[0],root,NV_NOFREE);
+ dtinsert(root,sp->rp);
+ errormsg(SH_DICT,ERROR_exit(1),e_redef,sp->nodes[0]->nvname);
+ }
+ }
+ for(i=0; i < sp->numnodes; i++)
+ {
+ if(np == sp->nodes[i])
+ {
+ if(remove)
+ {
+ while(++i < sp->numnodes)
+ sp->nodes[i-1] = sp->nodes[i];
+ sp->numnodes--;
+ }
+ return(np);
+ }
+ }
+ if(remove)
+ return(np);
+ if(sp->numnodes==sp->maxnodes)
+ {
+ sp->maxnodes += 20;
+ sp->nodes = (Namval_t**)realloc(sp->nodes,sizeof(Namval_t*)*sp->maxnodes);
+ }
+ sp->nodes[sp->numnodes++] = np;
+ return(np);
+}
+#endif /* SHOPT_TYPEDEF */
+
+/*
+ * given a list of assignments, determine <name> is on the list
+ returns a pointer to the argnod on the list or NULL
+ */
+struct argnod *nv_onlist(struct argnod *arg, const char *name)
+{
+ char *cp;
+ int len = strlen(name);
+ for(;arg; arg=arg->argnxt.ap)
+ {
+ if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
+ cp = ((struct fornod*)arg->argchn.ap)->fornam;
+ else
+ cp = arg->argval;
+ if(memcmp(cp,name,len)==0 && (cp[len]==0 || cp[len]=='='))
+ return(arg);
+ }
+ return(0);
+}
+
+/*
+ * Perform parameter assignment for a linked list of parameters
+ * <flags> contains attributes for the parameters
+ */
+void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *cp;
+ register Namval_t *np, *mp;
+ char *trap=shp->st.trap[SH_DEBUGTRAP];
+ char *prefix = shp->prefix;
+ int traceon = (sh_isoption(SH_XTRACE)!=0);
+ int array = (flags&(NV_ARRAY|NV_IARRAY));
+ Namarr_t *ap;
+ Namval_t node;
+ struct Namref nr;
+#if SHOPT_TYPEDEF
+ int maketype = flags&NV_TYPE;
+ struct sh_type shtp;
+ if(maketype)
+ {
+ shtp.previous = shp->mktype;
+ shp->mktype=(void*)&shtp;
+ shtp.numnodes=0;
+ shtp.maxnodes = 20;
+ shtp.rp = 0;
+ shtp.nodes =(Namval_t**)malloc(shtp.maxnodes*sizeof(Namval_t*));
+ }
+#endif /* SHOPT_TYPEDEF*/
+#if SHOPT_NAMESPACE
+ if(shp->namespace && nv_dict(shp->namespace)==shp->var_tree)
+ flags |= NV_NOSCOPE;
+#endif /* SHOPT_NAMESPACE */
+ flags &= ~(NV_TYPE|NV_ARRAY|NV_IARRAY);
+ if(sh_isoption(SH_ALLEXPORT))
+ flags |= NV_EXPORT;
+ if(shp->prefix)
+ {
+ flags &= ~(NV_IDENT|NV_EXPORT);
+ flags |= NV_VARNAME;
+ }
+ else
+ shp->prefix_root = shp->first_root = 0;
+ for(;arg; arg=arg->argnxt.ap)
+ {
+ shp->used_pos = 0;
+ if(arg->argflag&ARG_MAC)
+ {
+ shp->prefix = 0;
+ cp = sh_mactrim(shp,arg->argval,(flags&NV_NOREF)?-3:-1);
+ shp->prefix = prefix;
+ }
+ else
+ {
+ stakseek(0);
+ if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
+ {
+ int flag = (NV_VARNAME|NV_ARRAY|NV_ASSIGN);
+ int sub=0;
+ struct fornod *fp=(struct fornod*)arg->argchn.ap;
+ register Shnode_t *tp=fp->fortre;
+ flag |= (flags&(NV_NOSCOPE|NV_STATIC|NV_FARRAY));
+ if(arg->argflag&ARG_QUOTED)
+ cp = sh_mactrim(shp,fp->fornam,-1);
+ else
+ cp = fp->fornam;
+ error_info.line = fp->fortyp-shp->st.firstline;
+ if(!array && tp->tre.tretyp!=TLST && tp->com.comset && !tp->com.comarg && tp->com.comset->argval[0]==0 && tp->com.comset->argval[1]=='[')
+ array |= (tp->com.comset->argflag&ARG_MESSAGE)?NV_IARRAY:NV_ARRAY;
+ if(prefix && tp->com.comset && *cp=='[')
+ {
+ shp->prefix = 0;
+ np = nv_open(prefix,shp->last_root,flag);
+ shp->prefix = prefix;
+ if(np)
+ {
+ if(nv_isvtree(np) && !nv_isarray(np))
+ {
+ stakputc('.');
+ stakputs(cp);
+ cp = stakfreeze(1);
+ }
+ nv_close(np);
+ }
+ }
+ np = nv_open(cp,shp->var_tree,flag|NV_ASSIGN);
+ if(nv_isattr(np,NV_RDONLY) && np->nvfun && !(flags&NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ if(nv_isattr(np,NV_NOFREE) && nv_isnull(np))
+ nv_offattr(np,NV_NOFREE);
+ if(nv_istable(np))
+ _nv_unset(np,0);
+ if(typ && !array && (!shp->prefix || nv_isnull(np) || nv_isarray(np)))
+ {
+ if(!(nv_isnull(np)) && !nv_isarray(np))
+ _nv_unset(np,0);
+ nv_settype(np,typ,0);
+ }
+ if((flags&NV_STATIC) && !nv_isattr(np,NV_EXPORT) && !nv_isnull(np))
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ ap=nv_arrayptr(np);
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ flags |= NV_FARRAY;
+#endif /* SHOPT_FIXEDARRAY */
+ if(array && (!ap || !ap->hdr.type))
+ {
+#if SHOPT_FIXEDARRAY
+ if(!(arg->argflag&ARG_APPEND) && (!ap || !ap->fixed))
+#else
+ if(!(arg->argflag&ARG_APPEND))
+#endif /* SHOPT_FIXEDARRAY */
+ _nv_unset(np,NV_EXPORT);
+ if(array&NV_ARRAY)
+ {
+ nv_setarray(np,nv_associative);
+ }
+ else
+ {
+ nv_onattr(np,NV_ARRAY);
+ }
+ }
+ if(array && tp->tre.tretyp!=TLST && !tp->com.comset && !tp->com.comarg)
+ {
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ /* check for array assignment */
+ if(tp->tre.tretyp!=TLST && tp->com.comarg && !tp->com.comset && ((array&NV_IARRAY) || !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))))
+ {
+ int argc;
+ Dt_t *last_root = shp->last_root;
+ char **argv = sh_argbuild(shp,&argc,&tp->com,0);
+ shp->last_root = last_root;
+#if SHOPT_TYPEDEF
+ if(shp->mktype && shp->dot_depth==0 && np==((struct sh_type*)shp->mktype)->nodes[0])
+ {
+ shp->mktype = 0;
+ errormsg(SH_DICT,ERROR_exit(1),"%s: not a known type name",argv[0]);
+ }
+#endif /* SHOPT_TYPEDEF */
+ if(!(arg->argflag&ARG_APPEND))
+ {
+#if SHOPT_FIXEDARRAY
+ if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && !ap->fixed && (ap->nelem&ARRAY_MASK)))
+#else
+ if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && (ap->nelem&ARRAY_MASK)))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(ap)
+ ap->nelem |= ARRAY_UNDEF;
+ _nv_unset(np,0);
+ }
+ }
+ nv_setvec(np,(arg->argflag&ARG_APPEND),argc,argv);
+ if(traceon || trap)
+ {
+ int n = -1;
+ char *name = nv_name(np);
+ if(arg->argflag&ARG_APPEND)
+ n = '+';
+ if(trap)
+ sh_debug(shp,trap,name,(char*)0,argv,(arg->argflag&ARG_APPEND)|ARG_ASSIGN);
+ if(traceon)
+ {
+ sh_trace(shp,NIL(char**),0);
+ sfputr(sfstderr,name,n);
+ sfwrite(sfstderr,"=( ",3);
+ while(cp= *argv++)
+ sfputr(sfstderr,sh_fmtq(cp),' ');
+ sfwrite(sfstderr,")\n",2);
+ }
+ }
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ if((tp->tre.tretyp&COMMSK)==TFUN)
+ goto skip;
+ if(tp->tre.tretyp==TLST || !tp->com.comset || tp->com.comset->argval[0]!='[')
+ {
+ if(tp->tre.tretyp!=TLST && !tp->com.comnamp && tp->com.comset && tp->com.comset->argval[0]==0 && tp->com.comset->argchn.ap)
+ {
+ if(prefix)
+ cp = stakcopy(nv_name(np));
+ shp->prefix = cp;
+ if(tp->com.comset->argval[1]=='[')
+ {
+ if((arg->argflag&ARG_APPEND) && (!nv_isarray(np) || (nv_aindex(np)>=0)))
+ _nv_unset(np,0);
+ if(!(array&NV_IARRAY) && !(tp->com.comset->argflag&ARG_MESSAGE))
+ nv_setarray(np,nv_associative);
+ }
+ nv_setlist(tp->com.comset,flags&~NV_STATIC,0);
+ shp->prefix = prefix;
+ if(tp->com.comset->argval[1]!='[')
+ nv_setvtree(np);
+ nv_close(np);
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ if(*cp!='.' && *cp!='[' && strchr(cp,'['))
+ {
+ cp = stakcopy(nv_name(np));
+ nv_close(np);
+ if(!(arg->argflag&ARG_APPEND))
+ flag &= ~NV_ARRAY;
+ shp->prefix_root = shp->first_root;
+ np = nv_open(cp,shp->prefix_root?shp->prefix_root:shp->var_tree,flag);
+ }
+ if(arg->argflag&ARG_APPEND)
+ {
+ if(nv_isarray(np))
+ {
+ if((sub=nv_aimax(np)) < 0 && nv_arrayptr(np))
+ errormsg(SH_DICT,ERROR_exit(1),e_badappend,nv_name(np));
+ if(sub>=0)
+ sub++;
+ }
+ if(!nv_isnull(np) && np->nvalue.cp!=Empty && !nv_isvtree(np))
+ sub=1;
+ }
+ else if(((np->nvalue.cp && np->nvalue.cp!=Empty)||nv_isvtree(np)) && !nv_type(np))
+ _nv_unset(np,NV_EXPORT);
+ }
+ else
+ {
+ if(!(arg->argflag&ARG_APPEND))
+ _nv_unset(np,NV_EXPORT);
+ if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np))
+ nv_setarray(np,nv_associative);
+ }
+ skip:
+ if(sub>0)
+ {
+ sfprintf(stkstd,"%s[%d]",prefix?nv_name(np):cp,sub);
+ shp->prefix = stakfreeze(1);
+ nv_putsub(np,(char*)0,ARRAY_ADD|ARRAY_FILL|sub);
+ }
+ else if(prefix)
+ shp->prefix = stakcopy(nv_name(np));
+ else
+ shp->prefix = cp;
+ shp->last_table = 0;
+ if(shp->prefix)
+ {
+ if(*shp->prefix=='_' && shp->prefix[1]=='.' && nv_isref(L_ARGNOD))
+ {
+ sfprintf(stkstd,"%s%s",nv_name(L_ARGNOD->nvalue.nrp->np),shp->prefix+1);
+ shp->prefix = stkfreeze(stkstd,1);
+ }
+ memset(&nr,0,sizeof(nr));
+ memcpy(&node,L_ARGNOD,sizeof(node));
+ L_ARGNOD->nvalue.nrp = &nr;
+ nr.np = np;
+ nr.root = shp->last_root;
+ nr.table = shp->last_table;
+ L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
+ L_ARGNOD->nvfun = 0;
+ }
+ sh_exec(tp,sh_isstate(SH_ERREXIT));
+#if SHOPT_TYPEDEF
+ if(shp->prefix)
+#endif
+ {
+ L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
+ L_ARGNOD->nvflag = node.nvflag;
+ L_ARGNOD->nvfun = node.nvfun;
+ }
+ shp->prefix = prefix;
+ if(nv_isarray(np) && (mp=nv_opensub(np)))
+ np = mp;
+ while(tp->tre.tretyp==TLST)
+ {
+ if(!tp->lst.lstlef || !tp->lst.lstlef->tre.tretyp==TCOM || tp->lst.lstlef->com.comarg || tp->lst.lstlef->com.comset && tp->lst.lstlef->com.comset->argval[0]!='[')
+ break;
+ tp = tp->lst.lstrit;
+
+ }
+ if(!nv_isarray(np) && !typ && (tp->com.comarg || !tp->com.comset || tp->com.comset->argval[0]!='['))
+ {
+ nv_setvtree(np);
+ if(tp->com.comarg || tp->com.comset)
+ np->nvfun->dsize = 0;
+ }
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ cp = arg->argval;
+ mp = 0;
+ }
+ np = nv_open(cp,shp->prefix_root?shp->prefix_root:shp->var_tree,flags);
+ if(!np->nvfun && (flags&NV_NOREF))
+ {
+ if(shp->used_pos)
+ nv_onattr(np,NV_PARAM);
+ else
+ nv_offattr(np,NV_PARAM);
+ }
+ if(traceon || trap)
+ {
+ register char *sp=cp;
+ char *name=nv_name(np);
+ char *sub=0;
+ int append = 0;
+ if(nv_isarray(np))
+ sub = savesub;
+ if(cp=lastdot(sp,'='))
+ {
+ if(cp[-1]=='+')
+ append = ARG_APPEND;
+ cp++;
+ }
+ if(traceon)
+ {
+ sh_trace(shp,NIL(char**),0);
+ nv_outname(sfstderr,name,-1);
+ if(sub)
+ sfprintf(sfstderr,"[%s]",sh_fmtq(sub));
+ if(cp)
+ {
+ if(append)
+ sfputc(sfstderr,'+');
+ sfprintf(sfstderr,"=%s\n",sh_fmtq(cp));
+ }
+ }
+ if(trap)
+ {
+ char *av[2];
+ av[0] = cp;
+ av[1] = 0;
+ sh_debug(shp,trap,name,sub,av,append);
+ }
+ }
+#if SHOPT_TYPEDEF
+ check_type:
+ if(maketype)
+ {
+ nv_open(shtp.nodes[0]->nvname,shp->var_tree,NV_ASSIGN|NV_VARNAME|NV_NOADD|NV_NOFAIL);
+ np = nv_mktype(shtp.nodes,shtp.numnodes);
+ free((void*)shtp.nodes);
+ shp->mktype = shtp.previous;
+ maketype = 0;
+ if(shp->namespace)
+ free(shp->prefix);
+ shp->prefix = 0;
+ if(nr.np == np)
+ {
+ L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
+ L_ARGNOD->nvflag = node.nvflag;
+ L_ARGNOD->nvfun = node.nvfun;
+ }
+ }
+#endif /* SHOPT_TYPEDEF */
+ }
+}
+
+/*
+ * copy the subscript onto the stack
+ */
+static void stak_subscript(const char *sub, int last)
+{
+ register int c;
+ stakputc('[');
+ while(c= *sub++)
+ {
+ if(c=='[' || c==']' || c=='\\')
+ stakputc('\\');
+ stakputc(c);
+ }
+ stakputc(last);
+}
+
+/*
+ * construct a new name from a prefix and base name on the stack
+ */
+static char *copystack(const char *prefix, register const char *name, const char *sub)
+{
+ register int last=0,offset = staktell();
+ if(prefix)
+ {
+ stakputs(prefix);
+ if(*stakptr(staktell()-1)=='.')
+ stakseek(staktell()-1);
+ if(*name=='.' && name[1]=='[')
+ last = staktell()+2;
+ if(*name!='[' && *name!='.' && *name!='=' && *name!='+')
+ stakputc('.');
+ if(*name=='.' && (name[1]=='=' || name[1]==0))
+ stakputc('.');
+ }
+ if(last)
+ {
+ stakputs(name);
+ if(sh_checkid(stakptr(last),(char*)0))
+ stakseek(staktell()-2);
+ }
+ if(sub)
+ stak_subscript(sub,']');
+ if(!last)
+ stakputs(name);
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+/*
+ * grow this stack string <name> by <n> bytes and move from cp-1 to end
+ * right by <n>. Returns beginning of string on the stack
+ */
+static char *stack_extend(const char *cname, char *cp, int n)
+{
+ register char *name = (char*)cname;
+ int offset = name - stakptr(0);
+ int m = cp-name;
+ stakseek(strlen(name)+n+1);
+ name = stakptr(offset);
+ cp = name + m;
+ m = strlen(cp)+1;
+ while(m-->0)
+ cp[n+m]=cp[m];
+ return((char*)name);
+}
+
+Namval_t *nv_create(const char *name, Dt_t *root, int flags, Namfun_t *dp)
+{
+ Shell_t *shp = sh_getinterp();
+ char *sub=0, *cp=(char*)name, *sp, *xp;
+ register int c;
+ register Namval_t *np=0, *nq=0;
+ Namfun_t *fp=0;
+ long mode, add=0;
+ int copy=0,isref,top=0,noscope=(flags&NV_NOSCOPE);
+ int nofree=0, level=0;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ if(root==shp->var_tree)
+ {
+ if(dtvnext(root))
+ top = 1;
+ else
+ flags &= ~NV_NOSCOPE;
+ }
+ if(!dp->disc)
+ copy = dp->nofree&1;
+ if(*cp=='.')
+ cp++;
+ while(1)
+ {
+ switch(c = *(unsigned char*)(sp = cp))
+ {
+ case '[':
+ if(flags&NV_NOARRAY)
+ {
+ dp->last = cp;
+ return(np);
+ }
+ cp = nv_endsubscript((Namval_t*)0,sp,0);
+ if(sp==name || sp[-1]=='.')
+ c = *(sp = cp);
+ goto skip;
+ case '.':
+ if(flags&NV_IDENT)
+ return(0);
+ if(root==shp->var_tree)
+ flags &= ~NV_EXPORT;
+ if(!copy && !(flags&NV_NOREF))
+ {
+ c = sp-name;
+ copy = cp-name;
+ dp->nofree |= 1;
+ name = copystack((const char*)0, name,(const char*)0);
+ cp = (char*)name+copy;
+ sp = (char*)name+c;
+ c = '.';
+ }
+ skip:
+ case '+':
+ case '=':
+ *sp = 0;
+ case 0:
+ isref = 0;
+ dp->last = cp;
+ mode = (c=='.' || (flags&NV_NOADD))?add:NV_ADD;
+ if(level++ || ((flags&NV_NOSCOPE) && c!='.'))
+ mode |= HASH_NOSCOPE;
+ np=0;
+ if(top)
+ {
+ struct Ufunction *rp;
+ if((rp=shp->st.real_fun) && !rp->sdict && (flags&NV_STATIC))
+ {
+ Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0);
+ rp->sdict = dtopen(&_Nvdisc,Dtoset);
+ dtview(rp->sdict,dp);
+ dtview(shp->var_tree,rp->sdict);
+ }
+ if(np = nv_search(name,shp->var_tree,0))
+ {
+#if SHOPT_NAMESPACE
+ if(shp->var_tree->walk==shp->var_base || (shp->var_tree->walk!=shp->var_tree && shp->namespace && nv_dict(shp->namespace)==shp->var_tree->walk))
+#else
+ if(shp->var_tree->walk==shp->var_base)
+#endif /* SHOPT_NAMESPACE */
+ {
+#if SHOPT_NAMESPACE
+ if(!(nq = nv_search((char*)np,shp->var_base,HASH_BUCKET)))
+#endif /* SHOPT_NAMESPACE */
+ nq = np;
+ shp->last_root = shp->var_tree->walk;
+ if((flags&NV_NOSCOPE) && *cp!='.')
+ {
+ if(mode==0)
+ root = shp->var_tree->walk;
+ else
+ {
+ nv_delete(np,(Dt_t*)0,NV_NOFREE);
+ np = 0;
+ }
+ }
+ }
+ else
+ {
+ if(shp->var_tree->walk)
+ root = shp->var_tree->walk;
+ flags |= NV_NOSCOPE;
+ noscope = 1;
+ }
+ }
+ if(rp && rp->sdict && (flags&NV_STATIC))
+ {
+ root = rp->sdict;
+ if(np && shp->var_tree->walk==shp->var_tree)
+ {
+ _nv_unset(np,0);
+ nv_delete(np,shp->var_tree,0);
+ np = 0;
+ }
+ if(!np || shp->var_tree->walk!=root)
+ np = nv_search(name,root,HASH_NOSCOPE|NV_ADD);
+ }
+ }
+#if SHOPT_NAMESPACE
+ if(!np && !noscope && *name!='.' && shp->namespace && root==shp->var_tree)
+ root = nv_dict(shp->namespace);
+#endif /* SHOPT_NAMESPACE */
+ if(np || (np = nv_search(name,root,mode)))
+ {
+ isref = nv_isref(np);
+ shp->openmatch = 1;
+ if(top)
+ {
+ if(nq==np)
+ {
+ flags &= ~NV_NOSCOPE;
+ root = shp->last_root;
+ }
+ else if(nq)
+ {
+ if(nv_isnull(np) && c!='.' && (np->nvfun=nv_cover(nq)))
+ np->nvname = nq->nvname;
+ flags |= NV_NOSCOPE;
+ }
+ }
+ else if(add && nv_isnull(np) && c=='.' && cp[1]!='.')
+ nv_setvtree(np);
+#if SHOPT_NAMESPACE
+ if(shp->namespace && root==nv_dict(shp->namespace))
+ {
+ flags |= NV_NOSCOPE;
+ shp->last_table = shp->namespace;
+ }
+#endif /* SHOPT_NAMESPACE */
+ }
+ if(c)
+ *sp = c;
+ top = 0;
+ if(isref)
+ {
+#if SHOPT_FIXEDARRAY
+ int n=0,dim;
+#endif /* SHOPT_FIXEDARRAY */
+#if NVCACHE
+ nvcache.ok = 0;
+#endif
+ if(c=='.') /* don't optimize */
+ shp->argaddr = 0;
+ else if((flags&NV_NOREF) && (c!='[' && *cp!='.'))
+ {
+ if(c && !(flags&NV_NOADD))
+ nv_unref(np);
+ return(np);
+ }
+ while(nv_isref(np) && np->nvalue.cp)
+ {
+ root = nv_reftree(np);
+ shp->last_root = root;
+ shp->last_table = nv_reftable(np);
+ sub = nv_refsub(np);
+#if SHOPT_FIXEDARRAY
+ n = nv_refindex(np);
+ dim = nv_refdimen(np);
+#endif /* SHOPT_FIXEDARRAY */
+ np = nv_refnode(np);
+#if SHOPT_FIXEDARRAY
+ if(n)
+ {
+ ap = nv_arrayptr(np);
+ ap->nelem = dim;
+ nv_putsub(np,(char*)0,n);
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(sub && c!='.')
+ nv_putsub(np,sub,0L);
+ flags |= NV_NOSCOPE;
+ noscope = 1;
+ }
+ shp->first_root = root;
+ if(nv_isref(np) && (c=='[' || c=='.' || !(flags&NV_ASSIGN)))
+ errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np));
+ if(sub && c==0)
+ {
+ if(flags&NV_ARRAY)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ nq = nv_opensub(np);
+ if((flags&NV_ASSIGN) && (!nq || nv_isnull(nq)))
+ ap->nelem++;
+ if(!nq)
+ goto addsub;
+ }
+ return(np);
+ }
+ if(np==nq)
+ flags &= ~(noscope?0:NV_NOSCOPE);
+#if SHOPT_FIXEDARRAY
+ else if(c || n)
+#else
+ else if(c)
+#endif /* SHOPT_FIXEDARRAY */
+ {
+#if SHOPT_FIXEDARRAY
+ static char null[1] = "";
+#endif /* SHOPT_FIXEDARRAY */
+ c = (cp-sp);
+ copy = strlen(cp=nv_name(np));
+ dp->nofree |= 1;
+#if SHOPT_FIXEDARRAY
+ if(*sp==0)
+ name = cp;
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ name = copystack(cp,sp,sub);
+ sp = (char*)name + copy;
+ cp = sp+c;
+ c = *sp;
+ if(!noscope)
+ flags &= ~NV_NOSCOPE;
+#if SHOPT_FIXEDARRAY
+ if(c==0)
+ nv_endsubscript(np,null,NV_ADD);
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ flags |= NV_NOREF;
+ if(nv_isnull(np) && !nv_isarray(np))
+ nofree = NV_NOFREE;
+ }
+ shp->last_root = root;
+ if(*cp && cp[1]=='.')
+ cp++;
+ if(c=='.' && (cp[1]==0 || cp[1]=='=' || cp[1]=='+'))
+ {
+ nv_local = 1;
+ if(np)
+ nv_onattr(np,nofree);
+ return(np);
+ }
+ if(cp[-1]=='.')
+ cp--;
+ do
+ {
+#if SHOPT_FIXEDARRAY
+ int fixed;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!np)
+ {
+ if(!nq && *sp=='[' && *cp==0 && cp[-1]==']')
+ {
+ /*
+ * for backward compatibility
+ * evaluate subscript for
+ * possible side effects
+ */
+ cp[-1] = 0;
+ sh_arith(shp,sp+1);
+ cp[-1] = ']';
+ }
+ return(np);
+ }
+#if SHOPT_FIXEDARRAY
+ fixed = 0;
+ if((ap=nv_arrayptr(np)) && ap->fixed)
+ fixed = 1;
+#endif /* SHOPT_FIXEDARRAY */
+ if(c=='[' || (c=='.' && nv_isarray(np)))
+ {
+ int n = 0;
+ sub = 0;
+ mode &= ~HASH_NOSCOPE;
+ if(c=='[')
+ {
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap = nv_arrayptr(np);
+#endif /* SHOPT_FIXEDARRAY */
+#if 0
+ int scan = ap?(ap->nelem&ARRAY_SCAN):0;
+#endif
+ n = mode|nv_isarray(np);
+ if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']')
+ {
+ /* not implemented yet */
+ dp->last = cp;
+ return(np);
+ }
+#if SHOPT_FIXEDARRAY
+ if(fixed)
+ flags |= NV_FARRAY;
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if((n&NV_ADD)&&(flags&NV_ARRAY))
+ n |= ARRAY_FILL;
+ if(flags&NV_ASSIGN)
+ n |= NV_ADD;
+ cp = nv_endsubscript(np,sp,n|(flags&(NV_ASSIGN|NV_FARRAY)));
+#if SHOPT_FIXEDARRAY
+ flags &= ~NV_FARRAY;
+ if(fixed)
+ flags &= ~NV_ARRAY;
+
+#endif /* SHOPT_FIXEDARRAY */
+#if 0
+ if(scan)
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+#endif
+ }
+ else
+ cp = sp;
+ if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || (flags&NV_ARRAY))
+
+ {
+ int m = cp-sp;
+ sub = m?nv_getsub(np):0;
+ if(!sub)
+ {
+ if(m && !(n&NV_ADD))
+ return(0);
+ sub = "0";
+ }
+ n = strlen(sub)+2;
+ if(!copy)
+ {
+ copy = cp-name;
+ dp->nofree |= 1;
+ name = copystack((const char*)0, name,(const char*)0);
+ cp = (char*)name+copy;
+ sp = cp-m;
+ }
+ if(n <= m)
+ {
+ if(n)
+ {
+ memcpy(sp+1,sub,n-2);
+ sp[n-1] = ']';
+ }
+ if(n < m)
+ {
+ char *dp = sp+n;
+ while(*dp++=*cp++);
+ cp = sp+n;
+ }
+ }
+ else
+ {
+ int r = n-m;
+ m = sp-name;
+ name = stack_extend(name, cp-1, r);
+ sp = (char*)name + m;
+ *sp = '[';
+ memcpy(sp+1,sub,n-2);
+ sp[n-1] = ']';
+ cp = sp+n;
+
+ }
+ }
+ else if(c==0 && mode && (n=nv_aindex(np))>0)
+ nv_putsub(np,(char*)0,n);
+#if SHOPT_FIXEDARRAY
+ else if(n==0 && !fixed && (c==0 || (c=='[' && !nv_isarray(np))))
+#else
+ else if(n==0 && (c==0 || (c=='[' && !nv_isarray(np))))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ /* subscript must be 0*/
+ cp[-1] = 0;
+ n = sh_arith(shp,sp+1);
+ cp[-1] = ']';
+ if(n)
+ return(0);
+ if(c)
+ sp = cp;
+ }
+ dp->last = cp;
+ if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY)))
+ {
+ addsub:
+ sp = cp;
+ if(!(nq = nv_opensub(np)))
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ if(!sub && (flags&NV_NOADD))
+ return(0);
+ n = mode|((flags&NV_NOADD)?0:NV_ADD);
+ if(!ap && (n&NV_ADD))
+ {
+ nv_putsub(np,sub,ARRAY_FILL);
+ ap = nv_arrayptr(np);
+ }
+ if(n && ap && !ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap && ap->table && (nq=nv_search(sub,ap->table,n)))
+ nq->nvenv = (char*)np;
+ if(nq && nv_isnull(nq))
+ nq = nv_arraychild(np,nq,c);
+ }
+ if(nq)
+ {
+ if(c=='.' && !nv_isvtree(nq))
+ {
+ if(flags&NV_NOADD)
+ return(0);
+ nv_setvtree(nq);
+ }
+ nv_onattr(np,nofree);
+ nofree = 0;
+ np = nq;
+ }
+ else if(memcmp(cp,"[0]",3))
+ return(nq);
+ else
+ {
+ /* ignore [0] */
+ dp->last = cp += 3;
+ c = *cp;
+ }
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ else if(nv_isarray(np) && (!fixed || cp[-1]!=']'))
+#else
+ else if(nv_isarray(np))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(c==0 && (flags&NV_MOVE))
+ return(np);
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ }
+ nv_onattr(np,nofree);
+ nofree = 0;
+ if(c=='.' && (fp=np->nvfun))
+ {
+ for(; fp; fp=fp->next)
+ {
+ if(fp->disc && fp->disc->createf)
+ break;
+ }
+ if(fp)
+ {
+ if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np)
+ {
+ add = NV_ADD;
+ shp->last_table = 0;
+ break;
+ }
+ else if(np=nq)
+ {
+ if((c = *(sp=cp=dp->last=fp->last))==0)
+ {
+ if(nv_isarray(np) && sp[-1]!=']')
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ return(np);
+ }
+ }
+ }
+ }
+ }
+ while(c=='[');
+ if(c!='.' || cp[1]=='.')
+ return(np);
+ cp++;
+ break;
+ default:
+ dp->last = cp;
+ if((c = mbchar(cp)) && !isaletter(c))
+ return(np);
+ while(xp=cp, c=mbchar(cp), isaname(c));
+ cp = xp;
+ }
+ }
+ return(np);
+}
+
+/*
+ * delete the node <np> from the dictionary <root> and clear from the cache
+ * if <root> is NULL, only the cache is cleared
+ * if flags does not contain NV_NOFREE, the node is freed
+ * if np==0 && !root && flags==0, delete the Refdict dictionary
+ */
+void nv_delete(Namval_t* np, Dt_t *root, int flags)
+{
+#if NVCACHE
+ register int c;
+ struct Cache_entry *xp;
+ for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
+ {
+ if(xp->np==np)
+ xp->root = 0;
+ }
+#endif
+ if(!np && !root && flags==0)
+ {
+ if(Refdict)
+ dtclose(Refdict);
+ Refdict = 0;
+ return;
+ }
+ if(root || !(flags&NV_NOFREE))
+ {
+ if(!(flags&NV_FUNCTION) && Refdict)
+ {
+ Namval_t **key = &np;
+ struct Namref *rp;
+ while(rp = (struct Namref*)dtmatch(Refdict,(void*)key))
+ {
+ if(rp->sub)
+ free(rp->sub);
+ rp->sub = 0;
+ rp = dtdelete(Refdict,(void*)rp);
+ rp->np = &NullNode;
+ }
+ }
+ }
+ if(root)
+ {
+ if(dtdelete(root,np))
+ {
+ if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np)))
+ free((void*)np);
+ }
+#if 0
+ else
+ {
+ sfprintf(sfstderr,"%s not deleted\n",nv_name(np));
+ sfsync(sfstderr);
+ }
+#endif
+ }
+}
+
+/*
+ * Put <arg> into associative memory.
+ * If <flags> & NV_ARRAY then follow array to next subscript
+ * If <flags> & NV_NOARRAY then subscript is not allowed
+ * If <flags> & NV_NOSCOPE then use the current scope only
+ * If <flags> & NV_ASSIGN then assignment is allowed
+ * If <flags> & NV_IDENT then name must be an identifier
+ * If <flags> & NV_VARNAME then name must be a valid variable name
+ * If <flags> & NV_NOADD then node will not be added if not found
+ * If <flags> & NV_NOREF then don't follow reference
+ * If <flags> & NV_NOFAIL then don't generate an error message on failure
+ * If <flags> & NV_STATIC then unset before an assignment
+ * If <flags> & NV_UNJUST then unset attributes before assignment
+ * SH_INIT is only set while initializing the environment
+ */
+Namval_t *nv_open(const char *name, Dt_t *root, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *cp=(char*)name;
+ register int c;
+ register Namval_t *np=0;
+ Namfun_t fun;
+ int append=0;
+ const char *msg = e_varname;
+ char *fname = 0;
+ int offset = staktell();
+ Dt_t *funroot;
+#if NVCACHE
+ struct Cache_entry *xp;
+#endif
+
+ sh_stats(STAT_NVOPEN);
+ memset(&fun,0,sizeof(fun));
+ shp->openmatch = 0;
+ shp->last_table = 0;
+ if(!root)
+ root = shp->var_tree;
+ shp->last_root = root;
+ if(root==shp->fun_tree)
+ {
+ flags |= NV_NOREF;
+ msg = e_badfun;
+ if(strchr(name,'.'))
+ {
+ name = cp = copystack(0,name,(const char*)0);
+ fname = strrchr(cp,'.');
+ *fname = 0;
+ fun.nofree |= 1;
+ flags &= ~NV_IDENT;
+ funroot = root;
+ root = shp->var_tree;
+ }
+ }
+ else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN)))
+ {
+ long mode = ((flags&NV_NOADD)?0:NV_ADD);
+ if(flags&NV_NOSCOPE)
+ mode |= HASH_SCOPE|HASH_NOSCOPE;
+ np = nv_search(name,root,mode);
+ if(np && !(flags&NV_REF))
+ {
+ while(nv_isref(np))
+ {
+ shp->last_table = nv_reftable(np);
+ np = nv_refnode(np);
+ }
+ }
+ return(np);
+ }
+ else if(shp->prefix && (flags&NV_ASSIGN))
+ {
+ name = cp = copystack(shp->prefix,name,(const char*)0);
+ fun.nofree |= 1;
+ }
+ c = *(unsigned char*)cp;
+ if(root==shp->alias_tree)
+ {
+ msg = e_aliname;
+ while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
+ (c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
+ if(shp->subshell && c=='=')
+ root = sh_subaliastree(1);
+ if(c= *--cp)
+ *cp = 0;
+ np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD);
+ if(c)
+ *cp = c;
+ goto skip;
+ }
+ else if(flags&NV_IDENT)
+ msg = e_ident;
+ else if(c=='.')
+ {
+ c = *++cp;
+ flags |= NV_NOREF;
+ if(root==shp->var_tree)
+ root = shp->var_base;
+ shp->last_table = 0;
+ }
+ if(c= !isaletter(c))
+ goto skip;
+#if NVCACHE
+ for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
+ {
+ if(xp->root!=root)
+ continue;
+ if(*name==*xp->name && (flags&(NV_ARRAY|NV_NOSCOPE))==xp->flags && memcmp(xp->name,name,xp->len)==0 && (name[xp->len]==0 || name[xp->len]=='=' || name[xp->len]=='+'))
+ {
+ sh_stats(STAT_NVHITS);
+ np = xp->np;
+ cp = (char*)name+xp->len;
+ if(nv_isarray(np) && !(flags&NV_MOVE))
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ shp->last_table = xp->last_table;
+ shp->last_root = xp->last_root;
+ goto nocache;
+ }
+ }
+ nvcache.ok = 1;
+#endif
+ np = nv_create(name, root, flags, &fun);
+ cp = fun.last;
+#if NVCACHE
+ if(np && nvcache.ok && cp[-1]!=']')
+ {
+ xp = &nvcache.entries[nvcache.index];
+ if(*cp)
+ {
+ char *sp = strchr(name,*cp);
+ if(!sp)
+ goto nocache;
+ xp->len = sp-name;
+ }
+ else
+ xp->len = strlen(name);
+ c = roundof(xp->len+1,32);
+ if(c > xp->size)
+ {
+ if(xp->size==0)
+ xp->name = malloc(c);
+ else
+ xp->name = realloc(xp->name,c);
+ xp->size = c;
+ }
+ memcpy(xp->name,name,xp->len);
+ xp->name[xp->len] = 0;
+ xp->root = root;
+ xp->np = np;
+ xp->last_table = shp->last_table;
+ xp->last_root = shp->last_root;
+ xp->flags = (flags&(NV_ARRAY|NV_NOSCOPE));
+ nvcache.index = (nvcache.index+1)&(NVCACHE-1);
+ }
+nocache:
+ nvcache.ok = 0;
+#endif
+ if(fname)
+ {
+ c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD);
+ *fname = '.';
+ np = nv_search(name, funroot, c);
+ *fname = 0;
+ }
+ else
+ {
+ if(*cp=='.' && cp[1]=='.')
+ {
+ append |= NV_NODISC;
+ cp+=2;
+ }
+ if(*cp=='+' && cp[1]=='=')
+ {
+ append |= NV_APPEND;
+ cp++;
+ }
+ }
+ c = *cp;
+skip:
+#if SHOPT_TYPEDEF
+ if(np && shp->mktype)
+ np = nv_addnode(np,0);
+#endif /* SHOPT_TYPEDEF */
+ if(c=='=' && np && (flags&NV_ASSIGN))
+ {
+ cp++;
+ if(sh_isstate(SH_INIT))
+ {
+ nv_putval(np, cp, NV_RDONLY);
+ if(np==PWDNOD)
+ nv_onattr(np,NV_TAGGED);
+ }
+ else
+ {
+ char *sub=0, *prefix= shp->prefix;
+ Namval_t *mp;
+ Namarr_t *ap;
+ int isref;
+ shp->prefix = 0;
+ if((flags&NV_STATIC) && !shp->mktype)
+ {
+ if(!nv_isnull(np))
+ {
+ shp->prefix = prefix;
+ return(np);
+ }
+ }
+ isref = nv_isref(np);
+#if SHOPT_FIXEDARRAY
+ if(sh_isoption(SH_XTRACE) && (ap=nv_arrayptr(np)) && !ap->fixed)
+#else
+ if(sh_isoption(SH_XTRACE) && nv_isarray(np))
+#endif /* SHOPT_FIXEDARRAY */
+ sub = nv_getsub(np);
+ c = msg==e_aliname? 0: (append | (flags&NV_EXPORT));
+ if(isref)
+ nv_offattr(np,NV_REF);
+ if(!append && (flags&NV_UNJUST))
+ {
+ nv_offattr(np,NV_LJUST|NV_RJUST|NV_ZFILL);
+ np->nvsize = 0;
+ }
+ if(flags&NV_MOVE)
+ {
+ if(ap=nv_arrayptr(np))
+ {
+ if(mp=nv_opensub(np))
+ np = mp;
+ else if(!array_assoc(ap) && (mp = nv_open(cp,shp->var_tree,NV_NOFAIL|NV_VARNAME|NV_NOARRAY|NV_NOASSIGN|NV_NOADD)) && nv_isvtree(np))
+ {
+ ap->nelem |= ARRAY_TREE;
+ nv_putsub(np,(char*)0,ARRAY_ADD|nv_aindex(np));
+ np = nv_opensub(np);
+ ap->nelem &= ~ARRAY_TREE;
+ ap->nelem -= 1;
+ }
+ }
+ _nv_unset(np,NV_EXPORT);
+ }
+ nv_putval(np, cp, c);
+ if(isref)
+ {
+ if(nv_search((char*)np,shp->var_base,HASH_BUCKET))
+ shp->last_root = shp->var_base;
+ nv_setref(np,(Dt_t*)0,NV_VARNAME);
+ }
+ savesub = sub;
+ shp->prefix = prefix;
+ }
+ nv_onattr(np, flags&NV_ATTRIBUTES);
+ }
+ else if(c)
+ {
+ if(flags&NV_NOFAIL)
+ return(0);
+ if(c=='.')
+ msg = e_noparent;
+ else if(c=='[')
+ msg = e_noarray;
+ errormsg(SH_DICT,ERROR_exit(1),msg,name);
+ }
+ if(fun.nofree&1)
+ stakseek(offset);
+ return(np);
+}
+
+#if SHOPT_MULTIBYTE
+ static int ja_size(char*, int, int);
+ static void ja_restore(void);
+ static char *savep;
+ static char savechars[8+1];
+#endif /* SHOPT_MULTIBYTE */
+
+/*
+ * put value <string> into name-value node <np>.
+ * If <np> is an array, then the element given by the
+ * current index is assigned to.
+ * If <flags> contains NV_RDONLY, readonly attribute is ignored
+ * If <flags> contains NV_INTEGER, string is a pointer to a number
+ * If <flags> contains NV_NOFREE, previous value is freed, and <string>
+ * becomes value of node and <flags> becomes attributes
+ */
+void nv_putval(register Namval_t *np, const char *string, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register const char *sp=string;
+ register union Value *up;
+ register char *cp;
+ register int size = 0;
+ register int dot;
+ int was_local = nv_local;
+ union Value u;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ /* The following could cause the shell to fork if assignment
+ * would cause a side effect
+ */
+ shp->argaddr = 0;
+ if(shp->subshell && !nv_local)
+ np = sh_assignok(np,1);
+ if(np->nvfun && np->nvfun->disc && !(flags&NV_NODISC) && !nv_isref(np))
+ {
+ /* This function contains disc */
+ if(!nv_local)
+ {
+ nv_local=1;
+ nv_putv(np,sp,flags,np->nvfun);
+ if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
+ sh_envput(shp->env,np);
+ return;
+ }
+ /* called from disc, assign the actual value */
+ }
+ flags &= ~NV_NODISC;
+ nv_local=0;
+ if(flags&(NV_NOREF|NV_NOFREE))
+ {
+ if(np->nvalue.cp && np->nvalue.cp!=sp && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvalue.cp);
+ np->nvalue.cp = (char*)sp;
+ nv_setattr(np,(flags&~NV_RDONLY)|NV_NOFREE);
+ return;
+ }
+ up= &np->nvalue;
+ if(nv_isattr(np,NV_INT16P) == NV_INT16)
+ {
+ if(!np->nvalue.up || !nv_isarray(np))
+ {
+ up = &u;
+ up->up = &np->nvalue;
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ else if(np->nvalue.up && nv_isarray(np) && (ap=nv_arrayptr(np)) && !ap->fixed)
+#else
+ else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np))
+#endif /* SHOPT_FIXEDARRAY */
+ up = np->nvalue.up;
+ if(up && up->cp==Empty)
+ up->cp = 0;
+ if(nv_isattr(np,NV_EXPORT))
+ nv_offattr(np,NV_IMPORT);
+ if(nv_isattr (np, NV_INTEGER))
+ {
+ if(nv_isattr(np, NV_DOUBLE) == NV_DOUBLE)
+ {
+ if(nv_isattr(np, NV_LONG) && sizeof(double)<sizeof(Sfdouble_t))
+ {
+ Sfdouble_t ld, old=0;
+ if(flags&NV_INTEGER)
+ {
+ if(flags&NV_LONG)
+ ld = *((Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ ld = *((float*)sp);
+ else
+ ld = *((double*)sp);
+ }
+ else
+ ld = sh_arith(shp,sp);
+ if(!up->ldp)
+ up->ldp = new_of(Sfdouble_t,0);
+ else if(flags&NV_APPEND)
+ old = *(up->ldp);
+ *(up->ldp) = old?ld+old:ld;
+ }
+ else
+ {
+ double d,od=0;
+ if(flags&NV_INTEGER)
+ {
+ if(flags&NV_LONG)
+ d = (double)(*(Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ d = (double)(*(float*)sp);
+ else
+ d = *(double*)sp;
+ }
+ else
+ d = sh_arith(shp,sp);
+ if(!up->dp)
+ up->dp = new_of(double,0);
+ else if(flags&NV_APPEND)
+ od = *(up->dp);
+ *(up->dp) = od?d+od:d;
+ }
+ }
+ else
+ {
+ if(nv_isattr(np, NV_LONG) && sizeof(int32_t)<sizeof(Sflong_t))
+ {
+ Sflong_t ll=0,oll=0;
+ if(flags&NV_INTEGER)
+ {
+ if((flags&NV_DOUBLE) == NV_DOUBLE)
+ {
+ if(flags&NV_LONG)
+ ll = *((Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((float*)sp);
+ else
+ ll = *((double*)sp);
+ }
+ else if(nv_isattr(np,NV_UNSIGN))
+ {
+ if(flags&NV_LONG)
+ ll = *((Sfulong_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((uint16_t*)sp);
+ else
+ ll = *((uint32_t*)sp);
+ }
+ else
+ {
+ if(flags&NV_LONG)
+ ll = *((Sflong_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((uint16_t*)sp);
+ else
+ ll = *((uint32_t*)sp);
+ }
+ }
+ else if(sp)
+ ll = (Sflong_t)sh_arith(shp,sp);
+ if(!up->llp)
+ up->llp = new_of(Sflong_t,0);
+ else if(flags&NV_APPEND)
+ oll = *(up->llp);
+ *(up->llp) = ll+oll;
+ }
+ else
+ {
+ int32_t l=0,ol=0;
+ if(flags&NV_INTEGER)
+ {
+ if((flags&NV_DOUBLE) == NV_DOUBLE)
+ {
+ Sflong_t ll;
+ if(flags&NV_LONG)
+ ll = *((Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((float*)sp);
+ else
+ ll = *((double*)sp);
+ l = (int32_t)ll;
+ }
+ else if(nv_isattr(np,NV_UNSIGN))
+ {
+ if(flags&NV_LONG)
+ l = *((Sfulong_t*)sp);
+ else if(flags&NV_SHORT)
+ l = *((uint16_t*)sp);
+ else
+ l = *(uint32_t*)sp;
+ }
+ else
+ {
+ if(flags&NV_LONG)
+ l = *((Sflong_t*)sp);
+ else if(flags&NV_SHORT)
+ l = *((int16_t*)sp);
+ else
+ l = *(int32_t*)sp;
+ }
+ }
+ else if(sp)
+ {
+ Sfdouble_t ld = sh_arith(shp,sp);
+ if(ld<0)
+ l = (int32_t)ld;
+ else
+ l = (uint32_t)ld;
+ }
+ if(nv_size(np) <= 1)
+ nv_setsize(np,10);
+ if(nv_isattr (np, NV_SHORT))
+ {
+ int16_t s=0;
+ if(flags&NV_APPEND)
+ s = *up->sp;
+ *(up->sp) = s+(int16_t)l;
+ nv_onattr(np,NV_NOFREE);
+ }
+ else
+ {
+ if(!up->lp)
+ up->lp = new_of(int32_t,0);
+ else if(flags&NV_APPEND)
+ ol = *(up->lp);
+ *(up->lp) = l+ol;
+ }
+ }
+ }
+ }
+ else
+ {
+ const char *tofree=0;
+ int offset,append;
+#if _lib_pathnative
+ char buff[PATH_MAX];
+#endif /* _lib_pathnative */
+ if(flags&NV_INTEGER)
+ {
+ if((flags&NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(flags&NV_LONG)
+ sfprintf(shp->strbuf,"%.*Lg",LDBL_DIG,*((Sfdouble_t*)sp));
+ else
+ sfprintf(shp->strbuf,"%.*g",DBL_DIG,*((double*)sp));
+ }
+ else if(flags&NV_UNSIGN)
+ {
+ if(flags&NV_LONG)
+ sfprintf(shp->strbuf,"%I*lu",sizeof(Sfulong_t),*((Sfulong_t*)sp));
+ else
+ sfprintf(shp->strbuf,"%lu",(unsigned long)((flags&NV_SHORT)?*((uint16_t*)sp):*((uint32_t*)sp)));
+ }
+ else
+ {
+ if(flags&NV_LONG)
+ sfprintf(shp->strbuf,"%I*ld",sizeof(Sflong_t),*((Sflong_t*)sp));
+ else
+ sfprintf(shp->strbuf,"%ld",(long)((flags&NV_SHORT)?*((int16_t*)sp):*((int32_t*)sp)));
+ }
+ sp = sfstruse(shp->strbuf);
+ }
+ if(nv_isattr(np, NV_HOST|NV_INTEGER)==NV_HOST && sp)
+ {
+#ifdef _lib_pathnative
+ /*
+ * return the host file name given the UNIX name
+ */
+ pathnative(sp,buff,sizeof(buff));
+ if(buff[1]==':' && buff[2]=='/')
+ {
+ buff[2] = '\\';
+ if(*buff>='A' && *buff<='Z')
+ *buff += 'a'-'A';
+ }
+ sp = buff;
+#else
+ ;
+#endif /* _lib_pathnative */
+ }
+ else if((nv_isattr(np, NV_RJUST|NV_ZFILL|NV_LJUST)) && sp)
+ {
+ for(;*sp == ' '|| *sp=='\t';sp++);
+ if((nv_isattr(np,NV_ZFILL)) && (nv_isattr(np,NV_LJUST)))
+ for(;*sp=='0';sp++);
+ size = nv_size(np);
+#if SHOPT_MULTIBYTE
+ if(size)
+ size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL));
+#endif /* SHOPT_MULTIBYTE */
+ }
+ if(!up->cp || *up->cp==0)
+ flags &= ~NV_APPEND;
+ if(!nv_isattr(np, NV_NOFREE))
+ {
+ /* delay free in case <sp> points into free region */
+ tofree = up->cp;
+ }
+ if(nv_isattr(np,NV_BINARY) && !(flags&NV_RAW))
+ tofree = 0;
+ if(nv_isattr(np,NV_LJUST|NV_RJUST) && nv_isattr(np,NV_LJUST|NV_RJUST)!=(NV_LJUST|NV_RJUST))
+ tofree = 0;
+ if (sp)
+ {
+ append=0;
+ dot = strlen(sp);
+#if (_AST_VERSION>=20030127L)
+ if(nv_isattr(np,NV_BINARY))
+ {
+ int oldsize = (flags&NV_APPEND)?nv_size(np):0;
+ if(flags&NV_RAW)
+ {
+ if(tofree)
+ {
+ free((void*)tofree);
+ nv_offattr(np,NV_NOFREE);
+ }
+ up->cp = sp;
+ return;
+ }
+ size = 0;
+ if(nv_isattr(np,NV_ZFILL))
+ size = nv_size(np);
+ if(size==0)
+ size = oldsize + (3*dot/4);
+ cp = (char*)malloc(size+1);
+ nv_offattr(np,NV_NOFREE);
+ if(oldsize)
+ memcpy((void*)cp,(void*)up->cp,oldsize);
+ up->cp = cp;
+ if(size <= oldsize)
+ return;
+ dot = base64decode(sp,dot, (void**)0, cp+oldsize, size-oldsize,(void**)0);
+ dot += oldsize;
+ if(!nv_isattr(np,NV_ZFILL) || nv_size(np)==0)
+ nv_setsize(np,dot);
+ else if(nv_isattr(np,NV_ZFILL) && (size>dot))
+ memset((void*)&cp[dot],0,size-dot);
+ return;
+ }
+ else
+#endif
+ {
+ if(size==0 && nv_isattr(np,NV_HOST)!=NV_HOST &&nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL))
+ nv_setsize(np,size=dot);
+ else if(size > dot)
+ dot = size;
+ else if(nv_isattr(np,NV_LJUST|NV_RJUST)==NV_LJUST && dot>size)
+ dot = size;
+ if(flags&NV_APPEND)
+ {
+ if(dot==0)
+ return;
+ append = strlen(up->cp);
+ if(!tofree || size)
+ {
+ offset = staktell();
+ stakputs(up->cp);
+ stakputs(sp);
+ stakputc(0);
+ sp = stakptr(offset);
+ dot += append;
+ append = 0;
+ }
+ else
+ {
+ flags &= ~NV_APPEND;
+ }
+ }
+ }
+ if(size==0 || tofree || dot || !(cp=(char*)up->cp))
+ {
+ if(dot==0 && !nv_isattr(np,NV_LJUST|NV_RJUST))
+ {
+ cp = Null;
+ nv_onattr(np,NV_NOFREE);
+ }
+ else
+ {
+ if(tofree && tofree!=Empty && tofree!=Null)
+ {
+ cp = (char*)realloc((void*)tofree,((unsigned)dot+append+8));
+ tofree = 0;
+ }
+ else
+ cp = (char*)malloc(((unsigned)dot+8));
+ cp[dot+append] = 0;
+ nv_offattr(np,NV_NOFREE);
+ }
+ }
+
+ }
+ else
+ cp = 0;
+ up->cp = cp;
+ if(sp)
+ {
+ int c = cp[dot+append];
+ memmove(cp+append,sp,dot);
+ cp[dot+append] = c;
+ if(nv_isattr(np, NV_RJUST) && nv_isattr(np, NV_ZFILL))
+ rightjust(cp,size,'0');
+ else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_RJUST)
+ rightjust(cp,size,' ');
+ else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_LJUST)
+ {
+ register char *dp;
+ dp = strlen (cp) + cp;
+ cp = cp+size;
+ for (; dp < cp; *dp++ = ' ');
+ }
+#if SHOPT_MULTIBYTE
+ /* restore original string */
+ if(savep)
+ ja_restore();
+#endif /* SHOPT_MULTIBYTE */
+ }
+ if(flags&NV_APPEND)
+ stakseek(offset);
+ if(tofree && tofree!=Empty && tofree!=Null)
+ free((void*)tofree);
+ }
+ if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
+ sh_envput(shp->env,np);
+ return;
+}
+
+/*
+ *
+ * Right-justify <str> so that it contains no more than
+ * <size> characters. If <str> contains fewer than <size>
+ * characters, left-pad with <fill>. Trailing blanks
+ * in <str> will be ignored.
+ *
+ * If the leftmost digit in <str> is not a digit, <fill>
+ * will default to a blank.
+ */
+static void rightjust(char *str, int size, int fill)
+{
+ register int n;
+ register char *cp,*sp;
+ n = strlen(str);
+
+ /* ignore trailing blanks */
+ for(cp=str+n;n && *--cp == ' ';n--);
+ if (n == size)
+ return;
+ if(n > size)
+ {
+ *(str+n) = 0;
+ for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++);
+ return;
+ }
+ else *(sp = str+size) = 0;
+ if (n == 0)
+ {
+ while (sp > str)
+ *--sp = ' ';
+ return;
+ }
+ while(n--)
+ {
+ sp--;
+ *sp = *cp--;
+ }
+ if(!isdigit(*str))
+ fill = ' ';
+ while(sp>str)
+ *--sp = fill;
+ return;
+}
+
+#if SHOPT_MULTIBYTE
+ /*
+ * handle left and right justified fields for multi-byte chars
+ * given physical size, return a logical size which reflects the
+ * screen width of multi-byte characters
+ * Multi-width characters replaced by spaces if they cross the boundary
+ * <type> is non-zero for right justified fields
+ */
+
+ static int ja_size(char *str,int size,int type)
+ {
+ register char *cp = str;
+ register int c, n=size;
+ register int outsize;
+ register char *oldcp=cp;
+ int oldn;
+ wchar_t w;
+ while(*cp)
+ {
+ oldn = n;
+ w = mbchar(cp);
+ outsize = mbwidth(w);
+ size -= outsize;
+ c = cp-oldcp;
+ n += (c-outsize);
+ oldcp = cp;
+ if(size<=0 && type==0)
+ break;
+ }
+ /* check for right justified fields that need truncating */
+ if(size <0)
+ {
+ if(type==0)
+ {
+ /* left justified and character crosses field boundary */
+ n = oldn;
+ /* save boundary char and replace with spaces */
+ size = c;
+ savechars[size] = 0;
+ while(size--)
+ {
+ savechars[size] = cp[size];
+ cp[size] = ' ';
+ }
+ savep = cp;
+ }
+ size = -size;
+ if(type)
+ n -= (ja_size(str,size,0)-size);
+ }
+ return(n);
+ }
+
+ static void ja_restore(void)
+ {
+ register char *cp = savechars;
+ while(*cp)
+ *savep++ = *cp++;
+ savep = 0;
+ }
+#endif /* SHOPT_MULTIBYTE */
+
+#ifndef _ENV_H
+static char *staknam(register Namval_t *np, char *value)
+{
+ register char *p,*q;
+ q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2);
+ p=strcopy(q,nv_name(np));
+ if(value)
+ {
+ *p++ = '=';
+ strcpy(p,value);
+ }
+ return(q);
+}
+#endif
+
+/*
+ * put the name and attribute into value of attributes variable
+ */
+#ifdef _ENV_H
+static void attstore(register Namval_t *np, void *data)
+{
+ register int flag, c = ' ';
+ NOT_USED(data);
+ if(!(nv_isattr(np,NV_EXPORT)))
+ return;
+ flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
+ stakputc('=');
+ if((flag&NV_DOUBLE) == NV_DOUBLE)
+ {
+ /* export doubles as integers for ksh88 compatibility */
+ stakputc(c+NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE)));
+ }
+ else
+ {
+ stakputc(c+flag);
+ if(flag&NV_INTEGER)
+ c += nv_size(np);
+ }
+ stakputc(c);
+ stakputs(nv_name(np));
+}
+#else
+static void attstore(register Namval_t *np, void *data)
+{
+ register int flag = np->nvflag;
+ register struct adata *ap = (struct adata*)data;
+ ap->sh = sh_getinterp();
+ ap->tp = 0;
+ if(!(flag&NV_EXPORT) || (flag&NV_FUNCT))
+ return;
+ if((flag&(NV_UTOL|NV_LTOU|NV_INTEGER)) == (NV_UTOL|NV_LTOU))
+ {
+ data = (void*)nv_mapchar(np,0);
+ if(strcmp(data,e_tolower) && strcmp(data,e_toupper))
+ return;
+ }
+ flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
+ *ap->attval++ = '=';
+ if((flag&NV_DOUBLE) == NV_DOUBLE)
+ {
+ /* export doubles as integers for ksh88 compatibility */
+ *ap->attval++ = ' '+ NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE));
+ *ap->attval = ' ';
+ }
+ else
+ {
+ *ap->attval++ = ' '+flag;
+ if(flag&NV_INTEGER)
+ *ap->attval = ' ' + nv_size(np);
+ else
+ *ap->attval = ' ';
+ }
+ ap->attval = strcopy(++ap->attval,nv_name(np));
+}
+#endif
+
+#ifndef _ENV_H
+static void pushnam(Namval_t *np, void *data)
+{
+ register char *value;
+ register struct adata *ap = (struct adata*)data;
+ ap->sh = sh_getinterp();
+ ap->tp = 0;
+ if(nv_isattr(np,NV_IMPORT) && np->nvenv)
+ *ap->argnam++ = np->nvenv;
+ else if(value=nv_getval(np))
+ *ap->argnam++ = staknam(np,value);
+ if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER))
+ ap->attsize += (strlen(nv_name(np))+4);
+}
+#endif
+
+/*
+ * Generate the environment list for the child.
+ */
+
+#ifdef _ENV_H
+char **sh_envgen(void)
+{
+ Shell_t *shp = sh_getinterp();
+ int offset,tell;
+ register char **er;
+ env_delete(shp->env,"_");
+ er = env_get(shp->env);
+ offset = staktell();
+ stakputs(e_envmarker);
+ tell = staktell();
+ nv_scan(shp->var_tree, attstore,(void*)0,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER));
+ if(tell ==staktell())
+ stakseek(offset);
+ else
+ *--er = stakfreeze(1)+offset;
+ return(er);
+}
+#else
+char **sh_envgen(void)
+{
+ register char **er;
+ register int namec;
+ register char *cp;
+ struct adata data;
+ Shell_t *shp = sh_getinterp();
+ data.sh = shp;
+ data.tp = 0;
+ data.mapname = 0;
+ /* L_ARGNOD gets generated automatically as full path name of command */
+ nv_offattr(L_ARGNOD,NV_EXPORT);
+ data.attsize = 6;
+ namec = nv_scan(shp->var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT);
+ namec += shp->nenv;
+ er = (char**)stakalloc((namec+4)*sizeof(char*));
+ data.argnam = (er+=2) + shp->nenv;
+ if(shp->nenv)
+ memcpy((void*)er,environ,shp->nenv*sizeof(char*));
+ nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT);
+ *data.argnam = (char*)stakalloc(data.attsize);
+ cp = data.attval = strcopy(*data.argnam,e_envmarker);
+ nv_scan(shp->var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER));
+ *data.attval = 0;
+ if(cp!=data.attval)
+ data.argnam++;
+ *data.argnam = 0;
+ return(er);
+}
+#endif
+
+struct scan
+{
+ void (*scanfn)(Namval_t*, void*);
+ int scanmask;
+ int scanflags;
+ int scancount;
+ void *scandata;
+};
+
+static int scanfilter(Dt_t *dict, void *arg, void *data)
+{
+ register Namval_t *np = (Namval_t*)arg;
+ register int k=np->nvflag;
+ register struct scan *sp = (struct scan*)data;
+ register struct adata *tp = (struct adata*)sp->scandata;
+ char *cp;
+ NOT_USED(dict);
+#if SHOPT_TYPEDEF
+ if(!is_abuiltin(np) && tp && tp->tp && nv_type(np)!=tp->tp)
+ return(0);
+#endif /*SHOPT_TYPEDEF */
+ if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags)))
+ {
+ if(tp && tp->mapname)
+ {
+ if(sp->scanflags==NV_FUNCTION || sp->scanflags==(NV_NOFREE|NV_BINARY|NV_RAW))
+ {
+ int n = strlen(tp->mapname);
+ if(memcmp(np->nvname,tp->mapname,n) || np->nvname[n]!='.' || strchr(&np->nvname[n+1],'.'))
+ return(0);
+ }
+ else if((sp->scanflags==NV_UTOL||sp->scanflags==NV_LTOU) && (cp=(char*)nv_mapchar(np,0)) && strcmp(cp,tp->mapname))
+ return(0);
+ }
+ if(!np->nvalue.cp && !np->nvfun && !nv_isattr(np,~NV_DEFAULT))
+ return(0);
+ if(sp->scanfn)
+ {
+ if(nv_isarray(np))
+ nv_putsub(np,NIL(char*),0L);
+ (*sp->scanfn)(np,sp->scandata);
+ }
+ sp->scancount++;
+ }
+ return(0);
+}
+
+/*
+ * Walk through the name-value pairs
+ * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags
+ * are visited
+ * If <mask> is zero, and <flags> non-zero, then nodes with one or
+ * more of <flags> is visited
+ * If <mask> and <flags> are zero, then all nodes are visted
+ */
+int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags)
+{
+ Dt_t *base=0;
+ struct scan sdata;
+ int (*hashfn)(Dt_t*, void*, void*);
+ sdata.scanmask = mask;
+ sdata.scanflags = flags&~NV_NOSCOPE;
+ sdata.scanfn = fn;
+ sdata.scancount = 0;
+ sdata.scandata = data;
+ hashfn = scanfilter;
+ if(flags&NV_NOSCOPE)
+ base = dtview((Dt_t*)root,0);
+ dtwalk(root, hashfn,&sdata);
+ if(base)
+ dtview((Dt_t*)root,base);
+ return(sdata.scancount);
+}
+
+/*
+ * create a new environment scope
+ */
+void sh_scope(Shell_t *shp, struct argnod *envlist, int fun)
+{
+ register Dt_t *newscope, *newroot=shp->var_base;
+ struct Ufunction *rp;
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ {
+ newroot = nv_dict(shp->namespace);
+ dtview(newroot,(Dt_t*)shp->var_base);
+ }
+#endif /* SHOPT_NAMESPACE */
+ newscope = dtopen(&_Nvdisc,Dtoset);
+ if(envlist)
+ {
+ dtview(newscope,(Dt_t*)shp->var_tree);
+ shp->var_tree = newscope;
+ nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN,0);
+ if(!fun)
+ return;
+ shp->var_tree = dtview(newscope,0);
+ }
+ if((rp=shp->st.real_fun) && rp->sdict)
+ {
+ dtview(rp->sdict,newroot);
+ newroot = rp->sdict;
+
+ }
+ dtview(newscope,(Dt_t*)newroot);
+ shp->var_tree = newscope;
+}
+
+/*
+ * Remove freeable local space associated with the nvalue field
+ * of nnod. This includes any strings representing the value(s) of the
+ * node, as well as its dope vector, if it is an array.
+ */
+
+void sh_envnolocal (register Namval_t *np, void *data)
+{
+ struct adata *tp = (struct adata*)data;
+ char *cp=0;
+ if(np==VERSIONNOD && nv_isref(np))
+ return;
+ if(np==L_ARGNOD)
+ return;
+ if(np == tp->sh->namespace)
+ return;
+ if(nv_isref(np))
+ nv_unref(np);
+ if(nv_isattr(np,NV_EXPORT) && nv_isarray(np))
+ {
+ nv_putsub(np,NIL(char*),0);
+ if(cp = nv_getval(np))
+ cp = strdup(cp);
+ }
+ if(nv_isattr(np,NV_EXPORT|NV_NOFREE))
+ {
+ if(nv_isref(np) && np!=VERSIONNOD)
+ {
+ nv_offattr(np,NV_NOFREE|NV_REF);
+ free((void*)np->nvalue.nrp);
+ np->nvalue.cp = 0;
+ }
+ if(!cp)
+ return;
+ }
+ if(nv_isarray(np))
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ _nv_unset(np,NV_RDONLY);
+ nv_setattr(np,0);
+ if(cp)
+ {
+ nv_putval(np,cp,0);
+ free((void*)cp);
+ }
+}
+
+/*
+ * Currently this is a dummy, but someday will be needed
+ * for reference counting
+ */
+void nv_close(Namval_t *np)
+{
+ NOT_USED(np);
+}
+
+static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroot)
+{
+ register Namval_t *np,*nq, *npnext;
+ for(np=(Namval_t*)dtfirst(root);np;np=npnext)
+ {
+ if(nq=dtsearch(oroot,np))
+ {
+ if(nv_cover(nq))
+ {
+ int subshell = shp->subshell;
+ shp->subshell = 0;
+ if(nv_isattr(nq, NV_INTEGER))
+ {
+ Sfdouble_t d = nv_getnum(nq);
+ nv_putval(nq,(char*)&d,NV_LDOUBLE);
+ }
+ else if(shp->test&4)
+ nv_putval(nq, strdup(nv_getval(nq)), NV_RDONLY);
+ else
+ nv_putval(nq, nv_getval(nq), NV_RDONLY);
+ shp->subshell = subshell;
+ np->nvfun = 0;
+ }
+ if(nv_isattr(nq,NV_EXPORT))
+ sh_envput(shp->env,nq);
+ }
+ npnext = (Namval_t*)dtnext(root,np);
+ shp->last_root = root;
+ shp->last_table = 0;
+ if(nv_isvtree(np))
+ {
+ int len = strlen(np->nvname);
+ while((nq=npnext) && memcmp(np->nvname,nq->nvname,len)==0 && nq->nvname[len]=='.')
+
+ {
+ npnext = (Namval_t*)dtnext(root,nq);
+ _nv_unset(nq,flags);
+ nv_delete(nq,root,0);
+ }
+ }
+ _nv_unset(np,flags);
+ nv_delete(np,root,0);
+ }
+}
+
+/*
+ *
+ * Set the value of <np> to 0, and nullify any attributes
+ * that <np> may have had. Free any freeable space occupied
+ * by the value of <np>. If <np> denotes an array member, it
+ * will retain its attributes.
+ * <flags> can contain NV_RDONLY to override the readonly attribute
+ * being cleared.
+ * <flags> can contain NV_EXPORT to override preserve nvenv
+ */
+void _nv_unset(register Namval_t *np,int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register union Value *up;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ if(is_afunction(np) && np->nvalue.ip)
+ {
+ register struct slnod *slp = (struct slnod*)(np->nvenv);
+ if(slp && !nv_isattr(np,NV_NOFREE))
+ {
+ struct Ufunction *rq,*rp = np->nvalue.rp;
+ /* free function definition */
+ register char *name=nv_name(np),*cp= strrchr(name,'.');
+ if(cp)
+ {
+ Namval_t *npv;
+ *cp = 0;
+ npv = nv_open(name,shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD);
+ *cp++ = '.';
+ if(npv && npv!=shp->namespace)
+ nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv);
+ }
+ if(rp->fname && shp->fpathdict && (rq = (struct Ufunction*)nv_search(rp->fname,shp->fpathdict,0)))
+ {
+ do
+ {
+ if(rq->np != np)
+ continue;
+ dtdelete(shp->fpathdict,rq);
+ break;
+ }
+ while(rq = (struct Ufunction*)dtnext(shp->fpathdict,rq));
+ }
+ if(rp->sdict)
+ {
+ Namval_t *mp, *nq;
+ for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
+ {
+ nq = dtnext(rp->sdict,mp);
+ _nv_unset(mp,NV_RDONLY);
+ nv_delete(mp,rp->sdict,0);
+ }
+ dtclose(rp->sdict);
+ }
+ stakdelete(slp->slptr);
+ free((void*)np->nvalue.ip);
+ np->nvalue.ip = 0;
+ }
+ goto done;
+ }
+ if(shp->subshell)
+ np = sh_assignok(np,0);
+ nv_offattr(np,NV_NODISC);
+ if(np->nvfun && !nv_isref(np))
+ {
+ /* This function contains disc */
+ if(!nv_local)
+ {
+ nv_local=1;
+ nv_putv(np,NIL(char*),flags,np->nvfun);
+ nv_local=0;
+ return;
+ }
+ /* called from disc, assign the actual value */
+ nv_local=0;
+ }
+ if(nv_isattr(np,NV_INT16P) == NV_INT16)
+ {
+ np->nvalue.cp = nv_isarray(np)?Empty:0;
+ goto done;
+ }
+#if SHOPT_FIXEDARRAY
+ else if(np->nvalue.up && nv_isarray(np) && (ap=nv_arrayptr(np)) && !ap->fixed)
+#else
+ else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np))
+#endif /* SHOPT_FIXEDARRAY */
+ up = np->nvalue.up;
+ else if(nv_isref(np) && !nv_isattr(np,NV_EXPORT|NV_MINIMAL) && np->nvalue.nrp)
+ {
+
+ if(np->nvalue.nrp->root)
+ dtdelete(Refdict,(void*)np->nvalue.nrp);
+ if(np->nvalue.nrp->sub)
+ free(np->nvalue.nrp->sub);
+ free((void*)np->nvalue.nrp);
+ np->nvalue.cp = 0;
+ up = 0;
+ }
+ else
+ up = &np->nvalue;
+ if(up && up->cp)
+ {
+ if(up->cp!=Empty && up->cp!=Null && !nv_isattr(np, NV_NOFREE))
+ free((void*)up->cp);
+ up->cp = 0;
+ }
+done:
+ if(!nv_isarray(np) || !nv_arrayptr(np))
+ {
+ nv_setsize(np,0);
+ if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT))
+ {
+ if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'['))
+ env_delete(shp->env,nv_name(np));
+ if(!(flags&NV_EXPORT) || nv_isattr(np,NV_IMPORT|NV_EXPORT)==(NV_IMPORT|NV_EXPORT))
+ np->nvenv = 0;
+ nv_setattr(np,0);
+ }
+ else
+ {
+ nv_setattr(np,NV_MINIMAL);
+ nv_delete(np,(Dt_t*)0,0);
+ }
+ }
+}
+
+/*
+ * return the node pointer in the highest level scope
+ */
+Namval_t *sh_scoped(Shell_t *shp, register Namval_t *np)
+{
+ if(!dtvnext(shp->var_tree))
+ return(np);
+ return(dtsearch(shp->var_tree,np));
+}
+
+#if 1
+/*
+ * return space separated list of names of variables in given tree
+ */
+static char *tableval(Dt_t *root)
+{
+ static Sfio_t *out;
+ register Namval_t *np;
+ register int first=1;
+ register Dt_t *base = dtview(root,0);
+ if(out)
+ sfseek(out,(Sfoff_t)0,SEEK_SET);
+ else
+ out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
+ for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
+ {
+ if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
+ {
+ if(!first)
+ sfputc(out,' ');
+ else
+ first = 0;
+ sfputr(out,np->nvname,-1);
+ }
+ }
+ sfputc(out,0);
+ if(base)
+ dtview(root,base);
+ return((char*)out->_data);
+}
+#endif
+
+#if SHOPT_OPTIMIZE
+struct optimize
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+ char **ptr;
+ struct optimize *next;
+ Namval_t *np;
+};
+
+static struct optimize *opt_free;
+
+static void optimize_clear(Namval_t* np, Namfun_t *fp)
+{
+ struct optimize *op = (struct optimize*)fp;
+ nv_stack(np,fp);
+ nv_stack(np,(Namfun_t*)0);
+ for(;op && op->np==np; op=op->next)
+ {
+ if(op->ptr)
+ {
+ *op->ptr = 0;
+ op->ptr = 0;
+ }
+ }
+}
+
+static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ nv_putv(np,val,flags,fp);
+ optimize_clear(np,fp);
+}
+
+static Namfun_t *clone_optimize(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ return((Namfun_t*)0);
+}
+
+static const Namdisc_t optimize_disc = {sizeof(struct optimize),put_optimize,0,0,0,0,clone_optimize};
+
+void nv_optimize(Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namfun_t *fp;
+ register struct optimize *op, *xp;
+ if(shp->argaddr)
+ {
+ if(np==SH_LINENO)
+ {
+ shp->argaddr = 0;
+ return;
+ }
+ for(fp=np->nvfun; fp; fp = fp->next)
+ {
+ if(fp->disc && (fp->disc->getnum || fp->disc->getval))
+ {
+ shp->argaddr = 0;
+ return;
+ }
+ if(fp->disc== &optimize_disc)
+ break;
+ }
+ if((xp= (struct optimize*)fp) && xp->ptr==shp->argaddr)
+ return;
+ if(op = opt_free)
+ opt_free = op->next;
+ else
+ op=(struct optimize*)calloc(1,sizeof(struct optimize));
+ op->ptr = shp->argaddr;
+ op->np = np;
+ if(xp)
+ {
+ op->hdr.disc = 0;
+ op->next = xp->next;
+ xp->next = op;
+ }
+ else
+ {
+ op->hdr.disc = &optimize_disc;
+ op->next = (struct optimize*)shp->optlist;
+ shp->optlist = (void*)op;
+ nv_stack(np,&op->hdr);
+ }
+ }
+}
+
+void sh_optclear(Shell_t *shp, void *old)
+{
+ register struct optimize *op,*opnext;
+ for(op=(struct optimize*)shp->optlist; op; op = opnext)
+ {
+ opnext = op->next;
+ if(op->ptr && op->hdr.disc)
+ {
+ nv_stack(op->np,&op->hdr);
+ nv_stack(op->np,(Namfun_t*)0);
+ }
+ op->next = opt_free;
+ opt_free = op;
+ }
+ shp->optlist = old;
+}
+
+#else
+# define optimize_clear(np,fp)
+#endif /* SHOPT_OPTIMIZE */
+
+/*
+ * Return a pointer to a character string that denotes the value
+ * of <np>. If <np> refers to an array, return a pointer to
+ * the value associated with the current index.
+ *
+ * If the value of <np> is an integer, the string returned will
+ * be overwritten by the next call to nv_getval.
+ *
+ * If <np> has no value, 0 is returned.
+ */
+
+char *nv_getval(register Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register union Value *up= &np->nvalue;
+ register int numeric;
+#if SHOPT_OPTIMIZE
+ if(!nv_local && shp->argaddr)
+ nv_optimize(np);
+#endif /* SHOPT_OPTIMIZE */
+ if((!np->nvfun || !np->nvfun->disc) && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF))
+ goto done;
+ if(nv_isref(np))
+ {
+ if(!np->nvalue.cp)
+ return(0);
+ shp->last_table = nv_reftable(np);
+ return(nv_name(nv_refnode(np)));
+ }
+ if(np->nvfun && np->nvfun->disc)
+ {
+ if(!nv_local)
+ {
+ nv_local=1;
+ return(nv_getv(np, np->nvfun));
+ }
+ nv_local=0;
+ }
+ numeric = ((nv_isattr (np, NV_INTEGER)) != 0);
+ if(numeric)
+ {
+ Sflong_t ll;
+ if(!up->cp)
+ return("0");
+ if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE)
+ {
+ Sfdouble_t ld;
+ double d;
+ char *format;
+ if(nv_isattr(np,NV_LONG))
+ {
+ ld = *up->ldp;
+ if(nv_isattr (np,NV_EXPNOTE))
+ format = "%.*Lg";
+ else if(nv_isattr (np,NV_HEXFLOAT))
+ format = "%.*La";
+ else
+ format = "%.*Lf";
+ sfprintf(shp->strbuf,format,nv_size(np),ld);
+ }
+ else
+ {
+ d = *up->dp;
+ if(nv_isattr (np,NV_EXPNOTE))
+ format = "%.*g";
+ else if(nv_isattr (np,NV_HEXFLOAT))
+ format = "%.*a";
+ else
+ format = "%.*f";
+ sfprintf(shp->strbuf,format,nv_size(np),d);
+ }
+ return(sfstruse(shp->strbuf));
+ }
+ else if(nv_isattr(np,NV_UNSIGN))
+ {
+ if(nv_isattr (np,NV_LONG))
+ ll = *(Sfulong_t*)up->llp;
+ else if(nv_isattr (np,NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ ll = *(uint16_t*)(up->sp);
+ else
+ ll = (uint16_t)up->s;
+ }
+ else
+ ll = *(uint32_t*)(up->lp);
+ }
+ else if(nv_isattr (np,NV_LONG))
+ ll = *up->llp;
+ else if(nv_isattr (np,NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ ll = *up->sp;
+ else
+ ll = up->s;
+ }
+ else
+ ll = *(up->lp);
+ if((numeric=nv_size(np))==10)
+ {
+ if(nv_isattr(np,NV_UNSIGN))
+ {
+ sfprintf(shp->strbuf,"%I*u",sizeof(ll),ll);
+ return(sfstruse(shp->strbuf));
+ }
+ numeric = 0;
+ }
+ return(fmtbase(ll,numeric, numeric&&numeric!=10));
+ }
+done:
+#if (_AST_VERSION>=20030127L)
+ /*
+ * if NV_RAW flag is on, return pointer to binary data
+ * otherwise, base64 encode the data and return this string
+ */
+ if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
+ {
+ char *cp;
+ char *ep;
+ int size= nv_size(np), insize=(4*size)/3+size/45+8;
+ base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)&ep);
+ *ep = 0;
+ return(cp);
+ }
+#endif
+ if(!nv_isattr(np,NV_LJUST|NV_RJUST) && (numeric=nv_size(np)) && up->cp && up->cp[numeric])
+ {
+ char *cp = getbuf(numeric+1);
+ memcpy(cp,up->cp,numeric);
+ cp[numeric]=0;
+ return(cp);
+ }
+ return ((char*)up->cp);
+}
+
+Sfdouble_t nv_getnum(register Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register union Value *up;
+ register Sfdouble_t r=0;
+ register char *str;
+#if SHOPT_OPTIMIZE
+ if(!nv_local && shp->argaddr)
+ nv_optimize(np);
+#endif /* SHOPT_OPTIMIZE */
+ if(nv_istable(np))
+ errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np));
+ if(np->nvfun && np->nvfun->disc)
+ {
+ if(!nv_local)
+ {
+ nv_local=1;
+ return(nv_getn(np, np->nvfun));
+ }
+ nv_local=0;
+ }
+ if(nv_isref(np))
+ {
+ str = nv_refsub(np);
+ np = nv_refnode(np);
+ if(str)
+ nv_putsub(np,str,0L);
+ }
+ if(nv_isattr (np, NV_INTEGER))
+ {
+ up= &np->nvalue;
+ if(!up->lp || up->cp==Empty)
+ r = 0;
+ else if(nv_isattr(np, NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(nv_isattr(np, NV_LONG))
+ r = *up->ldp;
+ else
+ r = *up->dp;
+ }
+ else if(nv_isattr(np, NV_UNSIGN))
+ {
+ if(nv_isattr(np, NV_LONG))
+ r = (Sflong_t)*((Sfulong_t*)up->llp);
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ r = (Sflong_t)(*(uint16_t*)up->sp);
+ else
+ r = (Sflong_t)((uint16_t)up->s);
+ }
+ else
+ r = *((uint32_t*)up->lp);
+ }
+ else
+ {
+ if(nv_isattr(np, NV_LONG))
+ r = *up->llp;
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ r = *up->sp;
+ else
+ r = up->s;
+ }
+ else
+ r = *up->lp;
+ }
+ }
+ else if((str=nv_getval(np)) && *str!=0)
+ {
+ if(nv_isattr(np,NV_LJUST|NV_RJUST) || (*str=='0' && !(str[1]=='x'||str[1]=='X')))
+ {
+ while(*str=='0')
+ str++;
+ }
+ r = sh_arith(shp,str);
+ }
+ return(r);
+}
+
+/*
+ * Give <np> the attributes <newatts,> and change its current
+ * value to conform to <newatts>. The <size> of left and right
+ * justified fields may be given.
+ */
+void nv_newattr (register Namval_t *np, unsigned newatts, int size)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *sp;
+ register char *cp = 0;
+ register unsigned int n;
+ Namval_t *mp = 0;
+ Namarr_t *ap = 0;
+ int oldsize,oldatts,trans;
+ Namfun_t *fp= (newatts&NV_NODISC)?np->nvfun:0;
+ char *prefix = shp->prefix,*sub;
+ newatts &= ~NV_NODISC;
+
+ /* check for restrictions */
+ if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD)))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
+ /* handle attributes that do not change data separately */
+ n = np->nvflag;
+ trans = !(n&NV_INTEGER) && (n&(NV_LTOU|NV_UTOL));
+ if(newatts&NV_EXPORT)
+ nv_offattr(np,NV_IMPORT);
+ if(((n^newatts)&NV_EXPORT))
+ {
+ /* record changes to the environment */
+ if(n&NV_EXPORT)
+ env_delete(shp->env,nv_name(np));
+ else
+ sh_envput(shp->env,np);
+ }
+ oldsize = nv_size(np);
+ if((size==oldsize|| (n&NV_INTEGER)) && !trans && ((n^newatts)&~NV_NOCHANGE)==0)
+ {
+ if(size)
+ nv_setsize(np,size);
+ nv_offattr(np, ~NV_NOFREE);
+ nv_onattr(np, newatts);
+ return;
+ }
+ /* for an array, change all the elements */
+ if((ap=nv_arrayptr(np)) && ap->nelem>0)
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ oldsize = nv_size(np);
+ oldatts = np->nvflag;
+ if(fp)
+ np->nvfun = 0;
+ if(ap) /* add element to prevent array deletion */
+ {
+ ap->nelem++;
+#if SHOPT_FIXEDARRAY
+ if(ap->fixed)
+ {
+ nv_setsize(np,size);
+ np->nvflag &= NV_ARRAY;
+ np->nvflag |= newatts;
+ goto skip;
+ }
+#endif /* SHOPT_TYPEDEF */
+ }
+ do
+ {
+ nv_setsize(np,oldsize);
+ np->nvflag = oldatts;
+ if (sp = nv_getval(np))
+ {
+ if(nv_isattr(np,NV_ZFILL))
+ while(*sp=='0') sp++;
+ cp = (char*)malloc((n=strlen (sp)) + 8);
+ strcpy(cp, sp);
+ if(sp && (mp=nv_opensub(np)))
+ {
+ sub = nv_getsub(mp);
+ if(trans)
+ {
+ nv_disc(np, &ap->hdr,NV_POP);
+ nv_clone(np,mp,0);
+ nv_disc(np, &ap->hdr,NV_FIRST);
+ nv_offattr(mp,NV_ARRAY);
+ }
+ nv_newattr(mp,newatts&~NV_ARRAY,size);
+ }
+ if(!mp)
+ {
+ if(ap)
+ ap->nelem &= ~ARRAY_SCAN;
+ if(!trans)
+ _nv_unset(np,NV_RDONLY|NV_EXPORT);
+ if(ap)
+ ap->nelem |= ARRAY_SCAN;
+ }
+ if(size==0 && (newatts&NV_HOST)!=NV_HOST && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL)))
+ size = n;
+ }
+ else if(!trans)
+ _nv_unset(np,NV_EXPORT);
+ nv_setsize(np,size);
+ np->nvflag &= (NV_ARRAY|NV_NOFREE);
+ np->nvflag |= newatts;
+ if (cp)
+ {
+ if(!mp)
+ nv_putval (np, cp, NV_RDONLY);
+ free(cp);
+ }
+ }
+ while(ap && nv_nextsub(np));
+#if SHOPT_FIXEDARRAY
+skip:
+#endif /* SHOPT_TYPEDEF */
+ if(fp)
+ np->nvfun = fp;
+ if(ap)
+ ap->nelem--;
+ shp->prefix = prefix;
+ return;
+}
+
+static char *oldgetenv(const char *string)
+{
+ register char c0,c1;
+ register const char *cp, *sp;
+ register char **av = environ;
+ if(!string || (c0= *string)==0)
+ return(0);
+ if((c1=*++string)==0)
+ c1= '=';
+ while(cp = *av++)
+ {
+ if(cp[0]!=c0 || cp[1]!=c1)
+ continue;
+ sp = string;
+ while(*sp && *sp++ == *++cp);
+ if(*sp==0 && *++cp=='=')
+ return((char*)(cp+1));
+ }
+ return(0);
+}
+
+/*
+ * This version of getenv uses the hash storage to access environment values
+ */
+char *sh_getenv(const char *name)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *np;
+ if(!shp->var_tree)
+ {
+#if 0
+ if(name[0] == 'P' && name[1] == 'A' && name[2] == 'T' && name[3] == 'H' && name[4] == 0 || name[0] == 'L' && ((name[1] == 'C' || name[1] == 'D') && name[2] == '_' || name[1] == 'A' && name[1] == 'N') || name[0] == 'V' && name[1] == 'P' && name[2] == 'A' && name[3] == 'T' && name[4] == 'H' && name[5] == 0 || name[0] == '_' && name[1] == 'R' && name[2] == 'L' && name[3] == 'D' || name[0] == '_' && name[1] == 'A' && name[2] == 'S' && name[3] == 'T' && name[4] == '_')
+#endif
+ return(oldgetenv(name));
+ }
+ else if((np = nv_search(name,shp->var_tree,0)) && nv_isattr(np,NV_EXPORT))
+ return(nv_getval(np));
+ return(0);
+}
+
+#ifndef _NEXT_SOURCE
+/*
+ * Some dynamic linkers will make this file see the libc getenv(),
+ * so sh_getenv() is used for the astintercept() callback. Plain
+ * getenv() is provided for static links.
+ */
+char *getenv(const char *name)
+{
+ return sh_getenv(name);
+}
+#endif /* _NEXT_SOURCE */
+
+#undef putenv
+/*
+ * This version of putenv uses the hash storage to assign environment values
+ */
+int putenv(const char *name)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *np;
+ if(name)
+ {
+ np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
+ if(!strchr(name,'='))
+ _nv_unset(np,0);
+ }
+ return(0);
+}
+
+/*
+ * Override libast setenviron().
+ */
+char* sh_setenviron(const char *name)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *np;
+ if(name)
+ {
+ np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
+ if(strchr(name,'='))
+ return(nv_getval(np));
+ _nv_unset(np,0);
+ }
+ return("");
+}
+
+/*
+ * Same linker dance as with getenv() above.
+ */
+char* setenviron(const char *name)
+{
+ return sh_setenviron(name);
+}
+
+/*
+ * normalize <cp> and return pointer to subscript if any
+ * if <eq> is specified, return pointer to first = not in a subscript
+ */
+static char *lastdot(char *cp, int eq)
+{
+ register char *ep=0;
+ register int c;
+ if(eq)
+ cp++;
+ while(c= mbchar(cp))
+ {
+ if(c=='[')
+ {
+ if(*cp==']')
+ cp++;
+ else
+ cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
+ }
+ else if(c=='.')
+ {
+ if(*cp=='[')
+ {
+ cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
+ if((ep=sh_checkid(ep+1,cp)) < cp)
+ cp=strcpy(ep,cp);
+ }
+ ep = 0;
+ }
+ else if(eq && c == '=')
+ return(cp-1);
+ }
+ return(eq?0:ep);
+}
+
+int nv_rename(register Namval_t *np, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *mp=0,*nr=0;
+ register char *cp;
+ int r=0,arraynp=0,arraynr,index= -1;
+ Namval_t *last_table = shp->last_table;
+ Dt_t *last_root = shp->last_root;
+ Dt_t *hp = 0;
+ char *nvenv=0,*prefix=shp->prefix;
+ Namarr_t *ap,*aq=0;
+ if(nv_isattr(np,NV_PARAM) && shp->st.prevst)
+ {
+ if(!(hp=(Dt_t*)shp->st.prevst->save_tree))
+ hp = dtvnext(shp->var_tree);
+ }
+ if(!nv_isattr(np,NV_MINIMAL))
+ nvenv = np->nvenv;
+ if(nvenv || (cp = nv_name(np)) && nv_isarray(np) && cp[strlen(cp)-1] == ']')
+ arraynp = 1;
+ if(!(cp=nv_getval(np)))
+ {
+ if(flags&NV_MOVE)
+ errormsg(SH_DICT,ERROR_exit(1),e_varname,"");
+ return(0);
+ }
+ if(lastdot(cp,0) && nv_isattr(np,NV_MINIMAL))
+ errormsg(SH_DICT,ERROR_exit(1),e_varname,nv_name(np));
+ arraynr = cp[strlen(cp)-1] == ']';
+ if(nv_isarray(np) && !(mp=nv_opensub(np)))
+ index=nv_aindex(np);
+ shp->prefix = 0;
+ if(!hp)
+ hp = shp->var_tree;
+ if(!(nr = nv_open(cp, hp, flags|NV_ARRAY|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ hp = nv_dict(shp->namespace);
+ else
+#endif /* SHOPT_NAMESPACE */
+ hp = shp->var_base;
+ }
+ else if(shp->last_root)
+ hp = shp->last_root;
+ if(!nr)
+ nr= nv_open(cp, hp, flags|NV_NOREF|((flags&NV_MOVE)?0:NV_NOFAIL));
+ shp->prefix = prefix;
+ if(!nr)
+ {
+ if(!nv_isvtree(np))
+ _nv_unset(np,0);
+ return(0);
+ }
+ if(!mp && index>=0 && nv_isvtree(nr))
+ {
+ sfprintf(shp->strbuf,"%s[%d]%c",nv_name(np),index,0);
+ /* create a virtual node */
+ if(mp = nv_open(sfstruse(shp->strbuf),shp->var_tree,NV_VARNAME|NV_ADD|NV_ARRAY))
+ {
+ if(ap = nv_arrayptr(np))
+ ap->nelem++;
+ mp->nvenv = nvenv = (void*)np;
+ }
+ }
+ if(mp)
+ {
+ nvenv = (char*)np;
+ np = mp;
+ }
+ if(nr==np)
+ {
+ if(index<0)
+ return(0);
+ if(cp = nv_getval(np))
+ cp = strdup(cp);
+ }
+ _nv_unset(np,NV_EXPORT);
+ if(nr==np)
+ {
+ nv_putsub(np,(char*)0, index);
+ nv_putval(np,cp,0);
+ free((void*)cp);
+ return(1);
+ }
+ shp->prev_table = shp->last_table;
+ shp->prev_root = shp->last_root;
+ shp->last_table = last_table;
+ shp->last_root = last_root;
+ if(flags&NV_MOVE)
+ {
+ if(arraynp && !nv_isattr(np,NV_MINIMAL) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)))
+ ap->nelem++;
+ }
+ if(((aq=nv_arrayptr(nr)) && !arraynr) || nv_isvtree(nr))
+ {
+ if(ap=nv_arrayptr(np))
+ {
+ if(!ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap->table)
+ mp = nv_search(nv_getsub(np),ap->table,NV_ADD);
+ nv_arraychild(np,mp,0);
+ nvenv = (void*)np;
+ }
+ else
+ mp = np;
+ nv_clone(nr,mp,(flags&NV_MOVE)|NV_COMVAR);
+ mp->nvenv = nvenv;
+ if(flags&NV_MOVE)
+ {
+ if(arraynr && !nv_isattr(nr,NV_MINIMAL) && (mp=(Namval_t*)nr->nvenv) && (ap=nv_arrayptr(mp)))
+ {
+ nv_putsub(mp,nr->nvname,0);
+ _nv_unset(mp,0);
+ }
+ nv_delete(nr,(Dt_t*)0,NV_NOFREE);
+ }
+ }
+ else
+ {
+ nv_putval(np,nv_getval(nr),0);
+ if(flags&NV_MOVE)
+ _nv_unset(nr,0);
+ }
+ return(1);
+}
+
+/*
+ * Create a reference node from <np> to $np in dictionary <hp>
+ */
+void nv_setref(register Namval_t *np, Dt_t *hp, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *nq=0, *nr=0;
+ register char *ep,*cp;
+ Dt_t *root = shp->last_root, *hpnext=0;
+ Namarr_t *ap=0;
+ int openmatch;
+ if(nv_isref(np))
+ return;
+ if(nv_isarray(np))
+ errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np));
+ if(!(cp=nv_getval(np)))
+ {
+ _nv_unset(np,0);
+ nv_onattr(np,NV_REF);
+ return;
+ }
+ if((ep = lastdot(cp,0)) && nv_isattr(np,NV_MINIMAL))
+ errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np));
+ if(hp)
+ hpnext = dtvnext(hp);
+ if((nr=nv_open(cp, hp?hp:shp->var_tree, flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ nq = nr;
+ else if(hpnext && dtvnext(hpnext)==shp->var_base && (nr=nv_open(cp,hpnext,flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ nq = nr;
+ else if((openmatch=shp->openmatch) && hpnext==shp->var_base && (nr=nv_open(cp,hpnext,flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ nq = nr;
+ if(nq)
+ hp = shp->last_root;
+ else
+ hp = hp?(openmatch?hp:shp->var_base):shp->var_tree;
+ if(nr==np)
+ {
+ if(shp->namespace && nv_dict(shp->namespace)==hp)
+ errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np));
+ /* bind to earlier scope, or add to global scope */
+ if(!(hp=dtvnext(hp)) || (nq=nv_search((char*)np,hp,NV_ADD|HASH_BUCKET))==np)
+ errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np));
+ if(nv_isarray(nq))
+ nv_putsub(nq,(char*)0,ARRAY_UNDEF);
+ }
+#if SHOPT_FIXEDARRAY
+ if(nq && ep && nv_isarray(nq) && !((ap=nv_arrayptr(nq)) && ap->fixed) && !nv_getsub(nq))
+#else
+ if(nq && ep && nv_isarray(nq) && !nv_getsub(nq))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(!nv_arrayptr(nq))
+ {
+ nv_putsub(nq,"1",ARRAY_FILL);
+ _nv_unset(nq,NV_RDONLY);
+ }
+ nv_endsubscript(nq,ep-1,NV_ARRAY);
+ }
+ if(!nr)
+ {
+ shp->last_root = 0;
+ nr= nq = nv_open(cp, hp, flags);
+ if(shp->last_root)
+ hp = shp->last_root;
+ }
+ if(shp->last_root == shp->var_tree && root!=shp->var_tree)
+ {
+ _nv_unset(np,NV_RDONLY);
+ nv_onattr(np,NV_REF);
+ errormsg(SH_DICT,ERROR_exit(1),e_globalref,nv_name(np));
+ }
+ shp->instance = 1;
+ if(nq && !ep && (ap=nv_arrayptr(nq)) && !(ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN)))
+ ep = nv_getsub(nq);
+#if SHOPT_FIXEDARRAY
+ if(ep && !(ap && ap->fixed))
+#else
+ if(ep)
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ /* cause subscript evaluation and return result */
+ if(nv_isarray(nq))
+ ep = nv_getsub(nq);
+ else
+ {
+ int n;
+ ep[n=strlen(ep)-1] = 0;
+ nv_putsub(nr, ep, ARRAY_FILL);
+ ep[n] = ']';
+ if(nq = nv_opensub(nr))
+ ep = 0;
+ else
+ ep = nv_getsub(nq=nr);
+ }
+ }
+ shp->instance = 0;
+ shp->last_root = root;
+ _nv_unset(np,0);
+ nv_delete(np,(Dt_t*)0,0);
+ np->nvalue.nrp = newof(0,struct Namref,1,sizeof(Dtlink_t));
+ np->nvalue.nrp->np = nq;
+ np->nvalue.nrp->root = hp;
+ if(ep)
+ {
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ np->nvalue.nrp->curi = ARRAY_FIXED|nv_arrfixed(nq,(Sfio_t*)0,1,&np->nvalue.nrp->dim);
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ np->nvalue.nrp->sub = strdup(ep);
+ }
+ np->nvalue.nrp->table = shp->last_table;
+ nv_onattr(np,NV_REF|NV_NOFREE);
+ if(!Refdict)
+ {
+ NullNode.nvname = ".deleted";
+ NullNode.nvflag = NV_RDONLY;
+ Refdict = dtopen(&_Refdisc,Dtobag);
+ }
+ dtinsert(Refdict,np->nvalue.nrp);
+}
+
+/*
+ * get the scope corresponding to <index>
+ * whence uses the same values as lseeek()
+ */
+Shscope_t *sh_getscope(int index, int whence)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct sh_scoped *sp, *topmost;
+ if(whence==SEEK_CUR)
+ sp = &shp->st;
+ else
+ {
+ if ((struct sh_scoped*)shp->topscope != shp->st.self)
+ topmost = (struct sh_scoped*)shp->topscope;
+ else
+ topmost = &(shp->st);
+ sp = topmost;
+ if(whence==SEEK_SET)
+ {
+ int n =0;
+ while(sp = sp->prevst)
+ n++;
+ index = n - index;
+ sp = topmost;
+ }
+ }
+ if(index < 0)
+ return((Shscope_t*)0);
+ while(index-- && (sp = sp->prevst));
+ return((Shscope_t*)sp);
+}
+
+/*
+ * make <scoped> the top scope and return previous scope
+ */
+Shscope_t *sh_setscope(Shscope_t *scope)
+{
+ Shell_t *shp = sh_getinterp();
+ Shscope_t *old = (Shscope_t*)shp->st.self;
+ *shp->st.self = shp->st;
+ shp->st = *((struct sh_scoped*)scope);
+ shp->var_tree = scope->var_tree;
+ SH_PATHNAMENOD->nvalue.cp = shp->st.filename;
+ SH_FUNNAMENOD->nvalue.cp = shp->st.funname;
+ return(old);
+}
+
+void sh_unscope(Shell_t *shp)
+{
+ register Dt_t *root = shp->var_tree;
+ register Dt_t *dp = dtview(root,(Dt_t*)0);
+ table_unset(shp,root,NV_RDONLY|NV_NOSCOPE,dp);
+ if(shp->st.real_fun && dp==shp->st.real_fun->sdict)
+ {
+ dp = dtview(dp,(Dt_t*)0);
+ shp->st.real_fun->sdict->view = dp;
+ }
+ shp->var_tree=dp;
+ dtclose(root);
+}
+
+/*
+ * The inverse of creating a reference node
+ */
+void nv_unref(register Namval_t *np)
+{
+ Namval_t *nq;
+ if(!nv_isref(np))
+ return;
+ nv_offattr(np,NV_NOFREE|NV_REF);
+ if(!np->nvalue.nrp)
+ return;
+ nq = nv_refnode(np);
+ if(Refdict)
+ {
+ if(np->nvalue.nrp->sub)
+ free(np->nvalue.nrp->sub);
+ dtdelete(Refdict,(void*)np->nvalue.nrp);
+ }
+ free((void*)np->nvalue.nrp);
+ np->nvalue.cp = strdup(nv_name(nq));
+#if SHOPT_OPTIMIZE
+ {
+ Namfun_t *fp;
+ for(fp=nq->nvfun; fp; fp = fp->next)
+ {
+ if(fp->disc== &optimize_disc)
+ {
+ optimize_clear(nq,fp);
+ return;
+ }
+ }
+ }
+#endif
+}
+
+/*
+ * These following are for binary compatibility with the old hash library
+ * They will be removed someday
+ */
+
+#if defined(__IMPORT__) && defined(__EXPORT__)
+# define extern __EXPORT__
+#endif
+
+#undef hashscope
+
+extern Dt_t *hashscope(Dt_t *root)
+{
+ return(dtvnext(root));
+}
+
+#undef hashfree
+
+extern Dt_t *hashfree(Dt_t *root)
+{
+ Dt_t *dp = dtvnext(root);
+ dtclose(root);
+ return(dp);
+}
+
+#undef hashname
+
+extern char *hashname(void *obj)
+{
+ Namval_t *np = (Namval_t*)obj;
+ return(np->nvname);
+}
+
+#undef hashlook
+
+extern void *hashlook(Dt_t *root, const char *name, int mode,int size)
+{
+ NOT_USED(size);
+ return((void*)nv_search(name,root,mode));
+}
+
+char *nv_name(register Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *table;
+ register Namfun_t *fp;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ char *cp;
+ if(is_abuiltin(np) || is_afunction(np))
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace && is_afunction(np))
+ {
+ char *name = nv_name(shp->namespace);
+ int n = strlen(name);
+ if(memcmp(np->nvname,name,n)==0 && np->nvname[n]=='.')
+ return(np->nvname+n+1);
+ }
+#endif /* SHOPT_NAMESPACE */
+ return(np->nvname);
+ }
+#if SHOPT_FIXEDARRAY
+ ap = nv_arrayptr(np);
+#endif /* SHOPT_FIXEDARRAY */
+ if(!nv_isattr(np,NV_MINIMAL|NV_EXPORT) && np->nvenv)
+ {
+ Namval_t *nq= shp->last_table, *mp= (Namval_t*)np->nvenv;
+ if(np==shp->last_table)
+ shp->last_table = 0;
+ if(nv_isarray(mp))
+ sfprintf(shp->strbuf,"%s[%s]",nv_name(mp),np->nvname);
+ else
+ sfprintf(shp->strbuf,"%s.%s",nv_name(mp),np->nvname);
+ shp->last_table = nq;
+ return(sfstruse(shp->strbuf));
+ }
+ if(nv_istable(np))
+#if 1
+ shp->last_table = nv_parent(np);
+#else
+ shp->last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0);
+#endif
+ else if(!nv_isref(np))
+ {
+ for(fp= np->nvfun ; fp; fp=fp->next)
+ if(fp->disc && fp->disc->namef)
+ {
+ if(np==shp->last_table)
+ shp->last_table = 0;
+ return((*fp->disc->namef)(np,fp));
+ }
+ }
+ if(!(table=shp->last_table) || *np->nvname=='.' || table==shp->namespace || np==table)
+ {
+#if SHOPT_FIXEDARRAY
+ if(!ap || !ap->fixed || (ap->nelem&ARRAY_UNDEF))
+ return(np->nvname);
+ table = 0;
+#else
+ return(np->nvname);
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ if(table)
+ {
+ cp = nv_name(table);
+ sfprintf(shp->strbuf,"%s.%s",cp,np->nvname);
+ }
+ else
+ sfprintf(shp->strbuf,"%s",np->nvname);
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ nv_arrfixed(np,shp->strbuf,1,(char*)0);
+#endif /* SHOPT_FIXEDARRAY */
+ return(sfstruse(shp->strbuf));
+}
+
+Namval_t *nv_lastdict(void)
+{
+ Shell_t *shp = sh_getinterp();
+ return(shp->last_table);
+}
+
+#undef nv_context
+/*
+ * returns the data context for a builtin
+ */
+void *nv_context(Namval_t *np)
+{
+ return((void*)np->nvfun);
+}
+
+#define DISABLE /* proto workaround */
+
+int nv_isnull DISABLE (register Namval_t *np)
+{
+ return(nv_isnull(np));
+}
+
+#undef nv_setsize
+int nv_setsize(register Namval_t *np, int size)
+{
+ int oldsize = nv_size(np);
+ if(size>=0)
+ np->nvsize = size;
+ return(oldsize);
+}
+
+Shell_t *nv_shell(Namval_t *np)
+{
+ Namfun_t *fp;
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(!fp->disc)
+ return((Shell_t*)fp->last);
+ }
+ return(0);
+}
+
+#undef nv_unset
+
+void nv_unset(register Namval_t *np)
+{
+ _nv_unset(np,0);
+ return;
+}
diff --git a/src/cmd/ksh93/sh/nvdisc.c b/src/cmd/ksh93/sh/nvdisc.c
new file mode 100644
index 0000000..45a7edb
--- /dev/null
+++ b/src/cmd/ksh93/sh/nvdisc.c
@@ -0,0 +1,1468 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "variables.h"
+#include "builtins.h"
+#include "path.h"
+
+static void assign(Namval_t*,const char*,int,Namfun_t*);
+
+int nv_compare(Dt_t* dict, Void_t *sp, Void_t *dp, Dtdisc_t *disc)
+{
+ if(sp==dp)
+ return(0);
+ return(strcmp((char*)sp,(char*)dp));
+}
+
+/*
+ * call the next getval function in the chain
+ */
+char *nv_getv(Namval_t *np, register Namfun_t *nfp)
+{
+ register Namfun_t *fp;
+ register char *cp;
+ if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
+ fp = nfp = nfp->next;
+ nv_local=0;
+ for(; fp; fp=fp->next)
+ {
+ if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
+ continue;
+ if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
+ break;
+ }
+ if(fp && fp->disc->getval)
+ cp = (*fp->disc->getval)(np,fp);
+ else if(fp && fp->disc->getnum)
+ {
+ sfprintf(sh.strbuf,"%.*Lg",12,(*fp->disc->getnum)(np,fp));
+ cp = sfstruse(sh.strbuf);
+ }
+ else
+ {
+ nv_local=1;
+ cp = nv_getval(np);
+ }
+ return(cp);
+}
+
+/*
+ * call the next getnum function in the chain
+ */
+Sfdouble_t nv_getn(Namval_t *np, register Namfun_t *nfp)
+{
+ register Namfun_t *fp;
+ register Sfdouble_t d=0;
+ Shell_t *shp = sh_getinterp();
+ char *str;
+ if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
+ fp = nfp = nfp->next;
+ nv_local=0;
+ for(; fp; fp=fp->next)
+ {
+ if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
+ continue;
+ if(!fp->disc->getnum && nv_isattr(np,NV_INTEGER))
+ continue;
+ if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
+ break;
+ }
+ if(fp && fp->disc && fp->disc->getnum)
+ d = (*fp->disc->getnum)(np,fp);
+ else if(nv_isattr(np,NV_INTEGER))
+ {
+ nv_local = 1;
+ d = nv_getnum(np);
+ }
+ else
+ {
+ if(fp && fp->disc && fp->disc->getval)
+ str = (*fp->disc->getval)(np,fp);
+ else
+ str = nv_getv(np,fp?fp:nfp);
+ if(str && *str)
+ {
+ if(nv_isattr(np,NV_LJUST|NV_RJUST) || (*str=='0' && !(str[1]=='x'||str[1]=='X')))
+ {
+ while(*str=='0')
+ str++;
+ }
+ d = sh_arith(shp,str);
+ }
+ }
+ return(d);
+}
+
+/*
+ * call the next assign function in the chain
+ */
+void nv_putv(Namval_t *np, const char *value, int flags, register Namfun_t *nfp)
+{
+ register Namfun_t *fp, *fpnext;
+ Namarr_t *ap;
+ if((fp=nfp) != NIL(Namfun_t*) && !nv_local)
+ fp = nfp = nfp->next;
+ nv_local=0;
+ if(flags&NV_NODISC)
+ fp = 0;
+ for(; fp; fp=fpnext)
+ {
+ fpnext = fp->next;
+ if(!fp->disc || !fp->disc->putval)
+ {
+ if(!value && (!(ap=nv_arrayptr(np)) || ap->nelem==0))
+ {
+ if(fp->disc || !(fp->nofree&1))
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ }
+ continue;
+ }
+ if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
+ break;
+ }
+ if(!value && (flags&NV_TYPE) && fp && fp->disc->putval==assign)
+ fp = 0;
+ if(fp && fp->disc->putval)
+ (*fp->disc->putval)(np,value, flags, fp);
+ else
+ {
+ nv_local=1;
+ if(value)
+ nv_putval(np, value, flags);
+ else
+ _nv_unset(np, flags&(NV_RDONLY|NV_EXPORT));
+ }
+}
+
+#define LOOKUPS 0
+#define ASSIGN 1
+#define APPEND 2
+#define UNASSIGN 3
+#define LOOKUPN 4
+#define BLOCKED ((Namval_t*)&nv_local)
+
+struct vardisc
+{
+ Namfun_t fun;
+ Namval_t *disc[5];
+};
+
+struct blocked
+{
+ struct blocked *next;
+ Namval_t *np;
+ int flags;
+ void *sub;
+ int isub;
+};
+
+static struct blocked *blist;
+
+#define isblocked(bp,type) ((bp)->flags & (1<<(type)))
+#define block(bp,type) ((bp)->flags |= (1<<(type)))
+#define unblock(bp,type) ((bp)->flags &= ~(1<<(type)))
+
+/*
+ * returns pointer to blocking structure
+ */
+static struct blocked *block_info(Namval_t *np, struct blocked *pp)
+{
+ register struct blocked *bp;
+ void *sub=0;
+ int isub=0;
+ if(nv_isarray(np) && (isub=nv_aindex(np)) < 0)
+ sub = nv_associative(np,(const char*)0,NV_ACURRENT);
+ for(bp=blist ; bp; bp=bp->next)
+ {
+ if(bp->np==np && bp->sub==sub && bp->isub==isub)
+ return(bp);
+ }
+ if(pp)
+ {
+ pp->np = np;
+ pp->flags = 0;
+ pp->isub = isub;
+ pp->sub = sub;
+ pp->next = blist;
+ blist = pp;
+ }
+ return(pp);
+}
+
+static void block_done(struct blocked *bp)
+{
+ blist = bp = bp->next;
+ if(bp && (bp->isub>=0 || bp->sub))
+ nv_putsub(bp->np, bp->sub,(bp->isub<0?0:bp->isub)|ARRAY_SETSUB);
+}
+
+/*
+ * free discipline if no more discipline functions
+ */
+static void chktfree(register Namval_t *np, register struct vardisc *vp)
+{
+ register int n;
+ for(n=0; n< sizeof(vp->disc)/sizeof(*vp->disc); n++)
+ {
+ if(vp->disc[n])
+ break;
+ }
+ if(n>=sizeof(vp->disc)/sizeof(*vp->disc))
+ {
+ /* no disc left so pop */
+ Namfun_t *fp;
+ if((fp=nv_stack(np, NIL(Namfun_t*))) && !(fp->nofree&1))
+ free((void*)fp);
+ }
+}
+
+/*
+ * This function performs an assignment disc on the given node <np>
+ */
+static void assign(Namval_t *np,const char* val,int flags,Namfun_t *handle)
+{
+ int type = (flags&NV_APPEND)?APPEND:ASSIGN;
+ register struct vardisc *vp = (struct vardisc*)handle;
+ register Namval_t *nq = vp->disc[type];
+ struct blocked block, *bp = block_info(np, &block);
+ Namval_t node;
+ union Value *up = np->nvalue.up;
+#if SHOPT_TYPEDEF
+ Namval_t *tp, *nr;
+ if(val && (tp=nv_type(np)) && (nr=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL)) && tp==nv_type(nr))
+ {
+ char *sub = nv_getsub(np);
+ _nv_unset(np,0);
+ if(sub)
+ {
+ nv_putsub(np, sub, ARRAY_ADD);
+ nv_putval(np,nv_getval(nr), 0);
+ }
+ else
+ nv_clone(nr,np,0);
+ goto done;
+ }
+#endif /* SHOPT_TYPEDEF */
+ if(val || isblocked(bp,type))
+ {
+ if(!nq || isblocked(bp,type))
+ {
+ nv_putv(np,val,flags,handle);
+ goto done;
+ }
+ node = *SH_VALNOD;
+ if(!nv_isnull(SH_VALNOD))
+ {
+ nv_onattr(SH_VALNOD,NV_NOFREE);
+ _nv_unset(SH_VALNOD,0);
+ }
+ if(flags&NV_INTEGER)
+ nv_onattr(SH_VALNOD,(flags&(NV_LONG|NV_DOUBLE|NV_EXPNOTE|NV_HEXFLOAT|NV_SHORT)));
+ nv_putval(SH_VALNOD, val, (flags&NV_INTEGER)?flags:NV_NOFREE);
+ }
+ else
+ nq = vp->disc[type=UNASSIGN];
+ if(nq && !isblocked(bp,type))
+ {
+ int bflag=0;
+ block(bp,type);
+ if (type==APPEND && (bflag= !isblocked(bp,LOOKUPS)))
+ block(bp,LOOKUPS);
+ sh_fun(nq,np,(char**)0);
+ unblock(bp,type);
+ if(bflag)
+ unblock(bp,LOOKUPS);
+ if(!vp->disc[type])
+ chktfree(np,vp);
+ }
+ if(nv_isarray(np))
+ np->nvalue.up = up;
+ if(val)
+ {
+ register char *cp;
+ Sfdouble_t d;
+ if(nv_isnull(SH_VALNOD))
+ cp=0;
+ else if(flags&NV_INTEGER)
+ {
+ d = nv_getnum(SH_VALNOD);
+ cp = (char*)(&d);
+ flags |= (NV_LONG|NV_DOUBLE);
+ flags &= ~NV_SHORT;
+ }
+ else
+ cp = nv_getval(SH_VALNOD);
+ if(cp)
+ nv_putv(np,cp,flags|NV_RDONLY,handle);
+ _nv_unset(SH_VALNOD,0);
+ /* restore everything but the nvlink field */
+ memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
+ }
+ else if(sh_isstate(SH_INIT) || np==SH_FUNNAMENOD)
+ {
+ /* don't free functions during reinitialization */
+ nv_putv(np,val,flags,handle);
+ }
+ else if(!nq || !isblocked(bp,type))
+ {
+ Dt_t *root = sh_subfuntree(1);
+ int n;
+ Namarr_t *ap;
+ block(bp,type);
+ nv_disc(np,handle,NV_POP);
+ nv_putv(np, val, flags, handle);
+ if(sh.subshell)
+ goto done;
+ if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0)
+ goto done;
+ for(n=0; n < sizeof(vp->disc)/sizeof(*vp->disc); n++)
+ {
+ if((nq=vp->disc[n]) && !nv_isattr(nq,NV_NOFREE))
+ {
+ _nv_unset(nq,0);
+ dtdelete(root,nq);
+ }
+ }
+ unblock(bp,type);
+ if(!(handle->nofree&1))
+ free(handle);
+ }
+done:
+ if(bp== &block)
+ block_done(bp);
+}
+
+/*
+ * This function executes a lookup disc and then performs
+ * the lookup on the given node <np>
+ */
+static char* lookup(Namval_t *np, int type, Sfdouble_t *dp,Namfun_t *handle)
+{
+ register struct vardisc *vp = (struct vardisc*)handle;
+ struct blocked block, *bp = block_info(np, &block);
+ register Namval_t *nq = vp->disc[type];
+ register char *cp=0;
+ Namval_t node;
+ union Value *up = np->nvalue.up;
+ if(nq && !isblocked(bp,type))
+ {
+ node = *SH_VALNOD;
+ if(!nv_isnull(SH_VALNOD))
+ {
+ nv_onattr(SH_VALNOD,NV_NOFREE);
+ _nv_unset(SH_VALNOD,0);
+ }
+ if(type==LOOKUPN)
+ {
+ nv_onattr(SH_VALNOD,NV_DOUBLE|NV_INTEGER);
+ nv_setsize(SH_VALNOD,10);
+ }
+ block(bp,type);
+ sh_fun(nq,np,(char**)0);
+ unblock(bp,type);
+ if(!vp->disc[type])
+ chktfree(np,vp);
+ if(type==LOOKUPN)
+ {
+ cp = (char*)(SH_VALNOD->nvalue.cp);
+ *dp = nv_getnum(SH_VALNOD);
+ }
+ else if(cp = nv_getval(SH_VALNOD))
+ cp = stkcopy(stkstd,cp);
+ _nv_unset(SH_VALNOD,NV_RDONLY);
+ if(!nv_isnull(&node))
+ {
+ /* restore everything but the nvlink field */
+ memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
+ }
+ }
+ if(nv_isarray(np))
+ np->nvalue.up = up;
+ if(!cp)
+ {
+ if(type==LOOKUPS)
+ cp = nv_getv(np,handle);
+ else
+ *dp = nv_getn(np,handle);
+ }
+ if(bp== &block)
+ block_done(bp);
+ return(cp);
+}
+
+static char* lookups(Namval_t *np, Namfun_t *handle)
+{
+ return(lookup(np,LOOKUPS,(Sfdouble_t*)0,handle));
+}
+
+static Sfdouble_t lookupn(Namval_t *np, Namfun_t *handle)
+{
+ Sfdouble_t d;
+ lookup(np,LOOKUPN, &d ,handle);
+ return(d);
+}
+
+
+/*
+ * Set disc on given <event> to <action>
+ * If action==np, the current disc is returned
+ * A null return value indicates that no <event> is known for <np>
+ * If <event> is NULL, then return the event name after <action>
+ * If <event> is NULL, and <action> is NULL, return the first event
+ */
+char *nv_setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
+{
+ register struct vardisc *vp = (struct vardisc*)np->nvfun;
+ register int type;
+ char *empty = "";
+ while(vp)
+ {
+ if(vp->fun.disc && (vp->fun.disc->setdisc || vp->fun.disc->putval == assign))
+ break;
+ vp = (struct vardisc*)vp->fun.next;
+ }
+ if(vp && !vp->fun.disc)
+ vp = 0;
+ if(np == (Namval_t*)fp)
+ {
+ register const char *name;
+ register int getname=0;
+ /* top level call, check for get/set */
+ if(!event)
+ {
+ if(!action)
+ return((char*)nv_discnames[0]);
+ getname=1;
+ event = (char*)action;
+ }
+ for(type=0; name=nv_discnames[type]; type++)
+ {
+ if(strcmp(event,name)==0)
+ break;
+ }
+ if(getname)
+ {
+ event = 0;
+ if(name && !(name = nv_discnames[++type]))
+ action = 0;
+ }
+ if(!name)
+ {
+ for(fp=(Namfun_t*)vp; fp; fp=fp->next)
+ {
+ if(fp->disc && fp->disc->setdisc)
+ return((*fp->disc->setdisc)(np,event,action,fp));
+ }
+ }
+ else if(getname)
+ return((char*)name);
+ }
+ if(!fp)
+ return(NIL(char*));
+ if(np != (Namval_t*)fp)
+ {
+ /* not the top level */
+ while(fp = fp->next)
+ {
+ if(fp->disc && fp->disc->setdisc)
+ return((*fp->disc->setdisc)(np,event,action,fp));
+ }
+ return(NIL(char*));
+ }
+ /* Handle GET/SET/APPEND/UNSET disc */
+ if(vp && vp->fun.disc->putval!=assign)
+ vp = 0;
+ if(!vp)
+ {
+ Namdisc_t *dp;
+ if(action==np)
+ return((char*)action);
+ if(!(vp = newof(NIL(struct vardisc*),struct vardisc,1,sizeof(Namdisc_t))))
+ return(0);
+ dp = (Namdisc_t*)(vp+1);
+ vp->fun.disc = dp;
+ memset(dp,0,sizeof(*dp));
+ dp->dsize = sizeof(struct vardisc);
+ dp->putval = assign;
+ if(nv_isarray(np) && !nv_arrayptr(np))
+ nv_putsub(np,(char*)0, 1);
+ nv_stack(np, (Namfun_t*)vp);
+ }
+ if(action==np)
+ {
+ action = vp->disc[type];
+ empty = 0;
+ }
+ else if(action)
+ {
+ Namdisc_t *dp = (Namdisc_t*)vp->fun.disc;
+ if(type==LOOKUPS)
+ dp->getval = lookups;
+ else if(type==LOOKUPN)
+ dp->getnum = lookupn;
+ vp->disc[type] = action;
+ }
+ else
+ {
+ struct blocked *bp;
+ action = vp->disc[type];
+ vp->disc[type] = 0;
+ if(!(bp=block_info(np,(struct blocked*)0)) || !isblocked(bp,UNASSIGN))
+ chktfree(np,vp);
+ }
+ return(action?(char*)action:empty);
+}
+
+/*
+ * Set disc on given <event> to <action>
+ * If action==np, the current disc is returned
+ * A null return value indicates that no <event> is known for <np>
+ * If <event> is NULL, then return the event name after <action>
+ * If <event> is NULL, and <action> is NULL, return the first event
+ */
+static char *setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
+{
+ register Nambfun_t *vp = (Nambfun_t*)fp;
+ register int type,getname=0;
+ register const char *name;
+ const char **discnames = vp->bnames;
+ /* top level call, check for discipline match */
+ if(!event)
+ {
+ if(!action)
+ return((char*)discnames[0]);
+ getname=1;
+ event = (char*)action;
+ }
+ for(type=0; name=discnames[type]; type++)
+ {
+ if(strcmp(event,name)==0)
+ break;
+ }
+ if(getname)
+ {
+ event = 0;
+ if(name && !(name = discnames[++type]))
+ action = 0;
+ }
+ if(!name)
+ return(nv_setdisc(np,event,action,fp));
+ else if(getname)
+ return((char*)name);
+ /* Handle the disciplines */
+ if(action==np)
+ action = vp->bltins[type];
+ else if(action)
+ {
+ Namval_t *tp = nv_type(np);
+ if(tp && (np = (Namval_t*)vp->bltins[type]) && nv_isattr(np,NV_STATICF))
+ errormsg(SH_DICT,ERROR_exit(1),e_staticfun,name,tp->nvname);
+ vp->bltins[type] = action;
+ }
+ else
+ {
+ action = vp->bltins[type];
+ vp->bltins[type] = 0;
+ }
+ return(action?(char*)action:"");
+}
+
+static void putdisc(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ nv_putv(np,val,flag,fp);
+ if(!val && !(flag&NV_NOFREE))
+ {
+ register Nambfun_t *vp = (Nambfun_t*)fp;
+ register int i;
+ for(i=0; vp->bnames[i]; i++)
+ {
+ register Namval_t *mp;
+ if((mp=vp->bltins[i]) && !nv_isattr(mp,NV_NOFREE))
+ {
+ if(is_abuiltin(mp))
+ {
+ if(mp->nvfun && !nv_isattr(mp,NV_NOFREE))
+ free((void*)mp->nvfun);
+ dtdelete(sh.bltin_tree,mp);
+ free((void*)mp);
+ }
+ }
+ }
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+
+ }
+}
+
+static const Namdisc_t Nv_bdisc = { 0, putdisc, 0, 0, setdisc };
+
+Namfun_t *nv_clone_disc(register Namfun_t *fp, int flags)
+{
+ register Namfun_t *nfp;
+ register int size;
+ if(!fp->disc && !fp->next && (fp->nofree&1))
+ return(fp);
+ if(!(size=fp->dsize) && (!fp->disc || !(size=fp->disc->dsize)))
+ size = sizeof(Namfun_t);
+ if(!(nfp=newof(NIL(Namfun_t*),Namfun_t,1,size-sizeof(Namfun_t))))
+ return(0);
+ memcpy(nfp,fp,size);
+ nfp->nofree &= ~1;
+ nfp->nofree |= (flags&NV_RDONLY)?1:0;
+ return(nfp);
+}
+
+int nv_adddisc(Namval_t *np, const char **names, Namval_t **funs)
+{
+ register Nambfun_t *vp;
+ register int n=0;
+ register const char **av=names;
+ if(av)
+ {
+ while(*av++)
+ n++;
+ }
+ if(!(vp = newof(NIL(Nambfun_t*),Nambfun_t,1,n*sizeof(Namval_t*))))
+ return(0);
+ vp->fun.dsize = sizeof(Nambfun_t)+n*sizeof(Namval_t*);
+ vp->fun.nofree |= 2;
+ vp->num = n;
+ if(funs)
+ memcpy((void*)vp->bltins, (void*)funs,n*sizeof(Namval_t*));
+ else while(n>=0)
+ vp->bltins[n--] = 0;
+ vp->fun.disc = &Nv_bdisc;
+ vp->bnames = names;
+ nv_stack(np,&vp->fun);
+ return(1);
+}
+
+/*
+ * push, pop, clne, or reorder disciplines onto node <np>
+ * mode can be one of
+ * NV_FIRST: Move or push <fp> to top of the stack or delete top
+ * NV_LAST: Move or push <fp> to bottom of stack or delete last
+ * NV_POP: Delete <fp> from top of the stack
+ * NV_CLONE: Replace fp with a copy created my malloc() and return it
+ */
+Namfun_t *nv_disc(register Namval_t *np, register Namfun_t* fp, int mode)
+{
+ Namfun_t *lp, **lpp;
+ if(nv_isref(np))
+ return(0);
+ if(mode==NV_CLONE && !fp)
+ return(0);
+ if(fp)
+ {
+ fp->subshell = sh.subshell;
+ if((lp=np->nvfun)==fp)
+ {
+ if(mode==NV_CLONE)
+ {
+ lp = nv_clone_disc(fp,0);
+ return(np->nvfun=lp);
+ }
+ if(mode==NV_FIRST || mode==0)
+ return(fp);
+ np->nvfun = lp->next;
+ if(mode==NV_POP)
+ return(fp);
+ if(mode==NV_LAST && (lp->next==0 || lp->next->disc==0))
+ return(fp);
+ }
+ /* see if <fp> is on the list already */
+ lpp = &np->nvfun;
+ if(lp)
+ {
+ while(lp->next && lp->next->disc)
+ {
+ if(lp->next==fp)
+ {
+ if(mode==NV_LAST && fp->next==0)
+ return(fp);
+ if(mode==NV_CLONE)
+ {
+ fp = nv_clone_disc(fp,0);
+ lp->next = fp;
+ return(fp);
+ }
+ lp->next = fp->next;
+ if(mode==NV_POP)
+ return(fp);
+ if(mode!=NV_LAST)
+ break;
+ }
+ lp = lp->next;
+ }
+ if(mode==NV_LAST && lp->disc)
+ lpp = &lp->next;
+ }
+ if(mode==NV_POP)
+ return(0);
+ /* push */
+ nv_offattr(np,NV_NODISC);
+ if(mode==NV_LAST)
+ {
+ if(lp && !lp->disc)
+ fp->next = lp;
+ else
+ fp->next = 0;
+ }
+ else
+ {
+ if((fp->nofree&1) && *lpp)
+ fp = nv_clone_disc(fp,0);
+ fp->next = *lpp;
+ }
+ *lpp = fp;
+ }
+ else
+ {
+ if(mode==NV_FIRST)
+ return(np->nvfun);
+ else if(mode==NV_LAST)
+ for(lp=np->nvfun; lp; fp=lp,lp=lp->next);
+ else if(fp = np->nvfun)
+ np->nvfun = fp->next;
+ }
+ return(fp);
+}
+
+/*
+ * returns discipline pointer if discipline with specified functions
+ * is on the discipline stack
+ */
+Namfun_t *nv_hasdisc(Namval_t *np, const Namdisc_t *dp)
+{
+ register Namfun_t *fp;
+ for(fp=np->nvfun; fp; fp = fp->next)
+ {
+ if(fp->disc== dp)
+ return(fp);
+ }
+ return(0);
+}
+
+struct notify
+{
+ Namfun_t hdr;
+ char **ptr;
+};
+
+static void put_notify(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct notify *pp = (struct notify*)fp;
+ nv_putv(np,val,flags,fp);
+ nv_stack(np,fp);
+ nv_stack(np,(Namfun_t*)0);
+ *pp->ptr = 0;
+ if(!(fp->nofree&1))
+ free((void*)fp);
+}
+
+static const Namdisc_t notify_disc = { 0, put_notify };
+
+int nv_unsetnotify(Namval_t *np, char **addr)
+{
+ register Namfun_t *fp;
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(fp->disc->putval==put_notify && ((struct notify*)fp)->ptr==addr)
+ {
+ nv_stack(np,fp);
+ nv_stack(np,(Namfun_t*)0);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+int nv_setnotify(Namval_t *np, char **addr)
+{
+ struct notify *pp = newof(0,struct notify, 1,0);
+ if(!pp)
+ return(0);
+ pp->ptr = addr;
+ pp->hdr.disc = &notify_disc;
+ nv_stack(np,&pp->hdr);
+ return(1);
+}
+
+static void *newnode(const char *name)
+{
+ register int s;
+ register Namval_t *np = newof(0,Namval_t,1,s=strlen(name)+1);
+ if(np)
+ {
+ np->nvname = (char*)np+sizeof(Namval_t);
+ memcpy(np->nvname,name,s);
+ }
+ return((void*)np);
+}
+
+/*
+ * clone a numeric value
+ */
+static void *num_clone(register Namval_t *np, void *val)
+{
+ register int size;
+ void *nval;
+ if(!val)
+ return(0);
+ if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(nv_isattr(np,NV_LONG))
+ size = sizeof(Sfdouble_t);
+ else if(nv_isattr(np,NV_SHORT))
+ size = sizeof(float);
+ else
+ size = sizeof(double);
+ }
+ else
+ {
+ if(nv_isattr(np,NV_LONG))
+ size = sizeof(Sflong_t);
+ else if(nv_isattr(np,NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ size = sizeof(short);
+ else
+ return((void*)np->nvalue.ip);
+ }
+ else
+ size = sizeof(int32_t);
+ }
+ if(!(nval = malloc(size)))
+ return(0);
+ memcpy(nval,val,size);
+ return(nval);
+}
+
+void clone_all_disc( Namval_t *np, Namval_t *mp, int flags)
+{
+ register Namfun_t *fp, **mfp = &mp->nvfun, *nfp, *fpnext;
+ for(fp=np->nvfun; fp;fp=fpnext)
+ {
+ fpnext = fp->next;
+ if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
+ return;
+ if((fp->nofree&2) && (flags&NV_NODISC))
+ nfp = 0;
+ if(fp->disc && fp->disc->clonef)
+ nfp = (*fp->disc->clonef)(np,mp,flags,fp);
+ else if(flags&NV_MOVE)
+ nfp = fp;
+ else
+ nfp = nv_clone_disc(fp,flags);
+ if(!nfp)
+ continue;
+ nfp->next = 0;
+ *mfp = nfp;
+ mfp = &nfp->next;
+ }
+}
+
+/*
+ * clone <mp> from <np> flags can be one of the following
+ * NV_APPEND - append <np> onto <mp>
+ * NV_MOVE - move <np> to <mp>
+ * NV_NOFREE - mark the new node as nofree
+ * NV_NODISC - discplines with funs non-zero will not be copied
+ * NV_COMVAR - cloning a compound variable
+ */
+int nv_clone(Namval_t *np, Namval_t *mp, int flags)
+{
+ Namfun_t *fp, *fpnext;
+ const char *val = mp->nvalue.cp;
+ unsigned short flag = mp->nvflag;
+ unsigned short size = mp->nvsize;
+ for(fp=mp->nvfun; fp; fp=fpnext)
+ {
+ fpnext = fp->next;
+ if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
+ break;
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ }
+ mp->nvfun = fp;
+ if(fp=np->nvfun)
+ {
+ if(nv_isattr(mp,NV_EXPORT|NV_MINIMAL) == (NV_EXPORT|NV_MINIMAL))
+ {
+ mp->nvenv = 0;
+ nv_offattr(mp,NV_MINIMAL);
+ }
+ if(!(flags&NV_COMVAR) && !nv_isattr(np,NV_MINIMAL) && np->nvenv && !(nv_isattr(mp,NV_MINIMAL)))
+ mp->nvenv = np->nvenv;
+ mp->nvflag &= NV_MINIMAL;
+ mp->nvflag |= np->nvflag&~(NV_ARRAY|NV_MINIMAL|NV_NOFREE);
+ flag = mp->nvflag;
+ clone_all_disc(np, mp, flags);
+ }
+ if(flags&NV_APPEND)
+ return(1);
+ if(mp->nvsize == size)
+ nv_setsize(mp,nv_size(np));
+ if(mp->nvflag == flag)
+ mp->nvflag = (np->nvflag&~(NV_MINIMAL))|(mp->nvflag&NV_MINIMAL);
+ if(nv_isattr(np,NV_EXPORT))
+ mp->nvflag |= (np->nvflag&NV_MINIMAL);
+ if(mp->nvalue.cp==val && !nv_isattr(np,NV_INTEGER))
+ {
+ if(np->nvalue.cp && np->nvalue.cp!=Empty && (flags&NV_COMVAR) && !(flags&NV_MOVE))
+ {
+ if(size)
+ mp->nvalue.cp = (char*)memdup(np->nvalue.cp,size);
+ else
+ mp->nvalue.cp = strdup(np->nvalue.cp);
+ nv_offattr(mp,NV_NOFREE);
+ }
+ else if((np->nvfun || !nv_isattr(np,NV_ARRAY)) && !(mp->nvalue.cp = np->nvalue.cp))
+ nv_offattr(mp,NV_NOFREE);
+ }
+ if(flags&NV_MOVE)
+ {
+ if(nv_isattr(np,NV_INTEGER))
+ mp->nvalue.ip = np->nvalue.ip;
+ np->nvfun = 0;
+ np->nvalue.cp = 0;
+ if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(mp,NV_EXPORT))
+ {
+ mp->nvenv = np->nvenv;
+ np->nvflag = 0;
+ }
+ else
+ np->nvflag &= NV_MINIMAL;
+ nv_setsize(np,0);
+ return(1);
+ }
+ else if((flags&NV_ARRAY) && !nv_isattr(np,NV_MINIMAL))
+ mp->nvenv = np->nvenv;
+ if(nv_isattr(np,NV_INTEGER) && mp->nvalue.ip!=np->nvalue.ip && np->nvalue.cp!=Empty)
+ {
+ mp->nvalue.ip = (int*)num_clone(np,(void*)np->nvalue.ip);
+ nv_offattr(mp,NV_NOFREE);
+ }
+ else if((flags&NV_NOFREE) && !nv_arrayptr(np))
+ nv_onattr(np,NV_NOFREE);
+ return(1);
+}
+
+/*
+ * The following discipline is for copy-on-write semantics
+ */
+static char* clone_getv(Namval_t *np, Namfun_t *handle)
+{
+ return(np->nvalue.np?nv_getval(np->nvalue.np):0);
+}
+
+static Sfdouble_t clone_getn(Namval_t *np, Namfun_t *handle)
+{
+ return(np->nvalue.np?nv_getnum(np->nvalue.np):0);
+}
+
+static void clone_putv(Namval_t *np,const char* val,int flags,Namfun_t *handle)
+{
+ Namfun_t *dp = nv_stack(np,(Namfun_t*)0);
+ Namval_t *mp = np->nvalue.np;
+ if(!sh.subshell)
+ free((void*)dp);
+ if(val)
+ nv_clone(mp,np,NV_NOFREE);
+ np->nvalue.cp = 0;
+ nv_putval(np,val,flags);
+}
+
+static const Namdisc_t clone_disc =
+{
+ 0,
+ clone_putv,
+ clone_getv,
+ clone_getn
+};
+
+Namval_t *nv_mkclone(Namval_t *mp)
+{
+ Namval_t *np;
+ Namfun_t *dp;
+ np = newof(0,Namval_t,1,0);
+ np->nvflag = mp->nvflag;
+ np->nvsize = mp->nvsize;
+ np->nvname = mp->nvname;
+ np->nvalue.np = mp;
+ np->nvflag = mp->nvflag;
+ dp = newof(0,Namfun_t,1,0);
+ dp->disc = &clone_disc;
+ nv_stack(np,dp);
+ dtinsert(nv_dict(sh.namespace),np);
+ return(np);
+}
+
+Namval_t *nv_search(const char *name, Dt_t *root, int mode)
+{
+ register Namval_t *np;
+ register Dt_t *dp = 0;
+ if(mode&HASH_NOSCOPE)
+ dp = dtview(root,0);
+ if(mode&HASH_BUCKET)
+ {
+ Namval_t *mp = (void*)name;
+ if(!(np = dtsearch(root,mp)) && (mode&NV_ADD))
+ name = nv_name(mp);
+ }
+ else
+ {
+ if(*name=='.' && root==sh.var_tree && !dp)
+ root = sh.var_base;
+ np = dtmatch(root,(void*)name);
+ }
+#if SHOPT_COSHELL
+ if(sh.inpool)
+ mode |= HASH_NOSCOPE;
+#endif /* SHOPT_COSHELL */
+ if(!np && (mode&NV_ADD))
+ {
+ if(sh.namespace && !(mode&HASH_NOSCOPE) && root==sh.var_tree)
+ root = nv_dict(sh.namespace);
+ else if(!dp && !(mode&HASH_NOSCOPE))
+ {
+ register Dt_t *next;
+ while(next=dtvnext(root))
+ root = next;
+ }
+ np = (Namval_t*)dtinsert(root,newnode(name));
+ }
+ if(dp)
+ dtview(root,dp);
+ return(np);
+}
+
+/*
+ * finds function or builtin for given name and the discipline variable
+ * if var!=0 the variable pointer is returned and the built-in name
+ * is put onto the stack at the current offset.
+ * otherwise, a pointer to the builtin (variable or type) is returned
+ * and var contains the poiner to the variable
+ * if last==0 and first component of name is a reference, nv_bfsearch()
+ will return 0.
+ */
+Namval_t *nv_bfsearch(const char *name, Dt_t *root, Namval_t **var, char **last)
+{
+ Shell_t *shp = sh_getinterp();
+ int c,offset = staktell();
+ register char *sp, *cp=0;
+ Namval_t *np, *nq;
+ char *dname=0;
+ if(var)
+ *var = 0;
+ /* check for . in the name before = */
+ for(sp=(char*)name+1; *sp; sp++)
+ {
+ if(*sp=='=')
+ return(0);
+ if(*sp=='[')
+ {
+ while(*sp=='[')
+ {
+ sp = nv_endsubscript((Namval_t*)0,(char*)sp,0);
+ if(sp[-1]!=']')
+ return(0);
+ }
+ if(*sp==0)
+ break;
+ if(*sp!='.')
+ return(0);
+ cp = sp;
+ }
+ else if(*sp=='.')
+ cp = sp;
+ }
+ if(!cp)
+ return(var?nv_search(name,root,0):0);
+ stakputs(name);
+ stakputc(0);
+ dname = cp+1;
+ cp = stakptr(offset) + (cp-name);
+ if(last)
+ *last = cp;
+ c = *cp;
+ *cp = 0;
+ nq=nv_open(stakptr(offset),0,NV_VARNAME|NV_NOASSIGN|NV_NOADD|NV_NOFAIL);
+ *cp = c;
+ if(!nq)
+ {
+ np = 0;
+ goto done;
+ }
+ if(!var)
+ {
+ np = nq;
+ goto done;
+ }
+ *var = nq;
+ if(c=='[')
+ nv_endsubscript(nq, cp,NV_NOADD);
+ stakseek(offset);
+#if SHOPT_NAMESPACE
+ if(nv_istable(nq))
+ {
+ Namval_t *nsp = shp->namespace;
+ if(last==0)
+ return(nv_search(name,root,0));
+ shp->namespace = 0;
+ stakputs(nv_name(nq));
+ shp->namespace = nsp;
+ stakputs(dname-1);
+ stakputc(0);
+ np = nv_search(stakptr(offset),root,0);
+ stakseek(offset);
+ return(np);
+ }
+#endif /* SHOPT_NAMESPACE */
+ while(nv_isarray(nq) && !nv_isattr(nq,NV_MINIMAL|NV_EXPORT) && nq->nvenv && nv_isarray((Namval_t*)nq->nvenv))
+ nq = (Namval_t*)nq->nvenv;
+ return((Namval_t*)nv_setdisc(nq,dname,nq,(Namfun_t*)nq));
+done:
+ stakseek(offset);
+ return(np);
+}
+
+/*
+ * add or replace built-in version of command corresponding to <path>
+ * The <bltin> argument is a pointer to the built-in
+ * if <extra>==1, the built-in will be deleted
+ * Special builtins cannot be added or deleted return failure
+ * The return value for adding builtins is a pointer to the node or NULL on
+ * failure. For delete NULL means success and the node that cannot be
+ * deleted is returned on failure.
+ */
+Namval_t *sh_addbuiltin(const char *path, Shbltin_f bltin, void *extra)
+{
+ register const char *name = path_basename(path);
+ char *cp;
+ register Namval_t *np, *nq=0;
+ int offset=staktell();
+ if(name==path && bltin!=(Shbltin_f)SYSTYPESET->nvalue.bfp && (nq=nv_bfsearch(name,sh.bltin_tree,(Namval_t**)0,&cp)))
+ path = name = stakptr(offset);
+ if(np = nv_search(path,sh.bltin_tree,0))
+ {
+ /* exists without a path */
+ if(extra == (void*)1)
+ {
+ if(np->nvfun && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvfun);
+ dtdelete(sh.bltin_tree,np);
+ return(0);
+ }
+ if(!bltin)
+ return(np);
+ }
+ else for(np=(Namval_t*)dtfirst(sh.bltin_tree);np;np=(Namval_t*)dtnext(sh.bltin_tree,np))
+ {
+ if(strcmp(name,path_basename(nv_name(np))))
+ continue;
+ /* exists probably with different path so delete it */
+ if(strcmp(path,nv_name(np)))
+ {
+ if(nv_isattr(np,BLT_SPC))
+ return(np);
+ if(!bltin)
+ bltin = (Shbltin_f)np->nvalue.bfp;
+ if(np->nvenv)
+ dtdelete(sh.bltin_tree,np);
+ if(extra == (void*)1)
+ return(0);
+ np = 0;
+ }
+ break;
+ }
+ if(!np && !(np = nv_search(path,sh.bltin_tree,bltin?NV_ADD:0)))
+ return(0);
+ if(nv_isattr(np,BLT_SPC))
+ {
+ if(extra)
+ np->nvfun = (Namfun_t*)extra;
+ return(np);
+ }
+ np->nvenv = 0;
+ np->nvfun = 0;
+ if(bltin)
+ {
+ np->nvalue.bfp = (Nambfp_f)bltin;
+ nv_onattr(np,NV_BLTIN|NV_NOFREE);
+ np->nvfun = (Namfun_t*)extra;
+ }
+ if(nq)
+ {
+ cp=nv_setdisc(nq,cp+1,np,(Namfun_t*)nq);
+ nv_close(nq);
+ if(!cp)
+ errormsg(SH_DICT,ERROR_exit(1),e_baddisc,name);
+ }
+ if(extra == (void*)1)
+ return(0);
+ return(np);
+}
+
+#undef nv_stack
+extern Namfun_t *nv_stack(register Namval_t *np, register Namfun_t* fp)
+{
+ return(nv_disc(np,fp,0));
+}
+
+struct table
+{
+ Namfun_t fun;
+ Namval_t *parent;
+ Shell_t *shp;
+ Dt_t *dict;
+};
+
+static Namval_t *next_table(register Namval_t* np, Dt_t *root,Namfun_t *fp)
+{
+ struct table *tp = (struct table *)fp;
+ if(root)
+ return((Namval_t*)dtnext(root,np));
+ else
+ return((Namval_t*)dtfirst(tp->dict));
+}
+
+static Namval_t *create_table(Namval_t *np,const char *name,int flags,Namfun_t *fp)
+{
+ struct table *tp = (struct table *)fp;
+ tp->shp->last_table = np;
+ return(nv_create(name, tp->dict, flags, fp));
+}
+
+static Namfun_t *clone_table(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ struct table *tp = (struct table*)fp;
+ struct table *ntp = (struct table*)nv_clone_disc(fp,0);
+ Dt_t *oroot=tp->dict,*nroot=dtopen(&_Nvdisc,Dtoset);
+ if(!nroot)
+ return(0);
+ memcpy((void*)ntp,(void*)fp,sizeof(struct table));
+ ntp->dict = nroot;
+ ntp->parent = nv_lastdict();
+ for(np=(Namval_t*)dtfirst(oroot);np;np=(Namval_t*)dtnext(oroot,np))
+ {
+ mp = (Namval_t*)dtinsert(nroot,newnode(np->nvname));
+ nv_clone(np,mp,flags);
+ }
+ return(&ntp->fun);
+}
+
+struct adata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ char *mapname;
+ char **argnam;
+ int attsize;
+ char *attval;
+};
+
+static void delete_fun(Namval_t *np, void *data)
+{
+ Shell_t *shp = ((struct adata*)data)->sh;
+ nv_delete(np,shp->fun_tree,NV_NOFREE);
+}
+
+static void put_table(register Namval_t* np, const char* val, int flags, Namfun_t* fp)
+{
+ register Dt_t *root = ((struct table*)fp)->dict;
+ register Namval_t *nq, *mp;
+ Namarr_t *ap;
+ struct adata data;
+ nv_putv(np,val,flags,fp);
+ if(val)
+ return;
+ if(nv_isarray(np) && (ap=nv_arrayptr(np)) && array_elem(ap))
+ return;
+ memset(&data,0,sizeof(data));
+ data.mapname = nv_name(np);
+ data.sh = ((struct table*)fp)->shp;
+ nv_scan(data.sh->fun_tree,delete_fun,(void*)&data,NV_FUNCTION,NV_FUNCTION|NV_NOSCOPE);
+ for(mp=(Namval_t*)dtfirst(root);mp;mp=nq)
+ {
+ _nv_unset(mp,flags);
+ nq = (Namval_t*)dtnext(root,mp);
+ dtdelete(root,mp);
+ free((void*)mp);
+ }
+ dtclose(root);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ np->nvfun = 0;
+}
+
+/*
+ * return space separated list of names of variables in given tree
+ */
+static char *get_table(Namval_t *np, Namfun_t *fp)
+{
+ register Dt_t *root = ((struct table*)fp)->dict;
+ static Sfio_t *out;
+ register int first=1;
+ register Dt_t *base = dtview(root,0);
+ if(out)
+ sfseek(out,(Sfoff_t)0,SEEK_SET);
+ else
+ out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
+ for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
+ {
+ if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
+ {
+ if(!first)
+ sfputc(out,' ');
+ else
+ first = 0;
+ sfputr(out,np->nvname,-1);
+ }
+ }
+ sfputc(out,0);
+ if(base)
+ dtview(root,base);
+ return((char*)out->_data);
+}
+
+static const Namdisc_t table_disc =
+{
+ sizeof(struct table),
+ put_table,
+ get_table,
+ 0,
+ 0,
+ create_table,
+ clone_table,
+ 0,
+ next_table,
+};
+
+Namval_t *nv_parent(Namval_t *np)
+{
+ struct table *tp = (struct table *)nv_hasdisc(np,&table_disc);
+ if(tp)
+ return(tp->parent);
+ return(0);
+}
+
+Dt_t *nv_dict(Namval_t* np)
+{
+ Shell_t *shp=sh_getinterp();
+ struct table *tp = (struct table*)nv_hasdisc(np,&table_disc);
+ if(tp)
+ return(tp->dict);
+ np = shp->last_table;
+ while(np)
+ {
+ if(tp = (struct table*)nv_hasdisc(np,&table_disc))
+ return(tp->dict);
+#if 0
+ np = nv_create(np,(const char*)0, NV_FIRST, (Namfun_t*)0);
+#else
+ break;
+#endif
+ }
+ return(shp->var_tree);
+}
+
+int nv_istable(Namval_t *np)
+{
+ return(nv_hasdisc(np,&table_disc)!=0);
+}
+
+/*
+ * create a mountable name-value pair tree
+ */
+Namval_t *nv_mount(Namval_t *np, const char *name, Dt_t *dict)
+{
+ Namval_t *mp, *pp;
+ struct table *tp;
+ if(nv_hasdisc(np,&table_disc))
+ pp = np;
+ else
+ pp = nv_lastdict();
+ if(!(tp = newof((struct table*)0, struct table,1,0)))
+ return(0);
+ if(name)
+ {
+ Namfun_t *fp = pp->nvfun;
+ mp = (*fp->disc->createf)(pp,name,0,fp);
+ }
+ else
+ mp = np;
+ nv_offattr(mp,NV_TABLE);
+ if(!nv_isnull(mp))
+ _nv_unset(mp,NV_RDONLY);
+ tp->shp = sh_getinterp();
+ tp->dict = dict;
+ tp->parent = pp;
+ tp->fun.disc = &table_disc;
+ nv_disc(mp, &tp->fun, NV_FIRST);
+ return(mp);
+}
+
+const Namdisc_t *nv_discfun(int which)
+{
+ switch(which)
+ {
+ case NV_DCADD:
+ return(&Nv_bdisc);
+ case NV_DCRESTRICT:
+ return(&RESTRICTED_disc);
+ }
+ return(0);
+}
+
+int nv_hasget(Namval_t *np)
+{
+ register Namfun_t *fp;
+ for(fp=np->nvfun; fp; fp=fp->next)
+ {
+ if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
+ continue;
+ return(1);
+ }
+ return(0);
+}
+
+#if SHOPT_NAMESPACE
+Namval_t *sh_fsearch(Shell_t *shp, const char *fname, int add)
+{
+ Stk_t *stkp = shp->stk;
+ int offset = stktell(stkp);
+ sfputr(stkp,nv_name(shp->namespace),'.');
+ sfputr(stkp,fname,0);
+ fname = stkptr(stkp,offset);
+ return(nv_search(fname,sh_subfuntree(add&NV_ADD),add));
+}
+#endif /* SHOPT_NAMESPACE */
diff --git a/src/cmd/ksh93/sh/nvtree.c b/src/cmd/ksh93/sh/nvtree.c
new file mode 100644
index 0000000..4cc3a52
--- /dev/null
+++ b/src/cmd/ksh93/sh/nvtree.c
@@ -0,0 +1,1161 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * code for tree nodes and name walking
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "name.h"
+#include "argnod.h"
+#include "lexstates.h"
+
+struct nvdir
+{
+ Dt_t *root;
+ Namval_t *hp;
+ Namval_t *table;
+ Namval_t *otable;
+ Namval_t *(*nextnode)(Namval_t*,Dt_t*,Namfun_t*);
+ Namfun_t *fun;
+ struct nvdir *prev;
+ int len;
+ char *data;
+};
+
+static int Indent;
+char *nv_getvtree(Namval_t*, Namfun_t *);
+static void put_tree(Namval_t*, const char*, int,Namfun_t*);
+static char *walk_tree(Namval_t*, Namval_t*, int);
+
+static int read_tree(Namval_t* np, Sfio_t *iop, int n, Namfun_t *dp)
+{
+ Sfio_t *sp;
+ char *cp;
+ int c;
+ if(n>=0)
+ return(-1);
+ while((c = sfgetc(iop)) && isblank(c));
+ sfungetc(iop,c);
+ sfprintf(sh.strbuf,"%s=%c",nv_name(np),0);
+ cp = sfstruse(sh.strbuf);
+ sp = sfopen((Sfio_t*)0,cp,"s");
+ sfstack(iop,sp);
+ c=sh_eval(iop,SH_READEVAL);
+ return(c);
+}
+
+static Namval_t *create_tree(Namval_t *np,const char *name,int flag,Namfun_t *dp)
+{
+ register Namfun_t *fp=dp;
+ fp->dsize = 0;
+ while(fp=fp->next)
+ {
+ if(fp->disc && fp->disc->createf)
+ {
+ if(np=(*fp->disc->createf)(np,name,flag,fp))
+ dp->last = fp->last;
+ return(np);
+ }
+ }
+ return((flag&NV_NOADD)?0:np);
+}
+
+static Namfun_t *clone_tree(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp){
+ Namfun_t *dp;
+ if ((flags&NV_MOVE) && nv_type(np))
+ return(fp);
+ dp = nv_clone_disc(fp,flags);
+ if((flags&NV_COMVAR) && !(flags&NV_RAW))
+ {
+ walk_tree(np,mp,flags);
+ if((flags&NV_MOVE) && !(fp->nofree&1))
+ free((void*)fp);
+ }
+ return(dp);
+}
+
+static const Namdisc_t treedisc =
+{
+ 0,
+ put_tree,
+ nv_getvtree,
+ 0,
+ 0,
+ create_tree,
+ clone_tree
+ ,0,0,0,
+ read_tree
+};
+
+static char *nextdot(const char *str)
+{
+ register char *cp;
+ register int c;
+ if(*str=='.')
+ str++;
+ for(cp=(char*)str;c= *cp; cp++)
+ {
+ if(c=='[')
+ {
+ cp = nv_endsubscript((Namval_t*)0,(char*)cp,0);
+ return(*cp=='.'?cp:0);
+ }
+ if(c=='.')
+ return(cp);
+ }
+ return(0);
+}
+
+static Namfun_t *nextdisc(Namval_t *np)
+{
+ register Namfun_t *fp;
+ if(nv_isref(np))
+ return(0);
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(fp && fp->disc && fp->disc->nextf)
+ return(fp);
+ }
+ return(0);
+}
+
+void *nv_diropen(Namval_t *np,const char *name)
+{
+ char *next,*last;
+ int c,len=strlen(name);
+ struct nvdir *save, *dp = new_of(struct nvdir,len+1);
+ Namval_t *nq=0,fake;
+ Namfun_t *nfp=0;
+ if(!dp)
+ return(0);
+ memset((void*)dp, 0, sizeof(*dp));
+ dp->data = (char*)(dp+1);
+ if(name[len-1]=='*' || name[len-1]=='@')
+ len -= 1;
+ name = memcpy(dp->data,name,len);
+ dp->data[len] = 0;
+ dp->len = len;
+ dp->root = sh.last_root?sh.last_root:sh.var_tree;
+#if 1
+ while(1)
+ {
+ dp->table = sh.last_table;
+ sh.last_table = 0;
+ if(*(last=(char*)name)==0)
+ break;
+ if(!(next=nextdot(last)))
+ break;
+ *next = 0;
+ np = nv_open(name, dp->root, NV_NOFAIL);
+ *next = '.';
+ if(!np || !nv_istable(np))
+ break;
+ dp->root = nv_dict(np);
+ name = next+1;
+ }
+#else
+ dp->table = sh.last_table;
+ sh.last_table = 0;
+ last = dp->data;
+#endif
+ if(*name)
+ {
+ fake.nvname = (char*)name;
+ if(dp->hp = (Namval_t*)dtprev(dp->root,&fake))
+ {
+ char *cp = nv_name(dp->hp);
+ c = strlen(cp);
+ if(memcmp(name,cp,c) || name[c]!='[')
+ dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
+ else
+ {
+ np = dp->hp;
+ last = 0;
+ }
+ }
+ else
+ dp->hp = (Namval_t*)dtfirst(dp->root);
+ }
+ else
+ dp->hp = (Namval_t*)dtfirst(dp->root);
+ while(1)
+ {
+ if(!last)
+ next = 0;
+ else if(next= nextdot(last))
+ {
+ c = *next;
+ *next = 0;
+ }
+ if(!np)
+ {
+ if(nfp && nfp->disc && nfp->disc->createf)
+ {
+ np = (*nfp->disc->createf)(nq,last,0,nfp);
+ if(*nfp->last == '[')
+ {
+ nv_endsubscript(np,nfp->last,NV_NOADD);
+ if(nq = nv_opensub(np))
+ np = nq;
+ }
+ }
+ else
+ np = nv_search(last,dp->root,0);
+ }
+ if(next)
+ *next = c;
+ if(np==dp->hp && !next)
+ dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
+ if(np && ((nfp=nextdisc(np)) || nv_istable(np)))
+ {
+ if(!(save = new_of(struct nvdir,0)))
+ return(0);
+ *save = *dp;
+ dp->prev = save;
+ if(nv_istable(np))
+ dp->root = nv_dict(np);
+ else
+ dp->root = (Dt_t*)np;
+ if(nfp)
+ {
+ dp->nextnode = nfp->disc->nextf;
+ dp->table = np;
+ dp->otable = sh.last_table;
+ dp->fun = nfp;
+ dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
+ }
+ else
+ dp->nextnode = 0;
+ }
+ else
+ break;
+ if(!next || next[1]==0)
+ break;
+ last = next+1;
+ nq = np;
+ np = 0;
+ }
+ return((void*)dp);
+}
+
+
+static Namval_t *nextnode(struct nvdir *dp)
+{
+ if(dp->nextnode)
+ return((*dp->nextnode)(dp->hp,dp->root,dp->fun));
+ if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len))
+ return(0);
+ return((Namval_t*)dtnext(dp->root,dp->hp));
+}
+
+char *nv_dirnext(void *dir)
+{
+ register struct nvdir *save, *dp = (struct nvdir*)dir;
+ register Namval_t *np, *last_table;
+ register char *cp;
+ Namfun_t *nfp;
+ Namval_t *nq;
+ while(1)
+ {
+ while(np=dp->hp)
+ {
+#if 0
+ char *sptr;
+#endif
+ if(nv_isarray(np))
+ nv_putsub(np,(char*)0, ARRAY_UNDEF);
+ dp->hp = nextnode(dp);
+ if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
+ continue;
+ last_table = sh.last_table;
+#if 0
+ if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
+ {
+ sptr = dp->table->nvenv;
+ dp->table->nvenv = (char*)dp->otable;
+ }
+#endif
+ sh.last_table = dp->table;
+ cp = nv_name(np);
+#if 0
+ if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
+ dp->table->nvenv = sptr;
+#endif
+ if(dp->nextnode && !dp->hp && (nq = (Namval_t*)dp->table))
+ {
+ Namarr_t *ap = nv_arrayptr(nq);
+ if(ap && (ap->nelem&ARRAY_SCAN) && nv_nextsub(nq))
+ dp->hp = (*dp->nextnode)(np,(Dt_t*)0,dp->fun);
+ }
+ sh.last_table = last_table;
+ if(!dp->len || memcmp(cp,dp->data,dp->len)==0)
+ {
+ if((nfp=nextdisc(np)) && (nfp->disc->getval||nfp->disc->getnum) && nv_isvtree(np) && strcmp(cp,dp->data))
+ nfp = 0;
+ if(nfp || nv_istable(np))
+ {
+ Dt_t *root;
+ int len;
+ if(nv_istable(np))
+ root = nv_dict(np);
+ else
+ root = (Dt_t*)np;
+ /* check for recursive walk */
+ for(save=dp; save; save=save->prev)
+ {
+ if(save->root==root)
+ break;
+ }
+ if(save)
+ return(cp);
+ len = strlen(cp);
+ if(!(save = new_of(struct nvdir,len+1)))
+ return(0);
+ *save = *dp;
+ dp->prev = save;
+ dp->root = root;
+ dp->len = len-1;
+ dp->data = (char*)(save+1);
+ memcpy(dp->data,cp,len+1);
+ if(nfp && np->nvfun)
+ {
+#if 0
+ Namarr_t *ap = nv_arrayptr(np);
+ if(ap && (ap->nelem&ARRAY_UNDEF))
+ nv_putsub(np,(char*)0,ARRAY_SCAN);
+#endif
+ dp->nextnode = nfp->disc->nextf;
+ dp->otable = dp->table;
+ dp->table = np;
+ dp->fun = nfp;
+ dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
+ }
+ else
+ dp->nextnode = 0;
+ }
+ return(cp);
+ }
+ }
+ if(!(save=dp->prev))
+ break;
+ *dp = *save;
+ free((void*)save);
+ }
+ return(0);
+}
+
+void nv_dirclose(void *dir)
+{
+ struct nvdir *dp = (struct nvdir*)dir;
+ if(dp->prev)
+ nv_dirclose((void*)dp->prev);
+ free(dir);
+}
+
+static void outtype(Namval_t *np, Namfun_t *fp, Sfio_t* out, const char *prefix)
+{
+ char *type=0;
+ Namval_t *tp = fp->type;
+ if(!tp && fp->disc && fp->disc->typef)
+ tp = (*fp->disc->typef)(np,fp);
+ for(fp=fp->next;fp;fp=fp->next)
+ {
+ if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp)))
+ {
+ outtype(np,fp,out,prefix);
+ break;
+ }
+ }
+ if(prefix && *prefix=='t')
+ type = "-T";
+ else if(!prefix)
+ type = "type";
+ if(type)
+ {
+ char *cp=tp->nvname;
+ if(cp=strrchr(cp,'.'))
+ cp++;
+ else
+ cp = tp->nvname;
+ sfprintf(out,"%s %s ",type,cp);
+ }
+}
+
+/*
+ * print the attributes of name value pair give by <np>
+ */
+void nv_attribute(register Namval_t *np,Sfio_t *out,char *prefix,int noname)
+{
+ register const Shtable_t *tp;
+ register char *cp;
+ register unsigned val,mask,attr;
+ char *ip=0;
+ Namfun_t *fp=0;
+ Namval_t *typep=0;
+#if SHOPT_FIXEDARRAY
+ int fixed=0;
+#endif /* SHOPT_FIXEDARRAY */
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if((typep=fp->type) || (fp->disc && fp->disc->typef && (typep=(*fp->disc->typef)(np,fp))))
+ break;
+ }
+ if(np==typep)
+ {
+
+ fp = 0;
+ typep = 0;
+ }
+ if(!fp && !nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)))
+ {
+ if(prefix && *prefix)
+ {
+ if(nv_isvtree(np))
+ sfprintf(out,"%s -C ",prefix);
+ else if((!np->nvalue.cp||np->nvalue.cp==Empty) && nv_isattr(np,~NV_NOFREE)==NV_MINIMAL && strcmp(np->nvname,"_"))
+ sfputr(out,prefix,' ');
+ }
+ return;
+ }
+
+ if ((attr=nv_isattr(np,~NV_NOFREE)) || fp)
+ {
+ if((attr&NV_NOPRINT|NV_INTEGER)==NV_NOPRINT)
+ attr &= ~NV_NOPRINT;
+ if(!attr && !fp)
+ return;
+ if(fp)
+ {
+ prefix = Empty;
+ attr &= NV_RDONLY|NV_ARRAY;
+ if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
+ attr |= (NV_REF|NV_TAGGED);
+ if(typep)
+ {
+ char *cp = typep->nvname;
+ if(cp = strrchr(cp,'.'))
+ cp++;
+ else
+ cp = typep->nvname;
+ sfputr(out,cp,' ');
+ fp = 0;
+ }
+ }
+ else if(prefix && *prefix)
+ sfputr(out,prefix,' ');
+ for(tp = shtab_attributes; *tp->sh_name;tp++)
+ {
+ val = tp->sh_number;
+ mask = val;
+ if(fp && (val&NV_INTEGER))
+ break;
+ /*
+ * the following test is needed to prevent variables
+ * with E attribute from being given the F
+ * attribute as well
+ */
+ if(val==NV_DOUBLE && (attr&(NV_EXPNOTE|NV_HEXFLOAT)))
+ continue;
+ if(val&NV_INTEGER)
+ mask |= NV_DOUBLE;
+ else if(val&NV_HOST)
+ mask = NV_HOST;
+ if((attr&mask)==val)
+ {
+ if(val==NV_ARRAY)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ char **xp=0;
+ if(ap && array_assoc(ap))
+ {
+ if(tp->sh_name[1]!='A')
+ continue;
+ }
+ else if(tp->sh_name[1]=='A')
+ continue;
+ if((ap && (ap->nelem&ARRAY_TREE)) || (!ap && nv_isattr(np,NV_NOFREE)))
+ {
+ if(prefix && *prefix)
+ sfwrite(out,"-C ",3);
+ }
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ fixed++;
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(ap && !array_assoc(ap) && (xp=(char**)(ap+1)) && *xp)
+ ip = nv_namptr(*xp,0)->nvname;
+ }
+ if(val==NV_UTOL || val==NV_LTOU)
+ {
+ if((cp = (char*)nv_mapchar(np,0)) && strcmp(cp,tp->sh_name+2))
+ {
+ sfprintf(out,"-M %s ",cp);
+ continue;
+ }
+ }
+ if(prefix)
+ {
+ if(*tp->sh_name=='-')
+ sfprintf(out,"%.2s ",tp->sh_name);
+ if(ip)
+ {
+ sfprintf(out,"[%s] ",ip);
+ ip = 0;
+ }
+ }
+ else
+ sfputr(out,tp->sh_name+2,' ');
+ if ((val&(NV_LJUST|NV_RJUST|NV_ZFILL)) && !(val&NV_INTEGER) && val!=NV_HOST)
+ sfprintf(out,"%d ",nv_size(np));
+ if(val==(NV_REF|NV_TAGGED))
+ attr &= ~(NV_REF|NV_TAGGED);
+ }
+ if(val==NV_INTEGER && nv_isattr(np,NV_INTEGER))
+ {
+ if(nv_size(np) != 10)
+ {
+ if(nv_isattr(np, NV_DOUBLE)== NV_DOUBLE)
+ cp = "precision";
+ else
+ cp = "base";
+ if(!prefix)
+ sfputr(out,cp,' ');
+ sfprintf(out,"%d ",nv_size(np));
+ }
+ break;
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ if(fixed)
+ {
+ sfprintf(out,"%s",nv_name(np));
+ nv_arrfixed(np,out,0,(char*)0);
+ sfputc(out,';');
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ if(fp)
+ outtype(np,fp,out,prefix);
+ if(noname)
+ return;
+ sfputr(out,nv_name(np),'\n');
+ }
+}
+
+struct Walk
+{
+ Shell_t *shp;
+ Sfio_t *out;
+ Dt_t *root;
+ int noscope;
+ int indent;
+ int nofollow;
+ int array;
+ int flags;
+};
+
+void nv_outnode(Namval_t *np, Sfio_t* out, int indent, int special)
+{
+ char *fmtq,*ep,*xp;
+ Namval_t *mp;
+ Namarr_t *ap = nv_arrayptr(np);
+ int scan,tabs=0,c,more,associative = 0;
+ int saveI = Indent;
+ Indent = indent;
+ if(ap)
+ {
+ if(!(ap->nelem&ARRAY_SCAN))
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ sfputc(out,'(');
+ if(indent>=0)
+ {
+ sfputc(out,'\n');
+ tabs=1;
+ }
+ if(!(associative =(array_assoc(ap)!=0)))
+ {
+ if(array_elem(ap) < nv_aimax(np)+1)
+ associative=1;
+ }
+ }
+ mp = nv_opensub(np);
+ while(1)
+ {
+ if(mp && special && nv_isvtree(mp) && !nv_isarray(mp))
+ {
+ if(!nv_nextsub(np))
+ break;
+ mp = nv_opensub(np);
+ continue;
+ }
+ if(tabs)
+ sfnputc(out,'\t',Indent = ++indent);
+ tabs=0;
+ if(associative||special)
+ {
+ if(!(fmtq = nv_getsub(np)))
+ break;
+ sfprintf(out,"[%s]",sh_fmtq(fmtq));
+ sfputc(out,'=');
+ }
+ if(ap && !array_assoc(ap))
+ scan = ap->nelem&ARRAY_SCAN;
+ if(mp && nv_isarray(mp))
+ {
+ nv_outnode(mp, out, indent,0);
+ if(indent>0)
+ sfnputc(out,'\t',indent);
+ sfputc(out,')');
+ sfputc(out,indent>=0?'\n':' ');
+ if(ap && !array_assoc(ap))
+ ap->nelem |= scan;
+ more = nv_nextsub(np);
+ goto skip;
+ }
+ if(mp && nv_isvtree(mp))
+ {
+ if(indent<0)
+ nv_onattr(mp,NV_EXPORT);
+ nv_onattr(mp,NV_TABLE);
+ }
+ ep = nv_getval(mp?mp:np);
+ if(ep==Empty && !(ap && ap->fixed))
+ ep = 0;
+ xp = 0;
+ if(!ap && nv_isattr(np,NV_INTEGER|NV_LJUST)==NV_LJUST)
+ {
+ xp = ep+nv_size(np);
+ while(--xp>ep && *xp==' ');
+ if(xp>ep || *xp!=' ')
+ xp++;
+ if(xp < (ep+nv_size(np)))
+ *xp = 0;
+ else
+ xp = 0;
+ }
+ if(mp && nv_isvtree(mp))
+ fmtq = ep;
+ else if(!(fmtq = sh_fmtq(ep)))
+ fmtq = "";
+ else if(!associative && (ep=strchr(fmtq,'=')))
+ {
+ char *qp = strchr(fmtq,'\'');
+ if(!qp || qp>ep)
+ {
+ sfwrite(out,fmtq,ep-fmtq);
+ sfputc(out,'\\');
+ fmtq = ep;
+ }
+ }
+ if(ap && !array_assoc(ap))
+ ap->nelem |= scan;
+ more = nv_nextsub(np);
+ c = '\n';
+ if(indent<0)
+ {
+ c = indent < -1?-1:';';
+ if(ap)
+ c = more?' ':-1;
+ }
+ sfputr(out,fmtq,c);
+ if(xp)
+ *xp = ' ';
+ skip:
+ if(!more)
+ break;
+ mp = nv_opensub(np);
+ if(indent>0 && !(mp && special && nv_isvtree(mp)))
+ sfnputc(out,'\t',indent);
+ }
+ Indent = saveI;
+}
+
+static void outval(char *name, const char *vname, struct Walk *wp)
+{
+ register Namval_t *np, *nq, *last_table=wp->shp->last_table;
+ register Namfun_t *fp;
+ int isarray=0, special=0,mode=0;
+ if(*name!='.' || vname[strlen(vname)-1]==']')
+ mode = NV_ARRAY;
+ if(!(np=nv_open(vname,wp->root,mode|NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope)))
+ {
+ wp->shp->last_table = last_table;
+ return;
+ }
+ if(!wp->out)
+ wp->shp->last_table = last_table;
+ fp = nv_hasdisc(np,&treedisc);
+ if(*name=='.')
+ {
+ if(nv_isattr(np,NV_BINARY))
+ return;
+ if(fp && np->nvalue.cp && np->nvalue.cp!=Empty)
+ {
+ nv_local = 1;
+ fp = 0;
+ }
+ if(fp)
+ return;
+ if(nv_isarray(np))
+ return;
+ }
+ if(!special && fp && !nv_isarray(np))
+ {
+ Namfun_t *xp;
+ if(!wp->out)
+ {
+ fp = nv_stack(np,fp);
+ if(fp = nv_stack(np,NIL(Namfun_t*)))
+ free((void*)fp);
+ np->nvfun = 0;
+ return;
+ }
+ for(xp=fp->next; xp; xp = xp->next)
+ {
+ if(xp->disc && (xp->disc->getval || xp->disc->getnum))
+ break;
+ }
+ if(!xp)
+ return;
+ }
+ if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
+ return;
+ if(special || (nv_isarray(np) && nv_arrayptr(np)))
+ {
+ isarray=1;
+ if(array_elem(nv_arrayptr(np))==0)
+ isarray=2;
+ else
+ nq = nv_putsub(np,NIL(char*),ARRAY_SCAN|(wp->out?ARRAY_NOCHILD:0));
+ }
+ if(!wp->out)
+ {
+ _nv_unset(np,NV_RDONLY);
+ if(sh.subshell || (wp->flags!=NV_RDONLY) || nv_isattr(np,NV_MINIMAL|NV_NOFREE))
+ wp->root = 0;
+ nv_delete(np,wp->root,NV_NOFREE);
+ return;
+ }
+ if(isarray==1 && !nq)
+ {
+ sfputc(wp->out,'(');
+ if(wp->indent>=0)
+ sfputc(wp->out,'\n');
+ return;
+ }
+ if(isarray==0 && nv_isarray(np) && (nv_isnull(np)||np->nvalue.cp==Empty)) /* empty array */
+ isarray = 2;
+ special |= wp->nofollow;
+ if(!wp->array && wp->indent>0)
+ sfnputc(wp->out,'\t',wp->indent);
+ if(!special)
+ {
+ if(*name!='.')
+ nv_attribute(np,wp->out,"typeset",'=');
+ nv_outname(wp->out,name,-1);
+ if((np->nvalue.cp && np->nvalue.cp!=Empty) || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)) || nv_isvtree(np))
+ sfputc(wp->out,(isarray==2?(wp->indent>=0?'\n':';'):'='));
+ if(isarray==2)
+ return;
+ }
+ fp = np->nvfun;
+ if(*name=='.' && !isarray)
+ np->nvfun = 0;
+ nv_outnode(np, wp->out, wp->indent, special);
+ if(*name=='.' && !isarray)
+ np->nvfun = fp;
+ if(isarray && !special)
+ {
+ if(wp->indent>0)
+ {
+ sfnputc(wp->out,'\t',wp->indent);
+ sfwrite(wp->out,")\n",2);
+ }
+ else
+ sfwrite(wp->out,");",2);
+ }
+}
+
+/*
+ * format initialization list given a list of assignments <argp>
+ */
+static char **genvalue(char **argv, const char *prefix, int n, struct Walk *wp)
+{
+ register char *cp,*nextcp,*arg;
+ register Sfio_t *outfile = wp->out;
+ register int m,r,l;
+ if(n==0)
+ m = strlen(prefix);
+ else if(cp=nextdot(prefix))
+ m = cp-prefix;
+ else
+ m = strlen(prefix)-1;
+ m++;
+ if(outfile && !wp->array)
+ {
+ sfputc(outfile,'(');
+ if(wp->indent>=0)
+ {
+ wp->indent++;
+ sfputc(outfile,'\n');
+ }
+ }
+ for(; arg= *argv; argv++)
+ {
+ cp = arg + n;
+ if(n==0 && cp[m-1]!='.')
+ continue;
+ if(n && cp[m-1]==0)
+ break;
+ if(n==0 || strncmp(arg,prefix-n,m+n)==0)
+ {
+ cp +=m;
+ r = 0;
+ if(*cp=='.')
+ cp++,r++;
+ if(wp->indent < 0 && argv[1]==0)
+ wp->indent--;
+ if(nextcp=nextdot(cp))
+ {
+ if(outfile)
+ {
+ Namval_t *np,*tp;
+ *nextcp = 0;
+ np=nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope);
+ if(!np || (nv_isarray(np) && (!(tp=nv_opensub(np)) || !nv_isvtree(tp))))
+ {
+ *nextcp = '.';
+ continue;
+ }
+ if(wp->indent>=0)
+ sfnputc(outfile,'\t',wp->indent);
+ if(*cp!='[' && (tp = nv_type(np)))
+ {
+ char *sp;
+ if(sp = strrchr(tp->nvname,'.'))
+ sp++;
+ else
+ sp = tp->nvname;
+ sfputr(outfile,sp,' ');
+ }
+ nv_outname(outfile,cp,nextcp-cp);
+ sfputc(outfile,'=');
+ *nextcp = '.';
+ }
+ else
+ {
+ outval(cp,arg,wp);
+ continue;
+ }
+ argv = genvalue(argv,cp,n+m+r,wp);
+ if(wp->indent>=0)
+ sfputc(outfile,'\n');
+ if(*argv)
+ continue;
+ break;
+ }
+ else if(outfile && !wp->nofollow && argv[1] && memcmp(arg,argv[1],l=strlen(arg))==0 && argv[1][l]=='[')
+ {
+ int k=1;
+ Namarr_t *ap=0;
+ Namval_t *np = nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope);
+ if(!np)
+ continue;
+ if((wp->array = nv_isarray(np)) && (ap=nv_arrayptr(np)))
+ k = array_elem(ap);
+
+ if(wp->indent>0)
+ sfnputc(outfile,'\t',wp->indent);
+ nv_attribute(np,outfile,"typeset",1);
+ nv_close(np);
+ sfputr(outfile,arg+m+r+(n?n:0),(k?'=':'\n'));
+ if(!k)
+ {
+ wp->array=0;
+ continue;
+ }
+ wp->nofollow=1;
+ argv = genvalue(argv,cp,cp-arg ,wp);
+ sfputc(outfile,wp->indent<0?';':'\n');
+ }
+ else if(outfile && *cp=='[' && cp[-1]!='.')
+ {
+ /* skip multi-dimensional arrays */
+ if(*nv_endsubscript((Namval_t*)0,cp,0)=='[')
+ continue;
+ if(wp->indent>0)
+ sfnputc(outfile,'\t',wp->indent);
+ if(cp[-1]=='.')
+ cp--;
+ sfputr(outfile,cp,'=');
+ if(*cp=='.')
+ cp++;
+ argv = genvalue(++argv,cp,cp-arg ,wp);
+ sfputc(outfile,wp->indent>0?'\n':';');
+ }
+ else
+ {
+ outval(cp,arg,wp);
+ if(wp->array)
+ {
+ if(wp->indent>=0)
+ wp->indent++;
+ else
+ sfputc(outfile,' ');
+ wp->array = 0;
+ }
+ }
+ }
+ else
+ break;
+ wp->nofollow = 0;
+ }
+ wp->array = 0;
+ if(outfile)
+ {
+ int c = prefix[m-1];
+ cp = (char*)prefix;
+ if(c=='.')
+ cp[m-1] = 0;
+ outval(".",prefix-n,wp);
+ if(c=='.')
+ cp[m-1] = c;
+ if(wp->indent>0)
+ sfnputc(outfile,'\t',--wp->indent);
+ sfputc(outfile,')');
+ }
+ return(--argv);
+}
+
+/*
+ * walk the virtual tree and print or delete name-value pairs
+ */
+static char *walk_tree(register Namval_t *np, Namval_t *xp, int flags)
+{
+ static Sfio_t *out;
+ struct Walk walk;
+ Sfio_t *outfile;
+ Sfoff_t off = 0;
+ int len, savtop = staktell();
+ char *savptr = stakfreeze(0);
+ register struct argnod *ap=0;
+ struct argnod *arglist=0;
+ char *name,*cp, **argv;
+ char *subscript=0;
+ void *dir;
+ int n=0, noscope=(flags&NV_NOSCOPE);
+ Namarr_t *arp = nv_arrayptr(np);
+ Dt_t *save_tree = sh.var_tree;
+ Namval_t *mp=0;
+ Shell_t *shp = sh_getinterp();
+ char *xpname = xp?stakcopy(nv_name(xp)):0;
+ walk.shp = shp;
+ if(xp)
+ {
+ shp->last_root = shp->prev_root;
+ shp->last_table = shp->prev_table;
+ }
+ if(shp->last_table)
+ shp->last_root = nv_dict(shp->last_table);
+ if(shp->last_root)
+ shp->var_tree = shp->last_root;
+ stakputs(nv_name(np));
+ if(arp && !(arp->nelem&ARRAY_SCAN) && (subscript = nv_getsub(np)))
+ {
+ mp = nv_opensub(np);
+ stakputc('[');
+ stakputs(subscript);
+ stakputc(']');
+ stakputc('.');
+ }
+ else if(*stakptr(staktell()-1) == ']')
+ mp = np;
+ name = stakfreeze(1);
+ len = strlen(name);
+ shp->last_root = 0;
+ dir = nv_diropen(mp,name);
+ walk.root = shp->last_root?shp->last_root:shp->var_tree;
+ if(subscript)
+ name[strlen(name)-1] = 0;
+ while(cp = nv_dirnext(dir))
+ {
+ if(cp[len]!='.')
+ continue;
+ if(xp)
+ {
+ Dt_t *dp = shp->var_tree;
+ Namval_t *nq, *mq;
+ if(strlen(cp)<=len)
+ continue;
+ nq = nv_open(cp,walk.root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL);
+ if(!nq && (flags&NV_MOVE))
+ nq = nv_search(cp,walk.root,NV_NOADD);
+ stakseek(0);
+ stakputs(xpname);
+ stakputs(cp+len);
+ stakputc(0);
+ shp->var_tree = save_tree;
+ mq = nv_open(stakptr(0),shp->prev_root,NV_VARNAME|NV_NOASSIGN|NV_NOFAIL);
+ shp->var_tree = dp;
+ if(nq && mq)
+ {
+ nv_clone(nq,mq,flags|NV_RAW);
+ if(flags&NV_MOVE)
+ nv_delete(nq,walk.root,0);
+ }
+ continue;
+ }
+ stakseek(ARGVAL);
+ stakputs(cp);
+ ap = (struct argnod*)stakfreeze(1);
+ ap->argflag = ARG_RAW;
+ ap->argchn.ap = arglist;
+ n++;
+ arglist = ap;
+ }
+ nv_dirclose(dir);
+ if(xp)
+ {
+ shp->var_tree = save_tree;
+ return((char*)0);
+ }
+ argv = (char**)stakalloc((n+1)*sizeof(char*));
+ argv += n;
+ *argv = 0;
+ for(; ap; ap=ap->argchn.ap)
+ *--argv = ap->argval;
+ if(flags&1)
+ outfile = 0;
+ else if(!(outfile=out))
+ outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
+ else if(flags&NV_TABLE)
+ off = sftell(outfile);
+ else
+ sfseek(outfile,0L,SEEK_SET);
+ walk.out = outfile;
+ walk.indent = (flags&NV_EXPORT)?-1:Indent;
+ walk.nofollow = 0;
+ walk.noscope = noscope;
+ walk.array = 0;
+ walk.flags = flags;
+ genvalue(argv,name,0,&walk);
+ stakset(savptr,savtop);
+ shp->var_tree = save_tree;
+ if(!outfile)
+ return((char*)0);
+ sfputc(out,0);
+ sfseek(out,off,SEEK_SET);
+ return((char*)out->_data+off);
+}
+
+Namfun_t *nv_isvtree(Namval_t *np)
+{
+ if(np)
+ return(nv_hasdisc(np,&treedisc));
+ return(0);
+}
+
+/*
+ * get discipline for compound initializations
+ */
+char *nv_getvtree(register Namval_t *np, Namfun_t *fp)
+{
+ int flags=0, dsize=fp?fp->dsize:0;
+ for(; fp && fp->next; fp=fp->next)
+ {
+ if(fp->next->disc && (fp->next->disc->getnum || fp->next->disc->getval))
+ return(nv_getv(np,fp));
+ }
+ if(nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
+ return(nv_getv(np,fp));
+ if(nv_isattr(np,NV_ARRAY) && !nv_type(np) && nv_arraychild(np,(Namval_t*)0,0)==np)
+ return(nv_getv(np,fp));
+ if(flags = nv_isattr(np,NV_EXPORT))
+ nv_offattr(np,NV_EXPORT);
+ if(flags |= nv_isattr(np,NV_TABLE))
+ nv_offattr(np,NV_TABLE);
+ if(dsize && (flags&NV_EXPORT))
+ return("()");
+ return(walk_tree(np,(Namval_t*)0,flags));
+}
+
+/*
+ * put discipline for compound initializations
+ */
+static void put_tree(register Namval_t *np, const char *val, int flags,Namfun_t *fp)
+{
+ struct Namarray *ap;
+ int nleft = 0;
+ if(!val && !fp->next && nv_isattr(np,NV_NOFREE))
+ return;
+ if(!nv_isattr(np,(NV_INTEGER|NV_BINARY)))
+ {
+ Shell_t *shp = sh_getinterp();
+ Namval_t *last_table = shp->last_table;
+ Dt_t *last_root = shp->last_root;
+ Namval_t *mp = val?nv_open(val,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_ARRAY|NV_NOFAIL):0;
+ if(mp && nv_isvtree(mp))
+ {
+ shp->prev_table = shp->last_table;
+ shp->prev_root = shp->last_root;
+ shp->last_table = last_table;
+ shp->last_root = last_root;
+ if(!(flags&NV_APPEND))
+ walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
+ nv_clone(mp,np,NV_COMVAR);
+ return;
+ }
+ walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
+ }
+ nv_putv(np, val, flags,fp);
+ if(val && nv_isattr(np,(NV_INTEGER|NV_BINARY)))
+ return;
+ if(ap= nv_arrayptr(np))
+ nleft = array_elem(ap);
+ if(nleft==0)
+ {
+ fp = nv_stack(np,fp);
+ if(fp = nv_stack(np,NIL(Namfun_t*)))
+ free((void*)fp);
+ }
+}
+
+/*
+ * Insert discipline to cause $x to print current tree
+ */
+void nv_setvtree(register Namval_t *np)
+{
+ register Namfun_t *nfp;
+ if(sh.subshell)
+ sh_assignok(np,1);
+ if(nv_hasdisc(np, &treedisc))
+ return;
+ nfp = newof(NIL(void*),Namfun_t,1,0);
+ nfp->disc = &treedisc;
+ nfp->dsize = sizeof(Namfun_t);
+ nv_stack(np, nfp);
+}
+
diff --git a/src/cmd/ksh93/sh/nvtype.c b/src/cmd/ksh93/sh/nvtype.c
new file mode 100644
index 0000000..3b7f34e
--- /dev/null
+++ b/src/cmd/ksh93/sh/nvtype.c
@@ -0,0 +1,1709 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ */
+#include "defs.h"
+#include "io.h"
+#include "variables.h"
+
+static const char sh_opttype[] =
+"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-07-01 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - set the type of variables to \b\f?\f\b]"
+"[+DESCRIPTION?\b\f?\f\b sets the type on each of the variables specified "
+ "by \aname\a to \b\f?\f\b. If \b=\b\avalue\a is specified, "
+ "the variable \aname\a is set to \avalue\a before the variable "
+ "is converted to \b\f?\f\b.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "variables of this type are written to standard output.]"
+"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[r?Enables readonly. Once enabled, the value cannot be changed or unset.]"
+"[a]:?[type?Indexed array. Each \aname\a will converted to an index "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become index \b0\b. If \b[\b\atype\a\b]]\b is "
+ "specified, each subscript is interpreted as a value of enumeration "
+ "type \atype\a.]"
+"[A?Associative array. Each \aname\a will converted to an associate "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become subscript \b0\b.]"
+"[h]:[string?Used within a type definition to provide a help string "
+ "for variable \aname\a. Otherwise, it is ignored.]"
+"[S?Used with a type definition to indicate that the variable is shared by "
+ "each instance of the type. When used inside a function defined "
+ "with the \bfunction\b reserved word, the specified variables "
+ "will have function static scope. Otherwise, the variable is "
+ "unset prior to processing the assignment list.]"
+"[+DETAILS]\ftypes\f"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\fother\f \breadonly\b(1), \btypeset\b(1)]"
+;
+
+typedef struct Namtype Namtype_t;
+typedef struct Namchld
+{
+ Namfun_t fun;
+ Namtype_t *ptype;
+ Namtype_t *ttype;
+} Namchld_t;
+
+struct Namtype
+{
+ Namfun_t fun;
+ Shell_t *sh;
+ Namval_t *np;
+ Namval_t *parent;
+ Namval_t *bp;
+ Namval_t *cp;
+#if SHOPT_NAMESPACE
+ Namval_t *nsp;
+#endif /* SHOPT_NAMESPACE */
+ char *nodes;
+ char *data;
+ Namchld_t childfun;
+ int numnodes;
+ char **names;
+ size_t dsize;
+ short strsize;
+ unsigned short ndisc;
+ unsigned short current;
+ unsigned short nref;
+};
+
+#if 0
+struct type
+{
+ Namtype_t hdr;
+ unsigned short ndisc;
+ unsigned short current;
+ unsigned short nref;
+};
+#endif
+
+typedef struct
+{
+ char _cSfdouble_t;
+ Sfdouble_t _dSfdouble_t;
+ char _cdouble;
+ double _ddouble;
+ char _cfloat;
+ float _dfloat;
+ char _cSflong_t;
+ Sflong_t _dSflong_t;
+ char _clong;
+ long _dlong;
+ char _cshort;
+ short _dshort;
+ char _cpointer;
+ char *_dpointer;
+} _Align_;
+
+#define alignof(t) ((char*)&((_Align_*)0)->_d##t-(char*)&((_Align_*)0)->_c##t)
+
+static void put_type(Namval_t*, const char*, int, Namfun_t*);
+static Namval_t* create_type(Namval_t*, const char*, int, Namfun_t*);
+static Namfun_t* clone_type(Namval_t*, Namval_t*, int, Namfun_t*);
+static Namval_t* next_type(Namval_t*, Dt_t*, Namfun_t*);
+
+static const Namdisc_t type_disc =
+{
+ sizeof(Namtype_t),
+ put_type,
+ 0,
+ 0,
+ 0,
+ create_type,
+ clone_type,
+ 0,
+ next_type,
+ 0,
+#if 0
+ read_type
+#endif
+};
+
+size_t nv_datasize(Namval_t *np, size_t *offset)
+{
+ size_t s=0, a=0;
+ if(nv_isattr(np,NV_INTEGER))
+ {
+ if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(nv_isattr(np, NV_LONG))
+ {
+ a = alignof(Sfdouble_t);
+ s = sizeof(Sfdouble_t);
+ }
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ a = alignof(float);
+ s = sizeof(float);
+ }
+ else
+ {
+ a = alignof(double);
+ s = sizeof(double);
+ }
+ }
+ else
+ {
+ if(nv_isattr(np, NV_LONG))
+ {
+ a = alignof(Sflong_t);
+ s = sizeof(Sflong_t);
+ }
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ a = alignof(short);
+ s = sizeof(short);
+ }
+ else
+ {
+ a = alignof(long);
+ s = sizeof(long);
+ }
+ }
+ }
+ else if(nv_isattr(np, NV_BINARY) || nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL))
+ s = nv_size(np);
+ else
+ {
+ a = alignof(pointer);
+ s = nv_size(np);
+ }
+ if(a>1 && offset)
+ *offset = a*((*offset +a-1)/a);
+ return(s);
+}
+
+static char *name_chtype(Namval_t *np, Namfun_t *fp)
+{
+ Namchld_t *pp = (Namchld_t*)fp;
+ char *cp, *sub;
+ Namval_t *tp = sh.last_table;
+ Namval_t *nq = pp->ptype->np;
+ Namarr_t *ap;
+ if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
+ sh.last_table = 0;
+ cp = nv_name(nq);
+ if((ap = nv_arrayptr(nq)) && !(ap->nelem&ARRAY_UNDEF) && (sub= nv_getsub(nq)))
+ sfprintf(sh.strbuf,"%s[%s].%s",cp,sub,np->nvname);
+ else
+ sfprintf(sh.strbuf,"%s.%s",cp,np->nvname);
+#if SHOPT_FIXEDARRAY
+ if((ap=nv_arrayptr(np)) && ap->fixed)
+ nv_arrfixed(np,sh.strbuf,1,(char*)0);
+#endif /* SHOPT_FIXEDARRAY */
+ sh.last_table = tp;
+ return(sfstruse(sh.strbuf));
+}
+
+static void put_chtype(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ if(!val && nv_isattr(np,NV_REF))
+ return;
+ nv_putv(np,val,flag,fp);
+ if(!val)
+ {
+ Namchld_t *pp = (Namchld_t*)fp;
+ size_t dsize=0,offset = (char*)np-(char*)pp->ptype;
+ Namval_t *mp = (Namval_t*)((char*)pp->ttype+offset);
+ dsize = nv_datasize(mp,&dsize);
+ if(mp->nvalue.cp >= pp->ttype->data && mp->nvalue.cp < (char*)pp+pp->ttype->fun.dsize)
+ {
+ np->nvalue.cp = pp->ptype->data + (mp->nvalue.cp-pp->ptype->data);
+ if(np->nvalue.cp!=mp->nvalue.cp)
+ memcpy((char*)np->nvalue.cp,mp->nvalue.cp,dsize);
+ }
+ else if(!nv_isarray(mp) && mp->nvalue.cp)
+ {
+ np->nvalue.cp = mp->nvalue.cp;
+ nv_onattr(np,NV_NOFREE);
+ }
+ np->nvsize = mp->nvsize;
+ np->nvflag = mp->nvflag&~NV_RDONLY;
+ }
+}
+
+static Namfun_t *clone_chtype(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ if(flags&NV_NODISC)
+ return(0);
+ return(nv_clone_disc(fp,flags));
+}
+
+static const Namdisc_t chtype_disc =
+{
+ sizeof(Namchld_t),
+ put_chtype,
+ 0,
+ 0,
+ 0,
+ 0,
+ clone_chtype,
+ name_chtype
+};
+
+static Namval_t *findref(void *nodes, int n)
+{
+ Namval_t *tp,*np = nv_namptr(nodes,n);
+ char *name = np->nvname;
+ int i=n, len= strrchr(name,'.')-name;
+ Namtype_t *pp;
+ while(--i>0)
+ {
+ np = nv_namptr(nodes,i);
+ if(np->nvname[len]==0)
+ {
+ tp = nv_type(np);
+ pp = (Namtype_t*)nv_hasdisc(tp,&type_disc);
+ return(nv_namptr(pp->nodes,n-i-1));
+ }
+ }
+ return(0);
+}
+
+static int fixnode(Namtype_t *dp, Namtype_t *pp, int i, struct Namref *nrp,int flag)
+{
+ Namval_t *nq = nv_namptr(dp->nodes,i);
+ Namfun_t *fp;
+ if(fp=nv_hasdisc(nq,&chtype_disc))
+ nv_disc(nq, fp, NV_POP);
+ if(nv_isattr(nq,NV_REF))
+ {
+ nq->nvalue.nrp = nrp++;
+ nv_setsize(nq,0);
+ if(strchr(nq->nvname,'.'))
+ nq->nvalue.nrp->np = findref(dp->nodes,i);
+ else
+ nq->nvalue.nrp->np = nv_namptr(pp->childfun.ttype->nodes,i);
+ nq->nvalue.nrp->root = sh.last_root;
+ nq->nvalue.nrp->table = pp->np;
+ nq ->nvflag = NV_REF|NV_NOFREE|NV_MINIMAL;
+ return(1);
+ }
+ if(nq->nvalue.cp || nq->nvfun)
+ {
+ const char *data = nq->nvalue.cp;
+ if(nq->nvfun)
+ {
+ Namval_t *np = nv_namptr(pp->nodes,i);
+ if(nv_isarray(nq))
+ nq->nvalue.cp = 0;
+ nq->nvfun = 0;
+ if(nv_isarray(nq) && ((flag&NV_IARRAY) || nv_type(np)))
+ clone_all_disc(np,nq,flag&~NV_TYPE);
+ else
+ clone_all_disc(np,nq,flag);
+ if(fp)
+ nv_disc(np, fp, NV_LAST);
+ }
+#if 0
+ if(nq->nvalue.cp >= pp->data && nq->nvalue.cp < (char*)pp +pp->fun.dsize)
+ nq->nvalue.cp = dp->data + (nq->nvalue.cp-pp->data);
+#else
+ if(data >= pp->data && data < (char*)pp +pp->fun.dsize)
+ nq->nvalue.cp = dp->data + (data-pp->data);
+#endif
+ else if(!nq->nvfun && pp->childfun.ttype!=pp->childfun.ptype)
+ {
+ Namval_t *nr = nv_namptr( pp->childfun.ttype->nodes,i);
+ if(nr->nvalue.cp!=nq->nvalue.cp)
+ {
+ if(i=nv_size(nq))
+ {
+ const char *cp = nq->nvalue.cp;
+ nq->nvalue.cp = (char*)malloc(i);
+ memcpy((char*)nq->nvalue.cp,cp,i);
+ }
+ else
+ nq->nvalue.cp = strdup(nq->nvalue.cp);
+ nv_offattr(nq,NV_NOFREE);
+ }
+ }
+ else if(nq->nvalue.cp==Empty)
+ nv_offattr(nq,NV_NOFREE);
+
+ }
+ if(fp)
+ nv_disc(nq, &dp->childfun.fun, NV_LAST);
+ return(0);
+}
+
+static Namfun_t *clone_type(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namtype_t *dp, *pp=(Namtype_t*)fp;
+ register int i;
+ register Namval_t *nq, *nr;
+ size_t size = fp->dsize;
+ int save, offset=staktell();
+ char *cp;
+ Dt_t *root = sh.last_root;
+ Namval_t *last_table = sh.last_table;
+ struct Namref *nrp = 0;
+ Namarr_t *ap;
+ if(flags&NV_MOVE)
+ {
+ pp->np = mp;
+ pp->childfun.ptype = pp;
+ return(fp);
+ }
+ if(flags&NV_TYPE)
+ return(nv_clone_disc(fp,flags));
+ if(size==0 && (!fp->disc || (size=fp->disc->dsize)==0))
+ size = sizeof(Namfun_t);
+ dp = (Namtype_t*)malloc(size+pp->nref*sizeof(struct Namref));
+ if(pp->nref)
+ {
+ nrp = (struct Namref*)((char*)dp + size);
+ memset((void*)nrp,0,pp->nref*sizeof(struct Namref));
+ }
+ memcpy((void*)dp,(void*)pp,size);
+#if 0
+ dp->parent = nv_lastdict();
+#else
+ dp->parent = mp;
+#endif
+ dp->fun.nofree = (flags&NV_RDONLY?1:0);
+ dp->np = mp;
+ dp->childfun.ptype = dp;
+#if 0
+ dp->childfun.ttype = (Namtype_t*)nv_hasdisc(dp->fun.type,&type_disc);
+#endif
+ dp->nodes = (char*)(dp+1);
+ dp->data = (char*)dp + (pp->data - (char*)pp);
+ for(i=dp->numnodes; --i >= 0; )
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if(fixnode(dp,pp,i,nrp,NV_TYPE|(flags&NV_IARRAY)))
+ {
+ nrp++;
+ nq = nq->nvalue.nrp->np;
+ }
+ if(flags==(NV_NOFREE|NV_ARRAY))
+ continue;
+ if(nq->nvalue.cp || !nv_isvtree(nq) || nv_isattr(nq,NV_RDONLY))
+ {
+ /* see if default value has been overwritten */
+ if(!mp->nvname)
+ continue;
+ sh.last_table = last_table;
+ if(pp->strsize<0)
+ cp = nv_name(np);
+ else
+ cp = nv_name(mp);
+ stakputs(cp);
+ stakputc('.');
+ stakputs(nq->nvname);
+ stakputc(0);
+ root = nv_dict(mp);
+ save = fp->nofree;
+ fp->nofree = 1;
+ nr = nv_create(stakptr(offset),root,NV_VARNAME|NV_NOADD,fp);
+ fp->nofree = save;
+ stakseek(offset);
+ if(nr)
+ {
+ if(nv_isattr(nq,NV_RDONLY) && (nq->nvalue.cp || nv_isattr(nq,NV_INTEGER)))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nq->nvname);
+ if(nv_isref(nq))
+ nq = nv_refnode(nq);
+ if((size = nv_datasize(nr,(size_t*)0)) && size==nv_datasize(nq,(size_t*)0))
+ memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,size);
+ else if(ap=nv_arrayptr(nr))
+ {
+ nv_putsub(nr,NIL(char*),ARRAY_SCAN|ARRAY_NOSCOPE);
+ do
+ {
+ if(array_assoc(ap))
+ cp = (char*)((*ap->fun)(nr,NIL(char*),NV_ANAME));
+ else
+ cp = nv_getsub(nr);
+ nv_putsub(nq,cp,ARRAY_ADD|ARRAY_NOSCOPE);
+ if(array_assoc(ap))
+ {
+ Namval_t *mp = (Namval_t*)((*ap->fun)(nr,NIL(char*),NV_ACURRENT));
+ Namval_t *mq = (Namval_t*)((*ap->fun)(nq,NIL(char*),NV_ACURRENT));
+ nv_clone(mp,mq,NV_MOVE);
+ ap->nelem--;
+ nv_delete(mp,ap->table,0);
+ }
+ else
+ {
+ cp = nv_getval(nr);
+ nv_putval(nq,cp,0);
+ }
+ }
+ while(nv_nextsub(nr));
+ }
+ else
+ nv_putval(nq,nv_getval(nr),NV_RDONLY);
+#if SHOPT_TYPEDEF
+ if(sh.mktype)
+ nv_addnode(nr,1);
+#endif /* SHOPT_TYPEDEF */
+ if(pp->strsize<0)
+ continue;
+ _nv_unset(nr,0);
+ if(!nv_isattr(nr,NV_MINIMAL))
+ nv_delete(nr,sh.last_root,0);
+ }
+ else if(nv_isattr(nq,NV_RDONLY) && !nq->nvalue.cp && !nv_isattr(nq,NV_INTEGER))
+ errormsg(SH_DICT,ERROR_exit(1),e_required,nq->nvname,nv_name(mp));
+ }
+ }
+ if(nv_isattr(mp,NV_BINARY))
+ mp->nvalue.cp = dp->data;
+ if(pp->strsize<0)
+ dp->strsize = -pp->strsize;
+ return(&dp->fun);
+}
+
+
+/*
+ * return Namval_t* corresponding to child <name> in <np>
+ */
+static Namval_t *create_type(Namval_t *np,const char *name,int flag,Namfun_t *fp)
+{
+ Namtype_t *dp = (Namtype_t*)fp;
+ register const char *cp=name;
+ register int i=0,n;
+ Namval_t *nq=0;
+ if(!name)
+ return(dp->parent);
+ while((n=*cp++) && n != '=' && n != '+' && n!='[');
+ n = (cp-1) -name;
+ if(dp->numnodes && dp->strsize<0)
+ {
+ char *base = (char*)np-sizeof(Dtlink_t);
+ int m=strlen(np->nvname);
+ while((nq=nv_namptr(base,++i)) && memcmp(nq->nvname,np->nvname,m)==0)
+ {
+ if(nq->nvname[m]=='.' && memcmp(name,&nq->nvname[m+1],n)==0 && nq->nvname[m+n+1]==0)
+ goto found;
+ }
+ nq = 0;
+ }
+ else for(i=0; i < dp->numnodes; i++)
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
+ {
+ while(nv_isref(nq))
+ nq = nq->nvalue.nrp->np;
+ goto found;
+ }
+ }
+ nq = 0;
+found:
+ if(nq)
+ {
+ fp->last = (char*)&name[n];
+ sh.last_table = dp->parent;
+ }
+ else
+ {
+ if(name[n]!='=') for(i=0; i < dp->ndisc; i++)
+ {
+ if((memcmp(name,dp->names[i],n)==0) && dp->names[i][n]==0)
+ return(nq);
+ }
+ errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
+ }
+ return(nq);
+}
+
+static void put_type(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ Namval_t *nq;
+ if(val && (nq=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL)))
+ {
+ Namfun_t *pp;
+ if((pp=nv_hasdisc(nq,fp->disc)) && pp->type==fp->type)
+
+ {
+ if(!nq->nvenv)
+ flag |= NV_EXPORT;
+ _nv_unset(np, flag);
+ nv_clone(nq,np,NV_IARRAY);
+ return;
+ }
+ }
+ nv_putv(np,val,flag,fp);
+ if(!val)
+ {
+ Namtype_t *dp = (Namtype_t*)fp;
+ Namval_t *nq;
+ Namarr_t *ap;
+ int i;
+ if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0)
+ return;
+ for(i=0; i < dp->numnodes; i++)
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if(ap=nv_arrayptr(nq))
+ ap->nelem |= ARRAY_UNDEF;
+ if(!nv_hasdisc(nq,&type_disc))
+ _nv_unset(nq,flag|NV_TYPE|nv_isattr(nq,NV_RDONLY));
+ }
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ }
+}
+
+static Namval_t *next_type(register Namval_t* np, Dt_t *root,Namfun_t *fp)
+{
+ Namtype_t *dp = (Namtype_t*)fp;
+ if(!root)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ if(ap && (ap->nelem&ARRAY_UNDEF))
+ nv_putsub(np,(char*)0,ARRAY_SCAN);
+ dp->current = 0;
+ }
+ else if(++dp->current>=dp->numnodes)
+ return(0);
+ return(nv_namptr(dp->nodes,dp->current));
+}
+
+static Namfun_t *clone_inttype(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namfun_t *pp= (Namfun_t*)malloc(fp->dsize);
+ memcpy((void*)pp, (void*)fp, fp->dsize);
+ fp->nofree &= ~1;
+ if(nv_isattr(mp,NV_NOFREE) && mp->nvalue.cp)
+ memcpy((void*)mp->nvalue.cp,np->nvalue.cp, fp->dsize-sizeof(*fp));
+ else
+ mp->nvalue.cp = (char*)(fp+1);
+ if(!nv_isattr(mp,NV_MINIMAL))
+ mp->nvenv = 0;
+ nv_offattr(mp,NV_RDONLY);
+ return(pp);
+}
+
+static int typeinfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
+{
+ char *cp,**help,buffer[256];
+ Namtype_t *dp;
+ Namval_t *np,*nq,*tp;
+ int n, i, offset=staktell();
+ Sfio_t *sp;
+
+ np = *(Namval_t**)(fp+1);
+ stakputs(NV_CLASS);
+ stakputc('.');
+ stakputs(np->nvname);
+ stakputc(0);
+ np = nv_open(cp=stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME);
+ stakseek(offset);
+ if(!np)
+ {
+ sfprintf(sfstderr,"%s: no such variable\n",cp);
+ return(-1);
+ }
+ if(!(dp=(Namtype_t*)nv_hasdisc(np,&type_disc)))
+ {
+ Namfun_t *fp;
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(fp->disc && fp->disc->clonef==clone_inttype)
+ break;
+ }
+ if(!fp)
+ {
+ sfprintf(sfstderr,"%s: not a type\n",np->nvname);
+ return(-1);
+ }
+ if(strcmp(str,"other")==0)
+ return(0);
+ tp = fp->type;
+ nv_offattr(np,NV_RDONLY);
+ fp->type = 0;
+ if(np->nvenv)
+ sfprintf(out,"[+?\b%s\b is a %s.]\n", tp->nvname, np->nvenv);
+ cp = (char*)out->_next;
+ sfprintf(out,"[+?\b%s\b is a %n ", tp->nvname, &i);
+ nv_attribute(np,out,(char*)0, 1);
+ if(cp[i+1]=='i')
+ cp[i-1]='n';
+ fp->type = tp;
+ nv_onattr(np,NV_RDONLY);
+ sfprintf(out," with default value \b%s\b.]",nv_getval(np));
+ return(0);
+ }
+ if(strcmp(str,"other")==0)
+ {
+ Nambfun_t *bp;
+ if(bp=(Nambfun_t*)nv_hasdisc(np,nv_discfun(NV_DCADD)))
+ {
+ for(i=0; i < bp->num; i++)
+ {
+ if(nv_isattr(bp->bltins[i],NV_OPTGET))
+ sfprintf(out,"\b%s.%s\b(3), ",np->nvname,bp->bnames[i]);
+ }
+ }
+ return(0);
+ }
+ help = &dp->names[dp->ndisc];
+ sp = sfnew((Sfio_t*)0,buffer,sizeof(buffer),-1,SF_STRING|SF_WRITE);
+ sfprintf(out,"[+?\b%s\b defines the following fields:]{\n",np->nvname);
+ for(i=0; i < dp->numnodes; i++)
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if(tp=nv_type(nq))
+ {
+ Namfun_t *pp = nv_hasdisc(nq,&type_disc);
+ sfprintf(out,"\t[+%s?%s.\n",nq->nvname,tp->nvname);
+ n = strlen(nq->nvname);
+ while((cp=nv_namptr(dp->nodes,i+1)->nvname) && memcmp(cp,nq->nvname,n)==0 && cp[n]=='.')
+ i++;
+ }
+ else
+ {
+ sfseek(sp,(Sfoff_t)0, SEEK_SET);
+ nv_attribute(nq,sp,(char*)0,1);
+ cp = 0;
+ if(!nv_isattr(nq,NV_REF))
+ cp = sh_fmtq(nv_getval(nq));
+ sfputc(sp,0);
+ for(n=strlen(buffer); n>0 && buffer[n-1]==' '; n--);
+ buffer[n] = 0;
+ if(cp)
+ sfprintf(out,"\t[+%s?%s, default value is %s.\n",nq->nvname,*buffer?buffer:"string",cp);
+ else
+ sfprintf(out,"\t[+%s?%s.\n",nq->nvname,*buffer?buffer:"string");
+ }
+ if(help[i])
+ sfprintf(out," %s.",help[i]);
+ sfputc(out,']');
+ }
+ sfprintf(out,"}\n");
+ if(dp->ndisc>0)
+ {
+ stakseek(offset);
+ stakputs(NV_CLASS);
+ stakputc('.');
+ stakputs(np->nvname);
+ stakputc('.');
+ n = staktell();
+ sfprintf(out,"[+?\b%s\b defines the following discipline functions:]{\n",np->nvname);
+ for(i=0; i < dp->ndisc; i++)
+ {
+ stakputs(dp->names[i]);
+ stakputc(0);
+ cp = 0;
+ if((nq = nv_search(stakptr(offset),sh.fun_tree,0)) && nq->nvalue.cp)
+ cp = nq->nvalue.rp->help;
+ if(nq && nv_isattr(nq,NV_STATICF))
+ sfprintf(out,"\t[+%s?:static:%s]\n",dp->names[i],cp?cp:Empty);
+ else
+ sfprintf(out,"\t[+%s?%s]\n",dp->names[i],cp?cp:Empty);
+ if(cp)
+ sfputc(out,'.');
+ stakseek(n);
+ }
+ sfprintf(out,"}\n");
+ }
+ stakseek(offset);
+ sfclose(sp);
+ return(0);
+}
+
+static int std_disc(Namval_t *mp, Namtype_t *pp)
+{
+ register const char *sp, *cp = strrchr(mp->nvname,'.');
+ register const char **argv;
+ register int i;
+ Namval_t *np=0,*nq;
+ if(cp)
+ cp++;
+ else
+ cp = mp->nvname;
+ if(strcmp(cp,"create")==0)
+ {
+ if(pp)
+ pp->cp = mp;
+ return(0);
+ }
+ for(argv=nv_discnames; sp=*argv; argv++)
+ {
+ if(strcmp(cp,sp)==0)
+ {
+ if(!pp)
+ return(1);
+ goto found;
+ }
+ }
+ return(0);
+found:
+ if(memcmp(sp=mp->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
+ sp += sizeof(NV_CLASS);
+ sp += strlen(pp->fun.type->nvname)+1;
+ if(sp == cp)
+ np = pp->fun.type;
+ else for(i=1; i < pp->numnodes; i++)
+ {
+ nq = nv_namptr(pp->nodes,i);
+ if(memcmp(nq->nvname, sp, cp-sp-1)==0)
+ {
+ np = nq;
+ break;
+ }
+ }
+ if(np)
+ {
+ nv_onattr(mp,NV_NOFREE);
+ if(!nv_setdisc(np,cp, mp, (Namfun_t*)np))
+ sfprintf(sfstderr," nvsetdisc failed name=%s sp=%s cp=%s\n",np->nvname,sp,cp);
+ }
+ else
+ sfprintf(sfstderr,"can't set discipline %s cp=%s \n",sp,cp);
+ return(1);
+}
+
+
+void nv_addtype(Namval_t *np, const char *optstr, Optdisc_t *op, size_t optsz)
+{
+ Namdecl_t *cp = newof((Namdecl_t*)0,Namdecl_t,1,optsz);
+ Optdisc_t *dp = (Optdisc_t*)(cp+1);
+ Shell_t *shp = sh_getinterp();
+ Namval_t *mp,*bp;
+ char *name;
+ if(optstr)
+ cp->optstring = optstr;
+ else
+ cp->optstring = sh_opttype;
+ memcpy((void*)dp,(void*)op, optsz);
+ cp->optinfof = (void*)dp;
+ cp->tp = np;
+ mp = nv_search("typeset",shp->bltin_tree,0);
+ if(name=strrchr(np->nvname,'.'))
+ name++;
+ else
+ name = np->nvname;
+#if SHOPT_NAMESPACE
+ if(bp=(Namval_t*)shp->namespace)
+ {
+ Namtype_t *tp = (Namtype_t*)nv_hasdisc(np, &type_disc);
+ if(tp)
+ tp->nsp = bp;
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ sfprintf(shp->strbuf2,"%s.%s%c\n",nv_name(bp)+1,name,0);
+ name = sfstruse(shp->strbuf2);
+ }
+#endif /* SHOPT_NAMESPACE */
+ if((bp=nv_search(name,shp->fun_tree,NV_NOSCOPE)) && !bp->nvalue.ip)
+ nv_delete(bp,shp->fun_tree,0);
+ bp = sh_addbuiltin(name, (Shbltin_f)mp->nvalue.bfp, (void*)cp);
+ nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
+ nv_onattr(np, NV_RDONLY);
+}
+
+void nv_newtype(Namval_t *mp)
+{
+ struct {
+ Optdisc_t opt;
+ Namval_t *np;
+ } optdisc;
+ memset(&optdisc,0,sizeof(optdisc));
+ optdisc.opt.infof = typeinfo;
+ optdisc.np = mp;
+ nv_addtype(mp,sh_opttype, &optdisc.opt, sizeof(optdisc));
+}
+
+/*
+ * This function creates a type out of the <numnodes> nodes in the
+ * array <nodes>. The first node is the name for the type
+ */
+Namval_t *nv_mktype(Namval_t **nodes, int numnodes)
+{
+ Namval_t *mp=nodes[0], *bp=0, *np, *nq, **mnodes=nodes;
+ int i,j,k,m,n,nd=0,nref=0,iref=0,inherit=0;
+ int size=sizeof(NV_DATA), dsize=0, nnodes;
+ size_t offset=0;
+ char *name=0, *cp, *sp, **help;
+ Namtype_t *pp,*qp=0,*dp,*tp;
+ Dt_t *root = nv_dict(mp);
+ struct Namref *nrp = 0;
+ Namfun_t *fp;
+ m = strlen(mp->nvname)+1;
+ if(numnodes < 2)
+ {
+ cp = nodes[0]->nvname;
+ _nv_unset(nodes[0],NV_RDONLY);
+ errormsg(SH_DICT,ERROR_exit(1),e_badtypedef,cp);
+ }
+ for(nnodes=1,i=1; i <numnodes; i++)
+ {
+ np=nodes[i];
+ if(is_afunction(np))
+ {
+ if(!std_disc(np, (Namtype_t*)0))
+ {
+ size += strlen(np->nvname+m)+1;
+ if(memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
+ size -= sizeof(NV_CLASS);
+ nd++;
+ }
+ continue;
+ }
+ if(nv_isattr(np,NV_REF))
+ iref++;
+ if(np->nvenv)
+ size += strlen((char*)np->nvenv)+1;
+ if(strcmp(&np->nvname[m],NV_DATA)==0 && !nv_type(np))
+ continue;
+ if(qp)
+ { /* delete duplicates */
+ for(j=0; j < qp->numnodes;j++)
+ {
+ nq = nv_namptr(qp->nodes,j);
+ if(strcmp(nq->nvname,&np->nvname[m])==0)
+ break;
+ }
+ if(j < qp->numnodes)
+ continue;
+ }
+ nnodes++;
+ if(name && memcmp(&name[m],&np->nvname[m],n)==0 && np->nvname[m+n]=='.')
+ offset -= sizeof(char*);
+ dsize = nv_datasize(np,&offset);
+ if(!nv_isarray(np) && (dp=(Namtype_t*)nv_hasdisc(np, &type_disc)))
+ {
+ nnodes += dp->numnodes;
+ if((n=dp->strsize)<0)
+ n = -n;
+ iref = nref += dp->nref;
+ if(np->nvname[m]=='_' && np->nvname[m+1]==0 && (bp=nv_type(np)))
+ {
+ qp = dp;
+ nd = dp->ndisc;
+ nnodes = dp->numnodes;
+ offset = 0;
+ dsize = nv_size(np);
+ size += n;
+ }
+ else
+ size += n + dp->numnodes*(strlen(&np->nvname[m])+1);
+ n = strlen(np->nvname);
+ while((i+1) < numnodes && (cp=nodes[i+1]->nvname) && memcmp(cp,np->nvname,n)==0 && cp[n]=='.')
+ i++;
+ }
+ else if(nv_isattr(np,NV_REF))
+ nref++;
+ offset += (dsize?dsize:4);
+ size += (n=strlen(name=np->nvname)-m+1);
+ }
+ offset = roundof(offset,sizeof(char*));
+ nv_setsize(mp,offset);
+ if(nd)
+ nd++;
+ k = roundof(sizeof(Namtype_t),sizeof(Sfdouble_t)) - sizeof(Namtype_t);
+ pp = newof(NiL, Namtype_t, 1, nnodes*NV_MINSZ + offset + size + (nnodes+nd)*sizeof(char*) + iref*sizeof(struct Namref)+k);
+ pp->fun.dsize = sizeof(Namtype_t)+nnodes*NV_MINSZ +offset+k;
+ pp->fun.type = mp;
+ pp->parent = nv_lastdict();
+ pp->np = mp;
+ pp->bp = bp;
+ pp->childfun.fun.disc = &chtype_disc;
+ pp->childfun.fun.nofree = 1;
+ pp->childfun.ttype = pp;
+ pp->childfun.ptype = pp;
+ pp->fun.disc = &type_disc;
+ pp->nodes = (char*)(pp+1);
+ pp->numnodes = nnodes;
+ pp->data = pp->nodes + nnodes*NV_MINSZ +k;
+ pp->dsize = offset;
+ nrp = (struct Namref*)(pp->data+offset);
+ pp->names = (char**)(nrp+iref);
+ help = &pp->names[nd];
+ pp->strsize = size;
+ cp = (char*)&pp->names[nd+nnodes];
+ if(qp)
+ mnodes = newof(NiL, Namval_t*, nd+1, 0);
+ nd = 0;
+ nq = nv_namptr(pp->nodes,0);
+ nq->nvname = cp;
+ nv_onattr(nq,NV_MINIMAL);
+ cp = strcopy(cp,NV_DATA);
+ *cp++ = 0;
+ for(name=0, offset=0, k=i=1; i < numnodes; i++)
+ {
+ np=nodes[i];
+ if(is_afunction(np))
+ {
+ sp = np->nvname+m;
+ if(memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
+ sp += sizeof(NV_CLASS);
+ if(!std_disc(np, pp))
+ {
+ /* see if discipline already defined */
+ for(j=0; j< nd; j++)
+ {
+ if(strcmp(sp,pp->names[j])==0)
+ {
+ mnodes[j] = nodes[i];
+ break;
+ }
+ }
+ if(j>=nd)
+ {
+ pp->names[nd] = cp;
+ mnodes[nd++] = nodes[i];
+ cp = strcopy(cp,sp);
+ *cp++ = 0;
+ }
+ nv_onattr(mnodes[j],NV_NOFREE);
+ }
+ continue;
+ }
+ if(inherit)
+ {
+ for(j=0; j < k ; j++)
+ {
+ nq = nv_namptr(pp->nodes,j);
+ if(strcmp(nq->nvname,&np->nvname[m])==0)
+ break;
+ }
+ if(j < k)
+ {
+ sp = nv_getval(np);
+ if(nv_isvtree(np))
+ sfprintf(sfstderr,"initialization not implemented\n");
+ else if(sp)
+ nv_putval(nq,sp,0);
+ goto skip;
+ }
+ }
+ if(strcmp(&np->nvname[m],NV_DATA)==0 && !nv_type(np))
+ {
+ char *val=nv_getval(np);
+ nq = nv_namptr(pp->nodes,0);
+ nq->nvfun = 0;
+ nv_putval(nq,(val?val:0),nv_isattr(np,~(NV_IMPORT|NV_EXPORT|NV_ARRAY)));
+ nq->nvflag = np->nvflag|NV_NOFREE|NV_MINIMAL;
+ goto skip;
+ }
+ if(qp)
+ {
+ Nambfun_t *bp;
+ dp = (Namtype_t*)nv_hasdisc(nv_type(np), &type_disc);
+ memcpy(pp->nodes,dp->nodes,dp->numnodes*NV_MINSZ);
+ offset = nv_size(np);
+ memcpy(pp->data,dp->data,offset);
+ for(k=0;k < dp->numnodes; k++)
+ {
+ Namval_t *nr = nv_namptr(qp->nodes,k);
+ nq = nv_namptr(pp->nodes,k);
+ if(fixnode(pp,dp,k,nrp,0))
+ {
+ nrp++;
+ nq = nq->nvalue.nrp->np;
+ }
+ if(!nv_isattr(nr,NV_REF) && !nv_hasdisc(nr,&type_disc))
+ {
+ if(nr->nvsize)
+ memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,size=nv_datasize(nr,(size_t*)0));
+ else
+ {
+ nq->nvalue.cp = nr->nvalue.cp;
+ nv_onattr(nq,NV_NOFREE);
+ }
+ }
+ }
+ if(bp=(Nambfun_t*)nv_hasdisc(np,nv_discfun(NV_DCADD)))
+ {
+ for(j=0; j < bp->num; j++)
+ {
+ pp->names[nd++] = (char*)bp->bnames[j];
+ mnodes[j] = bp->bltins[j];
+ }
+ }
+ qp = 0;
+ inherit=1;
+ goto skip;
+ }
+ nq = nv_namptr(pp->nodes,k);
+ if(np->nvenv)
+ {
+ /* need to save the string pointer */
+ nv_offattr(np,NV_EXPORT);
+ help[k] = cp;
+ cp = strcopy(cp,np->nvenv);
+ j = *help[k];
+ if(islower(j))
+ *help[k] = toupper(j);
+ *cp++ = 0;
+ np->nvenv = 0;
+ }
+ nq->nvname = cp;
+ if(name && memcmp(name,&np->nvname[m],n)==0 && np->nvname[m+n]=='.')
+ offset -= sizeof(char*);
+ dsize = nv_datasize(np,&offset);
+ cp = strcopy(name=cp, &np->nvname[m]);
+ n = cp-name;
+ *cp++ = 0;
+ nq->nvsize = np->nvsize;
+ nq->nvflag = (np->nvflag&~(NV_IMPORT|NV_EXPORT))|NV_NOFREE|NV_MINIMAL;
+ if(dp = (Namtype_t*)nv_hasdisc(np, &type_disc))
+ {
+ int r,kfirst=k;
+ char *cname = &np->nvname[m];
+ /*
+ * If field is a type, mark the type by setting
+ * strsize<0. This changes create_type()
+ */
+ clone_all_disc(np,nq,NV_RDONLY);
+ if(nv_isarray(np))
+ {
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ k++;
+ goto skip;
+ }
+ if(fp=nv_hasdisc(nq,&chtype_disc))
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ if(tp = (Namtype_t*)nv_hasdisc(nq, &type_disc))
+ tp->strsize = -tp->strsize;
+else sfprintf(sfstderr,"tp==NULL\n");
+ for(r=0; r < dp->numnodes; r++)
+ {
+ Namval_t *nr = nv_namptr(dp->nodes,r);
+ nq = nv_namptr(pp->nodes,++k);
+ nq->nvname = cp;
+ dsize = nv_datasize(nr,&offset);
+ nq->nvflag = nr->nvflag;
+ if(nr->nvalue.cp)
+ {
+ Namchld_t *xp = (Namchld_t*)nv_hasdisc(nr,&chtype_disc);
+ if(xp && nr->nvalue.cp >= xp->ptype->data && nr->nvalue.cp < xp->ptype->data+xp->ptype->fun.dsize)
+ {
+ nq->nvalue.cp = pp->data+offset;
+ memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,dsize);
+ nv_onattr(nq,NV_NOFREE);
+ }
+ else
+ nq->nvalue.cp = strdup(nr->nvalue.cp);
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ }
+ nq->nvsize = nr->nvsize;
+ offset += dsize;
+ if(*cname!='_' || cname[1])
+ {
+ cp = strcopy(cp,cname);
+ *cp++ = '.';
+ }
+ cp = strcopy(cp,nr->nvname);
+ *cp++ = 0;
+ }
+ while((i+1) < numnodes && (cname=&nodes[i+1]->nvname[m]) && memcmp(cname,&np->nvname[m],n)==0 && cname[n]=='.')
+ {
+ int j=kfirst;
+ nv_unset(np);
+ nv_delete(np,root,0);
+ np = nodes[++i];
+ while(j < k)
+ {
+ nq = nv_namptr(pp->nodes,++j);
+ if(strcmp(nq->nvname,cname)==0)
+ {
+ sfprintf(sfstderr,"%s found at k=%d\n",nq->nvname,k);
+ if(nq->nvalue.cp>=pp->data && nq->nvalue.cp< (char*)pp->names)
+ memcpy((char*)nq->nvalue.cp,np->nvalue.cp,nv_datasize(np,0));
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ j = nv_isattr(np,NV_NOFREE);
+ nq->nvfun = np->nvfun;
+ np->nvfun = 0;
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ if(nq->nvfun)
+ {
+ for(fp=nq->nvfun; fp; fp = fp->next)
+ fp->nofree |= 1;
+ }
+ nq->nvalue.cp = np->nvalue.cp;
+ if(dsize && (np->nvalue.cp || !nv_isarray(np)))
+ {
+ nq->nvalue.cp = pp->data+offset;
+ sp = (char*)np->nvalue.cp;
+ if(nv_isattr(np,NV_INT16P) ==NV_INT16)
+ {
+ sp= (char*)&np->nvalue;
+ nv_onattr(nq,NV_INT16P);
+ j = 1;
+ }
+ if(sp)
+ memcpy((char*)nq->nvalue.cp,sp,dsize);
+ else if(nv_isattr(np,NV_LJUST|NV_RJUST))
+ memset((char*)nq->nvalue.cp,' ',dsize);
+ if(!j)
+ free((void*)np->nvalue.cp);
+ }
+ if(!nq->nvalue.cp && nq->nvfun== &pp->childfun.fun)
+ nq->nvalue.cp = Empty;
+ np->nvalue.cp = 0;
+#if 0
+ offset += dsize;
+#else
+ offset += (dsize?dsize:4);
+#endif
+ }
+ k++;
+ skip:
+ if(!nv_isnull(np))
+ _nv_unset(np,0);
+ nv_delete(np,root,0);
+ }
+ pp->ndisc = nd;
+ pp->nref = nref;
+ if(k>1)
+ {
+ nv_setsize(mp,offset);
+ mp->nvalue.cp = pp->data;
+ nv_onattr(mp,NV_NOFREE|NV_BINARY|NV_RAW);
+ }
+ else if(!mp->nvalue.cp)
+ mp->nvalue.cp = Empty;
+ nv_disc(mp, &pp->fun, NV_LAST);
+ if(nd>0)
+ {
+ pp->names[nd] = 0;
+ nv_adddisc(mp, (const char**)pp->names, mnodes);
+ }
+ if(mnodes!=nodes)
+ free((void*)mnodes);
+ nv_newtype(mp);
+ return(mp);
+}
+
+Namval_t *nv_mkinttype(char *name, size_t size, int sign, const char *help, Namdisc_t *ep)
+{
+ Namval_t *mp;
+ Namfun_t *fp;
+ Namdisc_t *dp;
+ int offset=staktell();
+ stakputs(NV_CLASS);
+ stakputc('.');
+ stakputs(name);
+ stakputc(0);
+ mp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
+ stakseek(offset);
+ offset = size + sizeof(Namdisc_t);
+ fp = newof(NiL, Namfun_t, 1, offset);
+ fp->type = mp;
+ fp->nofree |= 1;
+ fp->dsize = sizeof(Namfun_t)+size;
+ dp = (Namdisc_t*)(fp+1);
+ if(ep)
+ *dp = *ep;
+ dp->clonef = clone_inttype;
+ fp->disc = dp;
+ mp->nvalue.cp = (char*)(fp+1) + sizeof(Namdisc_t);
+ nv_setsize(mp,10);
+ mp->nvenv = (char*)help;
+ nv_onattr(mp,NV_NOFREE|NV_RDONLY|NV_INTEGER|NV_EXPORT);
+ if(size==16)
+ nv_onattr(mp,NV_INT16P);
+ else if(size==64)
+ nv_onattr(mp,NV_INT64);
+ if(!sign)
+ nv_onattr(mp,NV_UNSIGN);
+ nv_disc(mp, fp, NV_LAST);
+ nv_newtype(mp);
+ return(mp);
+}
+
+void nv_typename(Namval_t *tp, Sfio_t *out)
+{
+ char *v,*cp;
+ Namtype_t *dp;
+ cp = nv_name(tp);
+ if(v=strrchr(cp,'.'))
+ cp = v+1;
+ if((dp = (Namtype_t*)nv_hasdisc(tp,&type_disc)) && dp->bp)
+ {
+ nv_typename(dp->bp,out);
+ sfprintf(out,"%s.%s",sfstruse(out),cp);
+ }
+ else
+ sfputr(out,cp,-1);
+}
+
+Namval_t *nv_type(Namval_t *np)
+{
+ Namfun_t *fp;
+ if(nv_isattr(np,NV_BLTIN|BLT_DCL)==(NV_BLTIN|BLT_DCL))
+ {
+ Namdecl_t *ntp = (Namdecl_t*)nv_context(np);
+ return(ntp?ntp->tp:0);
+ }
+ for(fp=np->nvfun; fp; fp=fp->next)
+ {
+ if(fp->type)
+ return(fp->type);
+ if(fp->disc && fp->disc->typef && (np= (*fp->disc->typef)(np,fp)))
+ return(np);
+ }
+ return(0);
+}
+
+/*
+ * call any and all create functions
+ */
+static void type_init(Namval_t *np)
+{
+ int i;
+ Namtype_t *dp, *pp=(Namtype_t*)nv_hasdisc(np,&type_disc);
+ Namval_t *nq;
+ if(!pp)
+ return;
+ for(i=0; i < pp->numnodes; i++)
+ {
+ nq = nv_namptr(pp->nodes,i);
+ if((dp=(Namtype_t*)nv_hasdisc(nq,&type_disc)) && dp->cp)
+ sh_fun(dp->cp,nq, (char**)0);
+ }
+ if(pp->cp)
+ sh_fun(pp->cp, np, (char**)0);
+}
+
+/*
+ * This function turns variable <np> to the type <tp>
+ */
+int nv_settype(Namval_t* np, Namval_t *tp, int flags)
+{
+ int isnull = nv_isnull(np);
+ int rdonly = nv_isattr(np,NV_RDONLY);
+ char *val=0;
+ Namarr_t *ap=0;
+ Shell_t *shp = sh_getinterp();
+ int nelem=0,subshell=shp->subshell;
+#if SHOPT_TYPEDEF
+ Namval_t *tq;
+ if(nv_type(np)==tp)
+ return(0);
+ if(nv_isarray(np) && (tq=nv_type(np)))
+ {
+ if(tp==tq)
+ return(0);
+ errormsg(SH_DICT,ERROR_exit(1),e_redef,nv_name(np));
+ }
+ if((ap=nv_arrayptr(np)) && ap->nelem>0)
+ {
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ ap->hdr.type = tp;
+ do
+ {
+ nv_arraysettype(np, tp, nv_getsub(np),flags);
+ }
+ while(nv_nextsub(np));
+ }
+ else if(ap || nv_isarray(np))
+ {
+ flags &= ~NV_APPEND;
+ if(!ap)
+ {
+ if(subshell)
+ {
+ sh_assignok(np,1);
+ shp->subshell = 0;
+ }
+ nv_putsub(np,"0",ARRAY_FILL);
+ ap = nv_arrayptr(np);
+ nelem = 1;
+
+ }
+ }
+ else
+#endif /*SHOPT_TYPEDEF */
+ {
+ if(isnull)
+ flags &= ~NV_APPEND;
+ else if(!nv_isvtree(np))
+ {
+ val = strdup(nv_getval(np));
+ if(!(flags&NV_APPEND))
+ _nv_unset(np, NV_RDONLY);
+ }
+ if(!nv_clone(tp,np,flags|NV_NOFREE))
+ return(0);
+ }
+ if(ap)
+ {
+ int nofree;
+ nv_disc(np,&ap->hdr,NV_POP);
+ np->nvalue.up = 0;
+ nv_clone(tp,np,flags|NV_NOFREE);
+ if(np->nvalue.cp && np->nvalue.cp!=Empty && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvalue.cp);
+ np->nvalue.up = 0;
+ nofree = ap->hdr.nofree;
+ ap->hdr.nofree = 0;
+ ap->hdr.type = tp;
+ nv_disc(np, &ap->hdr, NV_FIRST);
+ ap->hdr.nofree = nofree;
+ nv_onattr(np,NV_ARRAY);
+ if(nelem)
+ {
+ ap->nelem++;
+ nv_putsub(np,"0",0);
+ _nv_unset(np,NV_RDONLY|NV_TYPE);
+ ap->nelem--;
+ shp->subshell = subshell;
+ }
+ }
+ type_init(np);
+ if(!rdonly)
+ nv_offattr(np,NV_RDONLY);
+ if(val)
+ {
+ nv_putval(np,val,NV_RDONLY);
+ free((void*)val);
+ }
+ return(0);
+}
+
+#define S(x) #x
+#define FIELD(x,y) { S(y##x), S(x##_t), offsetof(struct stat,st_##y##x) }
+typedef struct _field_
+{
+ char *name;
+ char *type;
+ int offset;
+} Fields_t;
+
+Fields_t foo[]=
+{
+ FIELD(dev,),
+ FIELD(ino,),
+ FIELD(nlink,),
+ FIELD(mode,),
+ FIELD(uid,),
+ FIELD(gid,),
+ FIELD(size,),
+ FIELD(time,a),
+ FIELD(time,m),
+ FIELD(time,c),
+#if 0
+ FIELD(blksize,),
+ FIELD(blocks,),
+#endif
+ 0
+};
+
+
+Namval_t *nv_mkstruct(const char *name, int rsize, Fields_t *fields)
+{
+ Namval_t *mp, *nq, *nr, *tp;
+ Fields_t *fp;
+ Namtype_t *dp, *pp;
+ char *cp, *sp;
+ int nnodes=0, offset=staktell(), n, r, i, j;
+ size_t m, size=0;
+ stakputs(NV_CLASS);
+ stakputc('.');
+ r = staktell();
+ stakputs(name);
+ stakputc(0);
+ mp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
+ stakseek(r);
+
+ for(fp=fields; fp->name; fp++)
+ {
+ m = strlen(fp->name)+1;
+ size += m;
+ nnodes++;
+ if(memcmp(fp->type,"typeset",7))
+ {
+ stakputs(fp->type);
+ stakputc(0);
+ tp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME|NV_NOADD|NV_NOFAIL);
+ stakseek(r);
+ if(!tp)
+ errormsg(SH_DICT,ERROR_exit(1),e_unknowntype,strlen(fp->type),fp->type);
+ if(dp = (Namtype_t*)nv_hasdisc(tp,&type_disc))
+ {
+ nnodes += dp->numnodes;
+ if((i=dp->strsize) < 0)
+ i = -i;
+ size += i + dp->numnodes*m;
+ }
+ }
+ }
+ pp = newof(NiL,Namtype_t, 1, nnodes*NV_MINSZ + rsize + size);
+ pp->fun.dsize = sizeof(Namtype_t)+nnodes*NV_MINSZ +rsize;
+ pp->fun.type = mp;
+ pp->np = mp;
+ pp->childfun.fun.disc = &chtype_disc;
+ pp->childfun.fun.nofree = 1;
+ pp->childfun.ttype = pp;
+ pp->childfun.ptype = pp;
+ pp->fun.disc = &type_disc;
+ pp->nodes = (char*)(pp+1);
+ pp->numnodes = nnodes;
+ pp->strsize = size;
+ pp->data = pp->nodes + nnodes*NV_MINSZ;
+ cp = pp->data + rsize;
+ for(i=0,fp=fields; fp->name; fp++)
+ {
+ nq = nv_namptr(pp->nodes,i++);
+ nq->nvname = cp;
+ nq->nvalue.cp = pp->data + fp->offset;
+ nv_onattr(nq,NV_MINIMAL|NV_NOFREE);
+ m = strlen(fp->name)+1;
+ memcpy(cp, fp->name, m);
+ cp += m;
+ if(memcmp(fp->type,"typeset",7))
+ {
+ stakputs(fp->type);
+ stakputc(0);
+ tp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
+ stakseek(r);
+ clone_all_disc(tp,nq,NV_RDONLY);
+ nq->nvflag = tp->nvflag|NV_MINIMAL|NV_NOFREE;
+ nq->nvsize = tp->nvsize;
+ if(dp = (Namtype_t*)nv_hasdisc(nq,&type_disc))
+ dp->strsize = -dp->strsize;
+ if(dp = (Namtype_t*)nv_hasdisc(tp,&type_disc))
+ {
+ if(nv_hasdisc(nq,&chtype_disc))
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ sp = (char*)nq->nvalue.cp;
+ memcpy(sp, dp->data, nv_size(tp));
+ for(j=0; j < dp->numnodes; j++)
+ {
+ nr = nv_namptr(dp->nodes,j);
+ nq = nv_namptr(pp->nodes,i++);
+ nq->nvname = cp;
+ memcpy(cp,fp->name,m);
+ cp[m-1] = '.';
+ cp += m;
+ n = strlen(nr->nvname)+1;
+ memcpy(cp,nr->nvname,n);
+ cp += n;
+ if(nr->nvalue.cp>=dp->data && nr->nvalue.cp < (char*)pp + pp->fun.dsize)
+ {
+ nq->nvalue.cp = sp + (nr->nvalue.cp-dp->data);
+ }
+ nq->nvflag = nr->nvflag;
+ nq->nvsize = nr->nvsize;
+ }
+ }
+ }
+ else if(strmatch(fp->type+7,"*-*i*")==0)
+ {
+ nv_onattr(nq,NV_NOFREE|NV_RDONLY|NV_INTEGER);
+ if(strmatch(fp->type+7,"*-*s*")==0)
+ nv_onattr(nq,NV_INT16P);
+ else if(strmatch(fp->type+7,"*-*l*")==0)
+ nv_onattr(nq,NV_INT64);
+ if(strmatch(fp->type+7,"*-*u*")==0)
+ nv_onattr(nq,NV_UNSIGN);
+ }
+
+ }
+ stakseek(offset);
+ nv_onattr(mp,NV_RDONLY|NV_NOFREE|NV_BINARY);
+ nv_setsize(mp,rsize);
+ nv_disc(mp, &pp->fun, NV_LAST);
+ mp->nvalue.cp = pp->data;
+ nv_newtype(mp);
+ return(mp);
+}
+
+static void put_stat(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
+{
+ if(val)
+ {
+ if(stat(val,(struct stat*)np->nvalue.cp)<0)
+ sfprintf(sfstderr,"stat of %s failed\n",val);
+ return;
+ }
+ nv_putv(np,val,flag,nfp);
+ nv_disc(np,nfp,NV_POP);
+ if(!(nfp->nofree&1))
+ free((void*)nfp);
+}
+
+static const Namdisc_t stat_disc =
+{
+ 0,
+ put_stat
+};
+
+
+void nv_mkstat(void)
+{
+ Namval_t *tp;
+ Namfun_t *fp;
+ tp = nv_mkstruct("stat_t", sizeof(struct stat), foo);
+ nv_offattr(tp,NV_RDONLY);
+ nv_setvtree(tp);
+ fp = newof(NiL,Namfun_t,1,0);
+ fp->type = tp;
+ fp->disc = &stat_disc;
+ nv_disc(tp,fp,NV_FIRST);
+ nv_putval(tp,e_devnull,0);
+ nv_onattr(tp,NV_RDONLY);
+}
+
+static void write_indent(Sfio_t *out,char *str,int n,int indent)
+{
+ register int c, first=1;
+ register char *cp = str;
+ while(n-- && (c = *str++))
+ {
+ if(c=='\n')
+ {
+ if(!first)
+ sfnputc(out,'\t',indent);
+ first = 0;
+ sfwrite(out,cp,str-cp);
+ cp = str;
+ }
+ }
+ if(cp > str)
+ {
+ sfnputc(out,'\t',indent);
+ sfwrite(out,cp,str-cp);
+ }
+}
+
+int sh_outtype(Shell_t *shp,Sfio_t *out)
+{
+ Namval_t node,*mp,*tp;
+ Dt_t *dp;
+ char *cp,*sp,*xp,nvtype[sizeof(NV_CLASS)];
+ Sfio_t *iop=0;
+ int n=0,indent = 0;
+ if(cp=shp->prefix)
+ {
+ indent=1;
+ while(*cp)
+ {
+ if(*cp++ =='.')
+ indent++;
+ }
+ n = cp-shp->prefix+1;
+ }
+ strcpy(nvtype,NV_CLASS);
+ if(!(mp = nv_open(nvtype, shp->var_base,NV_NOADD|NV_VARNAME)))
+ return(0);
+ memcpy(&node,L_ARGNOD,sizeof(node));
+ L_ARGNOD->nvfun = 0;
+ L_ARGNOD->nvalue.cp = 0;
+ dp = nv_dict(mp);
+ if(indent==0)
+ for(tp = (Namval_t*)dtfirst(dp); tp; tp = (Namval_t*)dtnext(dp,tp))
+ {
+ if(!nv_search(tp->nvname,shp->bltin_tree,0))
+ continue;
+ sfprintf(out,"typeset -T %s\n",tp->nvname);
+ }
+ for(tp = (Namval_t*)dtfirst(dp); tp; tp = (Namval_t*)dtnext(dp,tp))
+ {
+ if(nv_isnull(tp))
+ continue;
+ if(indent && (memcmp(tp->nvname,shp->prefix,n-1) || tp->nvname[n-1]!='.' || strchr(tp->nvname+n,'.')))
+ continue;
+ nv_settype(L_ARGNOD,tp,0);
+ if(indent)
+ sfnputc(out,'\t',indent);
+ sfprintf(out,"typeset -T %s=",tp->nvname+n);
+ shp->last_table = 0;
+ cp = nv_getval(L_ARGNOD);
+ if(indent)
+ write_indent(out,cp,strlen(cp)-1,indent);
+ else
+ sfprintf(out,"%.*s",strlen(cp)-1,cp);
+ _nv_unset(L_ARGNOD,NV_RDONLY);
+ for(sp=0; sp=nv_setdisc(tp,(char*)0,(Namval_t*)sp,(Namfun_t*)tp);)
+ {
+ mp = (Namval_t*)nv_setdisc(tp,sp,tp,(Namfun_t*)tp);
+ if(!mp || mp==tp)
+ continue;
+ if(cp=strrchr(mp->nvname,'.'))
+ cp++;
+ else
+ cp = mp->nvname;
+ if(indent)
+ sfnputc(out,'\t',indent);
+ if(nv_isattr(mp,NV_FPOSIX))
+ sfprintf(out,"\t%s()",cp);
+ else
+ sfprintf(out,"\tfunction %s",cp);
+ xp = 0;
+ if(mp->nvalue.ip && mp->nvalue.rp->hoffset>=0)
+ {
+ if(nv_isattr(mp,NV_FTMP))
+ iop = shp->heredocs;
+ else if(xp=mp->nvalue.rp->fname)
+ iop = sfopen(iop,xp,"r");
+ else if(shp->gd->hist_ptr)
+ iop = (shp->gd->hist_ptr)->histfp;
+ if(iop && sfseek(iop,(Sfoff_t)mp->nvalue.rp->hoffset,SEEK_SET)>=0)
+ sfmove(iop,out, nv_size(mp), -1);
+ else
+ sfputc(iop,'\n');
+ if(xp)
+ sfclose(iop);
+ if(nv_isattr(mp,NV_STATICF|NV_TAGGED))
+ {
+ if(indent)
+ sfnputc(out,'\t',indent);
+ sfwrite(out,"\ttypeset -f",11);
+ if(nv_isattr(mp,NV_STATICF))
+ sfputc(out,'S');
+ if(nv_isattr(mp,NV_TAGGED))
+ sfputc(out,'t');
+ if(mp->nvalue.rp->help)
+ sfprintf(out,"h '%s'",mp->nvalue.rp->help);
+ sfprintf(out," %s\n",cp);
+ }
+ iop = 0;
+ }
+ }
+ if(indent)
+ sfnputc(out,'\t',indent);
+ sfwrite(out,")\n",2);
+ }
+ dtdelete(shp->var_base,L_ARGNOD);
+ memcpy(L_ARGNOD,&node,sizeof(node));
+ dtinsert(shp->var_base,L_ARGNOD);
+ return(0);
+}
diff --git a/src/cmd/ksh93/sh/parse.c b/src/cmd/ksh93/sh/parse.c
new file mode 100644
index 0000000..6ef3ef9
--- /dev/null
+++ b/src/cmd/ksh93/sh/parse.c
@@ -0,0 +1,2082 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Rewritten by David Korn
+ * AT&T Labs
+ *
+ * This is the parser for a shell language
+ */
+
+#if KSHELL
+#include "defs.h"
+#else
+#include <shell.h>
+#include <ctype.h>
+#endif
+#include <fcin.h>
+#include <error.h>
+#include "shlex.h"
+#include "history.h"
+#include "builtins.h"
+#include "test.h"
+#include "history.h"
+
+#define HERE_MEM SF_BUFSIZE /* size of here-docs kept in memory */
+
+#if CDT_VERSION < 20111111L
+#define hash nvlink.hl._hash
+#else
+#define hash nvlink.lh.__hash
+#endif
+
+/* These routines are local to this module */
+
+static Shnode_t *makeparent(Lex_t*, int, Shnode_t*);
+static Shnode_t *makelist(Lex_t*, int, Shnode_t*, Shnode_t*);
+static struct argnod *qscan(struct comnod*, int);
+static struct ionod *inout(Lex_t*,struct ionod*, int);
+static Shnode_t *sh_cmd(Lex_t*,int,int);
+static Shnode_t *term(Lex_t*,int);
+static Shnode_t *list(Lex_t*,int);
+static struct regnod *syncase(Lex_t*,int);
+static Shnode_t *item(Lex_t*,int);
+static Shnode_t *simple(Lex_t*,int, struct ionod*);
+static int skipnl(Lex_t*,int);
+static Shnode_t *test_expr(Lex_t*,int);
+static Shnode_t *test_and(Lex_t*);
+static Shnode_t *test_or(Lex_t*);
+static Shnode_t *test_primary(Lex_t*);
+
+#define sh_getlineno(lp) (lp->lastline)
+
+#ifndef NIL
+# define NIL(type) ((type)0)
+#endif /* NIL */
+#define CNTL(x) ((x)&037)
+
+
+#if !KSHELL
+static struct stdata
+{
+ struct slnod *staklist;
+ int cmdline;
+} st;
+#endif
+
+static int opt_get;
+static int loop_level;
+static struct argnod *label_list;
+static struct argnod *label_last;
+
+#define getnode(type) ((Shnode_t*)stakalloc(sizeof(struct type)))
+
+#if SHOPT_KIA
+#include "path.h"
+/*
+ * write out entities for each item in the list
+ * type=='V' for variable assignment lists
+ * Otherwise type is determined by the command */
+static unsigned long writedefs(Lex_t *lexp,struct argnod *arglist, int line, int type, struct argnod *cmd)
+{
+ register struct argnod *argp = arglist;
+ register char *cp;
+ register int n,eline;
+ int width=0;
+ unsigned long r=0;
+ static char atbuff[20];
+ int justify=0;
+ char *attribute = atbuff;
+ unsigned long parent=lexp->script;
+ if(type==0)
+ {
+ parent = lexp->current;
+ type = 'v';
+ switch(*argp->argval)
+ {
+ case 'a':
+ type='p';
+ justify = 'a';
+ break;
+ case 'e':
+ *attribute++ = 'x';
+ break;
+ case 'r':
+ *attribute++ = 'r';
+ break;
+ case 'l':
+ break;
+ }
+ while(argp = argp->argnxt.ap)
+ {
+ if((n= *(cp=argp->argval))!='-' && n!='+')
+ break;
+ if(cp[1]==n)
+ break;
+ while((n= *++cp))
+ {
+ if(isdigit(n))
+ width = 10*width + n-'0';
+ else if(n=='L' || n=='R' || n =='Z')
+ justify=n;
+ else
+ *attribute++ = n;
+ }
+ }
+ }
+ else if(cmd)
+ parent=kiaentity(lexp,sh_argstr(cmd),-1,'p',-1,-1,lexp->unknown,'b',0,"");
+ *attribute = 0;
+ while(argp)
+ {
+ if((cp=strchr(argp->argval,'='))||(cp=strchr(argp->argval,'?')))
+ n = cp-argp->argval;
+ else
+ n = strlen(argp->argval);
+ eline = lexp->sh->inlineno-(lexp->token==NL);
+ r=kiaentity(lexp,argp->argval,n,type,line,eline,parent,justify,width,atbuff);
+ sfprintf(lexp->kiatmp,"p;%..64d;v;%..64d;%d;%d;s;\n",lexp->current,r,line,eline);
+ argp = argp->argnxt.ap;
+ }
+ return(r);
+}
+#endif /* SHOPT_KIA */
+
+static void typeset_order(const char *str,int line)
+{
+ register int c,n=0;
+ unsigned const char *cp=(unsigned char*)str;
+ static unsigned char *table;
+ if(*cp!='+' && *cp!='-')
+ return;
+ if(!table)
+ {
+ table = calloc(1,256);
+ for(cp=(unsigned char*)"bflmnprstuxACHS";c = *cp; cp++)
+ table[c] = 1;
+ for(cp=(unsigned char*)"aiEFLRXhTZ";c = *cp; cp++)
+ table[c] = 2;
+ for(c='0'; c <='9'; c++)
+ table[c] = 3;
+ }
+ for(cp=(unsigned char*)str; c= *cp++; n=table[c])
+ {
+ if(table[c] < n)
+ errormsg(SH_DICT,ERROR_warn(0),e_lextypeset,line,str);
+ }
+}
+
+/*
+ * add type definitions when compiling with -n
+ */
+static void check_typedef(struct comnod *tp)
+{
+ char *cp=0;
+ if(tp->comtyp&COMSCAN)
+ {
+ struct argnod *ap = tp->comarg;
+ while(ap = ap->argnxt.ap)
+ {
+ if(!(ap->argflag&ARG_RAW) || memcmp(ap->argval,"--",2))
+ break;
+ if(sh_isoption(SH_NOEXEC))
+ typeset_order(ap->argval,tp->comline);
+ if(memcmp(ap->argval,"-T",2)==0)
+ {
+ if(ap->argval[2])
+ cp = ap->argval+2;
+ else if((ap->argnxt.ap)->argflag&ARG_RAW)
+ cp = (ap->argnxt.ap)->argval;
+ if(cp)
+ break;
+ }
+ }
+ }
+ else
+ {
+ struct dolnod *dp = (struct dolnod*)tp->comarg;
+ char **argv = dp->dolval + dp->dolbot+1;
+ while((cp= *argv++) && memcmp(cp,"--",2))
+ {
+ if(sh_isoption(SH_NOEXEC))
+ typeset_order(cp,tp->comline);
+ if(memcmp(cp,"-T",2)==0)
+ {
+ if(cp[2])
+ cp = cp+2;
+ else
+ cp = *argv;
+ break;
+ }
+ }
+ }
+ if(cp)
+ {
+ Namval_t *mp=(Namval_t*)tp->comnamp ,*bp;
+ bp = sh_addbuiltin(cp, (Shbltin_f)mp->nvalue.bfp, (void*)0);
+ nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
+ }
+}
+
+/*
+ * Make a parent node for fork() or io-redirection
+ */
+static Shnode_t *makeparent(Lex_t *lp, int flag, Shnode_t *child)
+{
+ register Shnode_t *par = getnode(forknod);
+ par->fork.forktyp = flag;
+ par->fork.forktre = child;
+ par->fork.forkio = 0;
+ par->fork.forkline = sh_getlineno(lp)-1;
+ return(par);
+}
+
+static int paramsub(const char *str)
+{
+ register int c,sub=0,lit=0;
+ while(c= *str++)
+ {
+ if(c=='$' && !lit)
+ {
+ if(*str=='(')
+ return(0);
+ if(sub)
+ continue;
+ if(*str=='{')
+ str++;
+ if(!isdigit(*str) && strchr("?#@*!$ ",*str)==0)
+ return(1);
+ }
+ else if(c=='`')
+ return(0);
+ else if(c=='[' && !lit)
+ sub++;
+ else if(c==']' && !lit)
+ sub--;
+ else if(c=='\'')
+ lit = !lit;
+ }
+ return(0);
+}
+
+static Shnode_t *getanode(Lex_t *lp, struct argnod *ap)
+{
+ register Shnode_t *t = getnode(arithnod);
+ t->ar.artyp = TARITH;
+ t->ar.arline = sh_getlineno(lp);
+ t->ar.arexpr = ap;
+ if(ap->argflag&ARG_RAW)
+ t->ar.arcomp = sh_arithcomp(lp->sh,ap->argval);
+ else
+ {
+ if(sh_isoption(SH_NOEXEC) && (ap->argflag&ARG_MAC) && paramsub(ap->argval))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexwarnvar,lp->sh->inlineno);
+ t->ar.arcomp = 0;
+ }
+ return(t);
+}
+
+/*
+ * Make a node corresponding to a command list
+ */
+static Shnode_t *makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r)
+{
+ register Shnode_t *t;
+ if(!l || !r)
+ sh_syntax(lexp);
+ else
+ {
+ if((type&COMMSK) == TTST)
+ t = getnode(tstnod);
+ else
+ t = getnode(lstnod);
+ t->lst.lsttyp = type;
+ t->lst.lstlef = l;
+ t->lst.lstrit = r;
+ }
+ return(t);
+}
+
+/*
+ * entry to shell parser
+ * Flag can be the union of SH_EOF|SH_NL
+ */
+
+void *sh_parse(Shell_t *shp, Sfio_t *iop, int flag)
+{
+ register Shnode_t *t;
+ Lex_t *lexp = (Lex_t*)shp->lex_context;
+ Fcin_t sav_input;
+ struct argnod *sav_arg = lexp->arg;
+ int sav_prompt = shp->nextprompt;
+ if(shp->binscript && (sffileno(iop)==shp->infd || (flag&SH_FUNEVAL)))
+ return((void*)sh_trestore(shp,iop));
+ fcsave(&sav_input);
+ shp->st.staklist = 0;
+ lexp->noreserv = 0;
+ lexp->heredoc = 0;
+ lexp->inlineno = shp->inlineno;
+ lexp->firstline = shp->st.firstline;
+ shp->nextprompt = 1;
+ loop_level = 0;
+ label_list = label_last = 0;
+ if(sh_isoption(SH_INTERACTIVE))
+ sh_onstate(SH_INTERACTIVE);
+ if(sh_isoption(SH_VERBOSE))
+ sh_onstate(SH_VERBOSE);
+ sh_lexopen(lexp,shp,0);
+ if(fcfopen(iop) < 0)
+ return(NIL(void*));
+ if(fcfile())
+ {
+ char *cp = fcfirst();
+ if( cp[0]==CNTL('k') && cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0)
+ {
+ int version;
+ fcseek(4);
+ fcgetc(version);
+ fcclose();
+ fcrestore(&sav_input);
+ lexp->arg = sav_arg;
+ if(version > 3)
+ errormsg(SH_DICT,ERROR_exit(1),e_lexversion);
+ if(sffileno(iop)==shp->infd || (flag&SH_FUNEVAL))
+ shp->binscript = 1;
+ sfgetc(iop);
+ t = sh_trestore(shp,iop);
+ if(flag&SH_NL)
+ {
+ Shnode_t *tt;
+ while(1)
+ {
+ if(!(tt = sh_trestore(shp,iop)))
+ break;
+ t =makelist(lexp,TLST, t, tt);
+ }
+ }
+ return((void*)t);
+ }
+ }
+ flag &= ~SH_FUNEVAL;
+ if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0)
+ shp->inlineno=1;
+#if KSHELL
+ shp->nextprompt = 2;
+#endif
+ t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL));
+ fcclose();
+ fcrestore(&sav_input);
+ lexp->arg = sav_arg;
+ /* unstack any completed alias expansions */
+ if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1))
+ {
+ Sfio_t *sp = sfstack(iop,NULL);
+ if(sp)
+ sfclose(sp);
+ }
+ shp->nextprompt = sav_prompt;
+ if(flag&SH_NL)
+ {
+ shp->st.firstline = lexp->firstline;
+ shp->inlineno = lexp->inlineno;
+ }
+ stkseek(shp->stk,0);
+ return((void*)t);
+}
+
+/*
+ * This routine parses up the matching right parenthesis and returns
+ * the parse tree
+ */
+Shnode_t *sh_dolparen(Lex_t* lp)
+{
+ register Shnode_t *t=0;
+ Sfio_t *sp = fcfile();
+ int line = lp->sh->inlineno;
+ lp->sh->inlineno = error_info.line+lp->sh->st.firstline;
+ sh_lexopen(lp,lp->sh,1);
+ lp->comsub = 1;
+ switch(sh_lex(lp))
+ {
+ /* ((...)) arithmetic expression */
+ case EXPRSYM:
+ t = getanode(lp,lp->arg);
+ break;
+ case LPAREN:
+ t = sh_cmd(lp,RPAREN,SH_NL|SH_EMPTY);
+ break;
+ case LBRACE:
+ t = sh_cmd(lp,RBRACE,SH_NL|SH_EMPTY);
+ break;
+ }
+ lp->comsub = 0;
+ if(!sp && (sp=fcfile()))
+ {
+ /*
+ * This code handles the case where string has been converted
+ * to a file by an alias setup
+ */
+ register int c;
+ char *cp;
+ if(fcgetc(c) > 0)
+ fcseek(-1);
+ cp = fcseek(0);
+ fcclose();
+ fcsopen(cp);
+ sfclose(sp);
+ }
+ lp->sh->inlineno = line;
+ return(t);
+}
+
+/*
+ * remove temporary files and stacks
+ */
+
+void sh_freeup(Shell_t *shp)
+{
+ if(shp->st.staklist)
+ sh_funstaks(shp->st.staklist,-1);
+ shp->st.staklist = 0;
+}
+
+/*
+ * increase reference count for each stack in function list when flag>0
+ * decrease reference count for each stack in function list when flag<=0
+ * stack is freed when reference count is zero
+ */
+
+void sh_funstaks(register struct slnod *slp,int flag)
+{
+ register struct slnod *slpold;
+ while(slpold=slp)
+ {
+ if(slp->slchild)
+ sh_funstaks(slp->slchild,flag);
+ slp = slp->slnext;
+ if(flag<=0)
+ stakdelete(slpold->slptr);
+ else
+ staklink(slpold->slptr);
+ }
+}
+/*
+ * cmd
+ * empty
+ * list
+ * list & [ cmd ]
+ * list [ ; cmd ]
+ */
+
+static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag)
+{
+ register Shnode_t *left, *right;
+ register int type = FINT|FAMP;
+ if(sym==NL)
+ lexp->lasttok = 0;
+ left = list(lexp,flag);
+ if(lexp->token==NL)
+ {
+ if(flag&SH_NL)
+ lexp->token=';';
+ }
+ else if(!left && !(flag&SH_EMPTY))
+ sh_syntax(lexp);
+ switch(lexp->token)
+ {
+ case COOPSYM: /* set up a cooperating process */
+ type |= (FPIN|FPOU|FPCL|FCOOP);
+ /* FALL THRU */
+ case '&':
+ if(left)
+ {
+ /* (...)& -> {...;} & */
+ if(left->tre.tretyp==TPAR)
+ left = left->par.partre;
+ left = makeparent(lexp,TFORK|type, left);
+ }
+ /* FALL THRU */
+ case ';':
+ if(!left)
+ sh_syntax(lexp);
+ if(right=sh_cmd(lexp,sym,flag|SH_EMPTY))
+ left=makelist(lexp,TLST, left, right);
+ break;
+ case EOFSYM:
+ if(sym==NL)
+ break;
+ default:
+ if(sym && sym!=lexp->token)
+ {
+ if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM))
+ sh_syntax(lexp);
+ }
+ }
+ return(left);
+}
+
+/*
+ * list
+ * term
+ * list && term
+ * list || term
+ * unfortunately, these are equal precedence
+ */
+static Shnode_t *list(Lex_t *lexp, register int flag)
+{
+ register Shnode_t *t = term(lexp,flag);
+ register int token;
+ while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM))
+ t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI));
+ return(t);
+}
+
+/*
+ * term
+ * item
+ * item | term
+ */
+static Shnode_t *term(Lex_t *lexp,register int flag)
+{
+ register Shnode_t *t;
+ register int token;
+ if(flag&SH_NL)
+ token = skipnl(lexp,flag);
+ else
+ token = sh_lex(lexp);
+ /* check to see if pipeline is to be timed */
+ if(token==TIMESYM || token==NOTSYM)
+ {
+ t = getnode(parnod);
+ t->par.partyp=TTIME;
+ if(lexp->token==NOTSYM)
+ t->par.partyp |= COMSCAN;
+ t->par.partre = term(lexp,0);
+ }
+#if SHOPT_COSHELL
+ else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && (lexp->token=='|' || lexp->token==PIPESYM2))
+#else
+ else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|')
+#endif /* SHOPT_COSHELL */
+ {
+ register Shnode_t *tt;
+ int showme = t->tre.tretyp&FSHOWME;
+ t = makeparent(lexp,TFORK|FPOU,t);
+#if SHOPT_COSHELL
+ if(lexp->token==PIPESYM2)
+ t->tre.tretyp |= FALTPIPE;
+#endif /* SHOPT_COSHELL */
+ if(tt=term(lexp,SH_NL))
+ {
+ switch(tt->tre.tretyp&COMMSK)
+ {
+ case TFORK:
+ tt->tre.tretyp |= FPIN|FPCL;
+ break;
+ case TFIL:
+ tt->lst.lstlef->tre.tretyp |= FPIN|FPCL;
+ break;
+ default:
+ tt= makeparent(lexp,TSETIO|FPIN|FPCL,tt);
+ }
+ t=makelist(lexp,TFIL,t,tt);
+ t->tre.tretyp |= showme;
+ }
+ else if(lexp->token)
+ sh_syntax(lexp);
+ }
+ return(t);
+}
+
+/*
+ * case statement
+ */
+static struct regnod* syncase(Lex_t *lexp,register int esym)
+{
+ register int tok = skipnl(lexp,0);
+ register struct regnod *r;
+ if(tok==esym)
+ return(NIL(struct regnod*));
+ r = (struct regnod*)stakalloc(sizeof(struct regnod));
+ r->regptr=0;
+ r->regflag=0;
+ if(tok==LPAREN)
+ skipnl(lexp,0);
+ while(1)
+ {
+ if(!lexp->arg)
+ sh_syntax(lexp);
+ lexp->arg->argnxt.ap=r->regptr;
+ r->regptr = lexp->arg;
+ if((tok=sh_lex(lexp))==RPAREN)
+ break;
+ else if(tok=='|')
+ sh_lex(lexp);
+ else
+ sh_syntax(lexp);
+ }
+ r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI);
+ if((tok=lexp->token)==BREAKCASESYM)
+ r->regnxt=syncase(lexp,esym);
+ else if(tok==FALLTHRUSYM)
+ {
+ r->regflag++;
+ r->regnxt=syncase(lexp,esym);
+ }
+ else
+ {
+ if(tok!=esym && tok!=EOFSYM)
+ sh_syntax(lexp);
+ r->regnxt=0;
+ }
+ if(lexp->token==EOFSYM)
+ return(NIL(struct regnod*));
+ return(r);
+}
+
+/*
+ * This routine creates the parse tree for the arithmetic for
+ * When called, shlex.arg contains the string inside ((...))
+ * When the first argument is missing, a while node is returned
+ * Otherise a list containing an arithmetic command and a while
+ * is returned.
+ */
+static Shnode_t *arithfor(Lex_t *lexp,register Shnode_t *tf)
+{
+ register Shnode_t *t, *tw = tf;
+ register int offset;
+ register struct argnod *argp;
+ register int n;
+ Stk_t *stkp = lexp->sh->stk;
+ int argflag = lexp->arg->argflag;
+ /* save current input */
+ Fcin_t sav_input;
+ fcsave(&sav_input);
+ fcsopen(lexp->arg->argval);
+ /* split ((...)) into three expressions */
+ for(n=0; ; n++)
+ {
+ register int c;
+ argp = (struct argnod*)stkseek(stkp,ARGVAL);
+ argp->argnxt.ap = 0;
+ argp->argchn.cp = 0;
+ argp->argflag = argflag;
+ if(n==2)
+ break;
+ /* copy up to ; onto the stack */
+ sh_lexskip(lexp,';',1,ST_NESTED);
+ offset = stktell(stkp)-1;
+ if((c=fcpeek(-1))!=';')
+ break;
+ /* remove trailing white space */
+ while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c)))
+ offset--;
+ /* check for empty initialization expression */
+ if(offset==ARGVAL && n==0)
+ continue;
+ stkseek(stkp,offset);
+ /* check for empty condition and treat as while((1)) */
+ if(offset==ARGVAL)
+ sfputc(stkp,'1');
+ argp = (struct argnod*)stkfreeze(stkp,1);
+ t = getanode(lexp,argp);
+ if(n==0)
+ tf = makelist(lexp,TLST,t,tw);
+ else
+ tw->wh.whtre = t;
+ }
+ while((offset=fcpeek(0)) && isspace(offset))
+ fcseek(1);
+ stakputs(fcseek(0));
+ argp = (struct argnod*)stakfreeze(1);
+ fcrestore(&sav_input);
+ if(n<2)
+ {
+ lexp->token = RPAREN|SYMREP;
+ sh_syntax(lexp);
+ }
+ /* check whether the increment is present */
+ if(*argp->argval)
+ {
+ t = getanode(lexp,argp);
+ tw->wh.whinc = (struct arithnod*)t;
+ }
+ else
+ tw->wh.whinc = 0;
+ sh_lexopen(lexp, lexp->sh,1);
+ if((n=sh_lex(lexp))==NL)
+ n = skipnl(lexp,0);
+ else if(n==';')
+ n = sh_lex(lexp);
+ if(n!=DOSYM && n!=LBRACE)
+ sh_syntax(lexp);
+ tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
+ tw->wh.whtyp = TWH;
+ return(tf);
+
+}
+
+static Shnode_t *funct(Lex_t *lexp)
+{
+ Shell_t *shp = lexp->sh;
+ register Shnode_t *t;
+ register int flag;
+ struct slnod *volatile slp=0;
+ Stak_t *savstak;
+ Sfoff_t first, last;
+ struct functnod *volatile fp;
+ Sfio_t *iop;
+#if SHOPT_KIA
+ unsigned long current = lexp->current;
+#endif /* SHOPT_KIA */
+ int nargs=0,size=0,jmpval, saveloop=loop_level;
+ struct argnod *savelabel = label_last;
+ struct checkpt buff;
+ int save_optget = opt_get;
+ void *in_mktype = shp->mktype;
+ shp->mktype = 0;
+ opt_get = 0;
+ t = getnode(functnod);
+ t->funct.functline = shp->inlineno;
+ t->funct.functtyp=TFUN;
+ t->funct.functargs = 0;
+ if(!(flag = (lexp->token==FUNCTSYM)))
+ t->funct.functtyp |= FPOSIX;
+ else if(sh_lex(lexp))
+ sh_syntax(lexp);
+ if(!(iop=fcfile()))
+ {
+ iop = sfopen(NIL(Sfio_t*),fcseek(0),"s");
+ fcclose();
+ fcfopen(iop);
+ }
+ t->funct.functloc = first = fctell();
+ if(!shp->st.filename || sffileno(iop)<0)
+ {
+ if(fcfill() >= 0)
+ fcseek(-1);
+ if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
+ t->funct.functloc = sfseek(shp->gd->hist_ptr->histfp,(off_t)0,SEEK_CUR);
+ else
+ {
+ /* copy source to temporary file */
+ t->funct.functloc = 0;
+ if(lexp->sh->heredocs)
+ t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END);
+ else
+ lexp->sh->heredocs = sftmp(HERE_MEM);
+ lexp->sh->funlog = lexp->sh->heredocs;
+ t->funct.functtyp |= FPIN;
+ }
+ }
+ t->funct.functnam= (char*)lexp->arg->argval;
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,"");
+#endif /* SHOPT_KIA */
+ if(flag)
+ {
+ lexp->token = sh_lex(lexp);
+#if SHOPT_BASH
+ if(lexp->token == LPAREN)
+ {
+ if((lexp->token = sh_lex(lexp)) == RPAREN)
+ t->funct.functtyp |= FPOSIX;
+ else
+ sh_syntax(lexp);
+ }
+#endif
+ }
+ if(t->funct.functtyp&FPOSIX)
+ skipnl(lexp,0);
+ else
+ {
+ if(lexp->token==0)
+ {
+ struct comnod *ac;
+ char *cp, **argv, **argv0;
+ int c;
+ t->funct.functargs = ac = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*));
+ if(ac->comset || (ac->comtyp&COMSCAN))
+ errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
+ argv0 = argv = ((struct dolnod*)ac->comarg)->dolval+ARG_SPARE;
+ while(cp= *argv++)
+ {
+ size += strlen(cp)+1;
+ if((c = mbchar(cp)) && isaletter(c))
+ while(c=mbchar(cp), isaname(c));
+ }
+ if(c)
+ errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
+ nargs = argv-argv0;
+ size += sizeof(struct dolnod)+(nargs+ARG_SPARE)*sizeof(char*);
+ if(shp->shcomp && memcmp(".sh.math.",t->funct.functnam,9)==0)
+ {
+ Namval_t *np= nv_open(t->funct.functnam,shp->fun_tree,NV_ADD|NV_VARNAME);
+ np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
+ memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
+ np->nvalue.rp->argc = ((struct dolnod*)ac->comarg)->dolnum;
+ }
+ }
+ while(lexp->token==NL)
+ lexp->token = sh_lex(lexp);
+ }
+ if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM)
+ sh_syntax(lexp);
+ sh_pushcontext(shp,&buff,1);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval == 0)
+ {
+ /* create a new stak frame to compile the command */
+ savstak = stakcreate(STAK_SMALL);
+ savstak = stakinstall(savstak, 0);
+ slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod));
+ slp->slchild = 0;
+ slp->slnext = shp->st.staklist;
+ shp->st.staklist = 0;
+ t->funct.functstak = (struct slnod*)slp;
+ /*
+ * store the pathname of function definition file on stack
+ * in name field of fake for node
+ */
+ fp = (struct functnod*)(slp+1);
+ fp->functtyp = TFUN|FAMP;
+ fp->functnam = 0;
+ fp->functline = t->funct.functline;
+ if(shp->st.filename)
+ fp->functnam = stakcopy(shp->st.filename);
+ loop_level = 0;
+ label_last = label_list;
+ if(size)
+ {
+ struct dolnod *dp = (struct dolnod*)stakalloc(size);
+ char *cp, *sp, **argv, **old = ((struct dolnod*)t->funct.functargs->comarg)->dolval+1;
+ argv = ((char**)(dp->dolval))+1;
+ dp->dolnum = ((struct dolnod*)t->funct.functargs->comarg)->dolnum;
+ t->funct.functargs->comarg = (struct argnod*)dp;
+ for(cp=(char*)&argv[nargs]; sp= *old++; cp++)
+ {
+ *argv++ = cp;
+ cp = strcopy(cp,sp);
+ }
+ *argv = 0;
+ }
+ if(!flag && lexp->token==0)
+ {
+ /* copy current word token to current stak frame */
+ struct argnod *ap;
+ flag = ARGVAL + strlen(lexp->arg->argval);
+ ap = (struct argnod*)stakalloc(flag);
+ memcpy(ap,lexp->arg,flag);
+ lexp->arg = ap;
+ }
+ t->funct.functtre = item(lexp,SH_NOIO);
+ }
+ else if(shp->shcomp)
+ exit(1);
+ sh_popcontext(shp,&buff);
+ loop_level = saveloop;
+ label_last = savelabel;
+ /* restore the old stack */
+ if(slp)
+ {
+ slp->slptr = stakinstall(savstak,0);
+ slp->slchild = shp->st.staklist;
+ }
+#if SHOPT_KIA
+ lexp->current = current;
+#endif /* SHOPT_KIA */
+ if(jmpval)
+ {
+ if(slp && slp->slptr)
+ {
+ shp->st.staklist = slp->slnext;
+ stakdelete(slp->slptr);
+ }
+ siglongjmp(*shp->jmplist,jmpval);
+ }
+ shp->st.staklist = (struct slnod*)slp;
+ last = fctell();
+ fp->functline = (last-first);
+ fp->functtre = t;
+ shp->mktype = in_mktype;
+ if(lexp->sh->funlog)
+ {
+ if(fcfill()>0)
+ fcseek(-1);
+ lexp->sh->funlog = 0;
+ }
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,"");
+#endif /* SHOPT_KIA */
+ t->funct.functtyp |= opt_get;
+ opt_get = save_optget;
+ return(t);
+}
+
+/*
+ * Compound assignment
+ */
+static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int type)
+{
+ register int n;
+ register Shnode_t *t, **tp;
+ register struct comnod *ac;
+ Stk_t *stkp = lexp->sh->stk;
+ int array=0, index=0;
+ Namval_t *np;
+ n = strlen(ap->argval)-1;
+ if(ap->argval[n]!='=')
+ sh_syntax(lexp);
+ if(ap->argval[n-1]=='+')
+ {
+ ap->argval[n--]=0;
+ array = ARG_APPEND;
+ }
+ /* shift right */
+ while(n > 0)
+ {
+ ap->argval[n] = ap->argval[n-1];
+ n--;
+ }
+ *ap->argval=0;
+ t = getnode(fornod);
+ t->for_.fornam = (char*)(ap->argval+1);
+ t->for_.fortyp = sh_getlineno(lexp);
+ tp = &t->for_.fortre;
+ ap->argchn.ap = (struct argnod*)t;
+ ap->argflag &= ARG_QUOTED;
+ ap->argflag |= array;
+ lexp->assignok = SH_ASSIGN;
+ if(type==NV_ARRAY)
+ lexp->noreserv = 1;
+ else
+ lexp->aliasok = 1;
+ array= (type==NV_ARRAY)?SH_ARRAY:0;
+ if((n=skipnl(lexp,0))==RPAREN || n==LPAREN)
+ {
+ struct argnod *ar,*aq,**settail;
+ ac = (struct comnod*)getnode(comnod);
+ memset((void*)ac,0,sizeof(*ac));
+ comarray:
+ settail= &ac->comset;
+ ac->comline = sh_getlineno(lexp);
+ while(n==LPAREN)
+ {
+ ar = (struct argnod*)stkseek(stkp,ARGVAL);
+ ar->argflag= ARG_ASSIGN;
+ sfprintf(stkp,"[%d]=",index++);
+ if(aq=ac->comarg)
+ {
+ ac->comarg = aq->argnxt.ap;
+ sfprintf(stkp,"%s",aq->argval);
+ ar->argflag |= aq->argflag;
+ }
+ ar = (struct argnod*)stkfreeze(stkp,1);
+ ar->argnxt.ap = 0;
+ if(!aq)
+ ar = assign(lexp,ar,0);
+ ar->argflag |= ARG_MESSAGE;
+ *settail = ar;
+ settail = &(ar->argnxt.ap);
+ if(aq)
+ continue;
+ while((n = skipnl(lexp,0))==0)
+ {
+ ar = (struct argnod*)stkseek(stkp,ARGVAL);
+ ar->argflag= ARG_ASSIGN;
+ sfprintf(stkp,"[%d]=",index++);
+ stakputs(lexp->arg->argval);
+ ar = (struct argnod*)stkfreeze(stkp,1);
+ ar->argnxt.ap = 0;
+ ar->argflag = lexp->arg->argflag;
+ *settail = ar;
+ settail = &(ar->argnxt.ap);
+ }
+ }
+ }
+ else if(n && n!=FUNCTSYM)
+ sh_syntax(lexp);
+ else if(type!=NV_ARRAY && n!=FUNCTSYM && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)|| np==SYSDOT)))
+ {
+ array=SH_ARRAY;
+ if(fcgetc(n)==LPAREN)
+ {
+ int c;
+ if(fcgetc(c)==RPAREN)
+ {
+ lexp->token = SYMRES;
+ array = 0;
+ }
+ else
+ fcseek(-2);
+ }
+ else if(n>0)
+ fcseek(-1);
+ if(array && type==NV_TYPE)
+ {
+ struct argnod *arg = lexp->arg;
+ n = lexp->token;
+ if(path_search(lexp->sh,lexp->arg->argval,NIL(Pathcomp_t**),1) && (np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && nv_isattr(np,BLT_DCL))
+ {
+ lexp->token = n;
+ lexp->arg = arg;
+ array = 0;
+ }
+ else
+ sh_syntax(lexp);
+ }
+ }
+ lexp->noreserv = 0;
+ while(1)
+ {
+ if((n=lexp->token)==RPAREN)
+ break;
+ if(n==FUNCTSYM || n==SYMRES)
+ ac = (struct comnod*)funct(lexp);
+ else
+ ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|array,NIL(struct ionod*));
+ if((n=lexp->token)==RPAREN)
+ break;
+ if(n!=NL && n!=';')
+ {
+ if(array && n==LPAREN)
+ goto comarray;
+ sh_syntax(lexp);
+ }
+ lexp->assignok = SH_ASSIGN;
+ if((n=skipnl(lexp,0)) || array)
+ {
+ if(n==RPAREN)
+ break;
+ if(array || n!=FUNCTSYM)
+ sh_syntax(lexp);
+ }
+ if((n!=FUNCTSYM) && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)||np==SYSDOT)))
+ {
+ struct argnod *arg = lexp->arg;
+ if(n!=0)
+ sh_syntax(lexp);
+ /* check for sys5 style function */
+ if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN)
+ {
+ lexp->arg = arg;
+ lexp->token = 0;
+ sh_syntax(lexp);
+ }
+ lexp->arg = arg;
+ lexp->token = SYMRES;
+ }
+ t = makelist(lexp,TLST,(Shnode_t*)ac,t);
+ *tp = t;
+ tp = &t->lst.lstrit;
+ }
+ *tp = (Shnode_t*)ac;
+ lexp->assignok = 0;
+ return(ap);
+}
+
+/*
+ * item
+ *
+ * ( cmd ) [ < in ] [ > out ]
+ * word word* [ < in ] [ > out ]
+ * if ... then ... else ... fi
+ * for ... while ... do ... done
+ * case ... in ... esac
+ * begin ... end
+ */
+
+static Shnode_t *item(Lex_t *lexp,int flag)
+{
+ register Shnode_t *t;
+ register struct ionod *io;
+ register int tok = (lexp->token&0xff);
+ int savwdval = lexp->lasttok;
+ int savline = lexp->lastline;
+ int showme=0, comsub;
+ if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME))
+ io=inout(lexp,NIL(struct ionod*),1);
+ else
+ io=0;
+ if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM)
+ {
+ lexp->lastline = sh_getlineno(lexp);
+ lexp->lasttok = lexp->token;
+ }
+ switch(tok)
+ {
+ /* [[ ... ]] test expression */
+ case BTESTSYM:
+ t = test_expr(lexp,ETESTSYM);
+ t->tre.tretyp &= ~TTEST;
+ break;
+ /* ((...)) arithmetic expression */
+ case EXPRSYM:
+ t = getanode(lexp,lexp->arg);
+ sh_lex(lexp);
+ goto done;
+
+ /* case statement */
+ case CASESYM:
+ {
+ int savetok = lexp->lasttok;
+ int saveline = lexp->lastline;
+ t = getnode(swnod);
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+ t->sw.swarg=lexp->arg;
+ t->sw.swtyp=TSW;
+ t->sw.swio = 0;
+ t->sw.swtyp |= FLINENO;
+ t->sw.swline = lexp->sh->inlineno;
+ if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE)
+ sh_syntax(lexp);
+ if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM)
+ {
+ lexp->lasttok = savetok;
+ lexp->lastline = saveline;
+ sh_syntax(lexp);
+ }
+ break;
+ }
+
+ /* if statement */
+ case IFSYM:
+ {
+ register Shnode_t *tt;
+ t = getnode(ifnod);
+ t->if_.iftyp=TIF;
+ t->if_.iftre=sh_cmd(lexp,THENSYM,SH_NL);
+ t->if_.thtre=sh_cmd(lexp,ELSESYM,SH_NL|SH_SEMI);
+ tok = lexp->token;
+ t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI):
+ (tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0));
+ if(tok==ELIFSYM)
+ {
+ if(!tt || tt->tre.tretyp!=TSETIO)
+ goto done;
+ t->if_.eltre = tt->fork.forktre;
+ tt->fork.forktre = t;
+ t = tt;
+ goto done;
+ }
+ break;
+ }
+
+ /* for and select statement */
+ case FORSYM:
+ case SELECTSYM:
+ {
+ t = getnode(fornod);
+ t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT);
+ t->for_.forlst=0;
+ t->for_.forline = lexp->sh->inlineno;
+ if(sh_lex(lexp))
+ {
+ if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR)
+ sh_syntax(lexp);
+ /* arithmetic for */
+ t = arithfor(lexp,t);
+ break;
+ }
+ t->for_.fornam=(char*) lexp->arg->argval;
+ t->for_.fortyp |= FLINENO;
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*));
+#endif /* SHOPT_KIA */
+ while((tok=sh_lex(lexp))==NL);
+ if(tok==INSYM)
+ {
+ if(sh_lex(lexp))
+ {
+ if(lexp->token != NL && lexp->token !=';')
+ sh_syntax(lexp);
+ /* some Linux scripts assume this */
+ if(sh_isoption(SH_NOEXEC))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n'));
+ t->for_.forlst = (struct comnod*)getnode(comnod);
+ (t->for_.forlst)->comarg = 0;
+ (t->for_.forlst)->comset = 0;
+ (t->for_.forlst)->comnamp = 0;
+ (t->for_.forlst)->comnamq = 0;
+ (t->for_.forlst)->comstate = 0;
+ (t->for_.forlst)->comio = 0;
+ (t->for_.forlst)->comtyp = 0;
+ }
+ else
+ t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*));
+ if(lexp->token != NL && lexp->token !=';')
+ sh_syntax(lexp);
+ tok = skipnl(lexp,0);
+ }
+ /* 'for i;do cmd' is valid syntax */
+ else if(tok==';')
+ tok=sh_lex(lexp);
+ if(tok!=DOSYM && tok!=LBRACE)
+ sh_syntax(lexp);
+ loop_level++;
+ t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
+ if(--loop_level==0)
+ label_last = label_list;
+ break;
+ }
+
+ /* This is the code for parsing function definitions */
+ case FUNCTSYM:
+ return(funct(lexp));
+
+#if SHOPT_NAMESPACE
+ case NSPACESYM:
+ t = getnode(fornod);
+ t->for_.fortyp=TNSPACE;
+ t->for_.forlst=0;
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+ t->for_.fornam=(char*) lexp->arg->argval;
+ while((tok=sh_lex(lexp))==NL);
+ if(tok!=LBRACE)
+ sh_syntax(lexp);
+ t->for_.fortre = sh_cmd(lexp,RBRACE,SH_NL);
+ break;
+#endif /* SHOPT_NAMESPACE */
+
+ /* while and until */
+ case WHILESYM:
+ case UNTILSYM:
+ t = getnode(whnod);
+ t->wh.whtyp=(lexp->token==WHILESYM ? TWH : TUN);
+ loop_level++;
+ t->wh.whtre = sh_cmd(lexp,DOSYM,SH_NL);
+ t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI);
+ if(--loop_level==0)
+ label_last = label_list;
+ t->wh.whinc = 0;
+ break;
+
+ case LABLSYM:
+ {
+ register struct argnod *argp = label_list;
+ while(argp)
+ {
+ if(strcmp(argp->argval,lexp->arg->argval)==0)
+ errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval);
+ argp = argp->argnxt.ap;
+ }
+ lexp->arg->argnxt.ap = label_list;
+ label_list = lexp->arg;
+ label_list->argchn.len = sh_getlineno(lexp);
+ label_list->argflag = loop_level;
+ skipnl(lexp,flag);
+ if(!(t = item(lexp,SH_NL)))
+ sh_syntax(lexp);
+ tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1));
+ if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval);
+ return(t);
+ }
+
+ /* command group with {...} */
+ case LBRACE:
+ comsub = lexp->comsub;
+ lexp->comsub = 0;
+ t = sh_cmd(lexp,RBRACE,SH_NL|SH_SEMI);
+ lexp->comsub = comsub;
+ break;
+
+ case LPAREN:
+ t = getnode(parnod);
+ t->par.partre=sh_cmd(lexp,RPAREN,SH_NL|SH_SEMI);
+ t->par.partyp=TPAR;
+ break;
+
+#if SHOPT_COSHELL
+ case '&':
+ if(tok=sh_lex(lexp))
+ {
+ if(tok!=NL)
+ sh_syntax(lexp);
+ t = getnode(comnod);
+ memset(t,0,sizeof(struct comnod));
+ t->com.comline = sh_getlineno(lexp);
+ }
+ else
+ t = (Shnode_t*)simple(lexp,SH_NOIO,NIL(struct ionod*));
+ t->com.comtyp |= FAMP;
+ if(lexp->token=='&' || lexp->token=='|')
+ sh_syntax(lexp);
+ return(t);
+ break;
+#endif /* SHOPT_COSHELL */
+ default:
+ if(io==0)
+ return(0);
+
+ case ';':
+ if(io==0)
+ {
+ if(!(flag&SH_SEMI))
+ return(0);
+ if(sh_lex(lexp)==';')
+ sh_syntax(lexp);
+ showme = FSHOWME;
+ }
+ /* simple command */
+ case 0:
+ t = (Shnode_t*)simple(lexp,flag,io);
+ if(t->com.comarg && lexp->intypeset)
+ check_typedef(&t->com);
+ lexp->intypeset = 0;
+ lexp->inexec = 0;
+ t->tre.tretyp |= showme;
+ return(t);
+ }
+ sh_lex(lexp);
+ if(io=inout(lexp,io,0))
+ {
+ if((tok=t->tre.tretyp&COMMSK) != TFORK)
+ tok = TSETIO;
+ t=makeparent(lexp,tok,t);
+ t->tre.treio=io;
+ }
+done:
+ lexp->lasttok = savwdval;
+ lexp->lastline = savline;
+ return(t);
+}
+
+static struct argnod *process_sub(Lex_t *lexp,int tok)
+{
+ struct argnod *argp;
+ Shnode_t *t;
+ int mode = (tok==OPROCSYM);
+ t = sh_cmd(lexp,RPAREN,SH_NL);
+ argp = (struct argnod*)stkalloc(lexp->sh->stk,sizeof(struct argnod));
+ *argp->argval = 0;
+ argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t);
+ argp->argflag = (ARG_EXP|mode);
+ return(argp);
+}
+
+
+/*
+ * This is for a simple command, for list, or compound assignment
+ */
+static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
+{
+ register struct comnod *t;
+ register struct argnod *argp;
+ register int tok;
+ Stk_t *stkp = lexp->sh->stk;
+ struct argnod **argtail;
+ struct argnod **settail;
+ int cmdarg=0;
+ int argno = 0;
+ int assignment = 0;
+ int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD));
+ int associative=0;
+ if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[')
+ {
+ flag |= SH_ARRAY;
+ associative = 1;
+ }
+ t = (struct comnod*)getnode(comnod);
+ t->comio=io; /*initial io chain*/
+ /* set command line number for error messages */
+ t->comline = sh_getlineno(lexp);
+ argtail = &(t->comarg);
+ t->comset = 0;
+ t->comnamp = 0;
+ t->comnamq = 0;
+ t->comstate = 0;
+ settail = &(t->comset);
+ while(lexp->token==0)
+ {
+ argp = lexp->arg;
+ if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0)
+ {
+ lexp->token = LBRACE;
+ break;
+ }
+ if(associative && argp->argval[0]!='[')
+ sh_syntax(lexp);
+ /* check for assignment argument */
+ if((argp->argflag&ARG_ASSIGN) && assignment!=2)
+ {
+ *settail = argp;
+ settail = &(argp->argnxt.ap);
+ lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1;
+ if(assignment)
+ {
+ struct argnod *ap=argp;
+ char *last, *cp;
+ if(assignment==1)
+ {
+ last = strchr(argp->argval,'=');
+ if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last) && cp[-1]!='.')
+ last = cp;
+ stkseek(stkp,ARGVAL);
+ sfwrite(stkp,argp->argval,last-argp->argval);
+ ap=(struct argnod*)stkfreeze(stkp,1);
+ ap->argflag = ARG_RAW;
+ ap->argchn.ap = 0;
+ }
+ *argtail = ap;
+ argtail = &(ap->argnxt.ap);
+ if(argno>=0)
+ argno++;
+ }
+ else /* alias substitutions allowed */
+ lexp->aliasok = 1;
+ }
+ else
+ {
+ if(!(argp->argflag&ARG_RAW))
+ argno = -1;
+ if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/')
+ {
+ /* check for builtin command */
+ Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0);
+ if(cmdarg==0)
+ t->comnamp = (void*)np;
+ if(np && is_abuiltin(np))
+ {
+ if(nv_isattr(np,BLT_DCL))
+ {
+ assignment = 1+(*argp->argval=='a');
+ if(np==SYSTYPESET)
+ lexp->intypeset = 1;
+ key_on = 1;
+ }
+ else if(np==SYSCOMMAND)
+ cmdarg++;
+ else if(np==SYSEXEC)
+ lexp->inexec = 1;
+ else if(np->nvalue.bfp==(Nambfp_f)b_getopts)
+ opt_get |= FOPTGET;
+ }
+ }
+ *argtail = argp;
+ argtail = &(argp->argnxt.ap);
+ if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC))
+ lexp->assignok = SH_COMPASSIGN;
+ lexp->aliasok = 0;
+ }
+ retry:
+ tok = sh_lex(lexp);
+ if(tok==LABLSYM && (flag&SH_ASSIGN))
+ lexp->token = tok = 0;
+ if((tok==IPROCSYM || tok==OPROCSYM))
+ {
+ argp = process_sub(lexp,tok);
+ argno = -1;
+ *argtail = argp;
+ argtail = &(argp->argnxt.ap);
+ goto retry;
+ }
+ if(tok==LPAREN)
+ {
+ if(argp->argflag&ARG_ASSIGN)
+ {
+ int intypeset = lexp->intypeset;
+ int type = 0;
+ lexp->intypeset = 0;
+ if(t->comnamp==SYSTYPESET)
+ {
+ struct argnod *ap;
+ for(ap=t->comarg->argnxt.ap;ap;ap=ap->argnxt.ap)
+ {
+ if(*ap->argval!='-')
+ break;
+ if(strchr(ap->argval,'T'))
+ type = NV_TYPE;
+ else if(strchr(ap->argval,'a'))
+ type = NV_ARRAY;
+ else
+ continue;
+ break;
+ }
+ }
+ argp = assign(lexp,argp,type);
+ lexp->intypeset = intypeset;
+ if(associative)
+ lexp->assignok |= SH_ASSIGN;
+ goto retry;
+ }
+ else if(argno==1 && !t->comset)
+ {
+ /* SVR2 style function */
+ if(!(flag&SH_ARRAY) && sh_lex(lexp) == RPAREN)
+ {
+ lexp->arg = argp;
+ return(funct(lexp));
+ }
+ lexp->token = LPAREN;
+ }
+ }
+ else if(flag&SH_ASSIGN)
+ {
+ if(tok==RPAREN)
+ break;
+ else if(tok==NL && (flag&SH_ARRAY))
+ {
+ lexp->comp_assign = 2;
+ goto retry;
+ }
+
+ }
+ if(!(flag&SH_NOIO))
+ {
+ if(io)
+ {
+ while(io->ionxt)
+ io = io->ionxt;
+ io->ionxt = inout(lexp,(struct ionod*)0,0);
+ }
+ else
+ t->comio = io = inout(lexp,(struct ionod*)0,0);
+ }
+ }
+ *argtail = 0;
+ t->comtyp = TCOM;
+#if SHOPT_KIA
+ if(lexp->kiafile && !(flag&SH_NOIO))
+ {
+ register Namval_t *np=(Namval_t*)t->comnamp;
+ unsigned long r=0;
+ int line = t->comline;
+ argp = t->comarg;
+ if(np)
+ r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,"");
+ else if(argp)
+ r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,"");
+ if(r>0)
+ sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line);
+ if(t->comset && argno==0)
+ writedefs(lexp,t->comset,line,'v',t->comarg);
+ else if(np && nv_isattr(np,BLT_DCL))
+ writedefs(lexp,argp,line,0,NIL(struct argnod*));
+ else if(argp && strcmp(argp->argval,"read")==0)
+ writedefs(lexp,argp,line,0,NIL(struct argnod*));
+#if 0
+ else if(argp && strcmp(argp->argval,"unset")==0)
+ writedefs(lexp,argp,line,'u',NIL(struct argnod*));
+#endif
+ else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap))
+ {
+ r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line);
+ }
+ }
+#endif /* SHOPT_KIA */
+ if(t->comnamp && (argp=t->comarg->argnxt.ap))
+ {
+ Namval_t *np=(Namval_t*)t->comnamp;
+ if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval))
+ {
+ register char *cp = argp->argval;
+ /* convert break/continue labels to numbers */
+ tok = 0;
+ for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap)
+ {
+ if(strcmp(cp,argp->argval))
+ continue;
+ tok = loop_level-argp->argflag;
+ if(tok>=1)
+ {
+ argp = t->comarg->argnxt.ap;
+ if(tok>9)
+ {
+ argp->argval[1] = '0'+tok%10;
+ argp->argval[2] = 0;
+ tok /= 10;
+ }
+ else
+ argp->argval[1] = 0;
+ *argp->argval = '0'+tok;
+ }
+ break;
+ }
+ if(sh_isoption(SH_NOEXEC) && tok==0)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp);
+ }
+ else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') &&
+ (argp->argval[1]==0||strchr(argp->argval,'k')))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval);
+ }
+ /* expand argument list if possible */
+ if(argno>0 && !(flag&SH_ARRAY))
+ t->comarg = qscan(t,argno);
+ else if(t->comarg)
+ t->comtyp |= COMSCAN;
+ lexp->aliasok = 0;
+ return((Shnode_t*)t);
+}
+
+/*
+ * skip past newlines but issue prompt if interactive
+ */
+static int skipnl(Lex_t *lexp,int flag)
+{
+ register int token;
+ while((token=sh_lex(lexp))==NL);
+ if(token==';' && !(flag&SH_SEMI))
+ sh_syntax(lexp);
+ return(token);
+}
+
+/*
+ * check for and process and i/o redirections
+ * if flag>0 then an alias can be in the next word
+ * if flag<0 only one redirection will be processed
+ */
+static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag)
+{
+ register int iof = lexp->digits, token=lexp->token;
+ register struct ionod *iop;
+ Stk_t *stkp = lexp->sh->stk;
+ char *iovname=0;
+ register int errout=0;
+ if(token==IOVNAME)
+ {
+ iovname=lexp->arg->argval+1;
+ token= sh_lex(lexp);
+ iof = 0;
+ }
+ switch(token&0xff)
+ {
+ case '<':
+ if(token==IODOCSYM)
+ iof |= (IODOC|IORAW);
+ else if(token==IOMOV0SYM)
+ iof |= IOMOV;
+ else if(token==IORDWRSYMT)
+ iof |= IORDW|IOREWRITE;
+ else if(token==IORDWRSYM)
+ iof |= IORDW;
+ else if((token&SYMSHARP) == SYMSHARP)
+ {
+ int n;
+ iof |= IOLSEEK;
+ if(fcgetc(n)=='#')
+ iof |= IOCOPY;
+ else if(n>0)
+ fcseek(-1);
+ }
+ break;
+
+ case '>':
+ if(iof<0)
+ {
+ errout = 1;
+ iof = 1;
+ }
+ iof |= IOPUT;
+ if(token==IOAPPSYM)
+ iof |= IOAPP;
+ else if(token==IOMOV1SYM)
+ iof |= IOMOV;
+ else if(token==IOCLOBSYM)
+ iof |= IOCLOB;
+ else if((token&SYMSHARP) == SYMSHARP)
+ iof |= IOLSEEK;
+ else if((token&SYMSEMI) == SYMSEMI)
+ iof |= IOREWRITE;
+ break;
+
+ default:
+ return(lastio);
+ }
+ lexp->digits=0;
+ iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod));
+ iop->iodelim = 0;
+ if(token=sh_lex(lexp))
+ {
+ if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub)
+ {
+ lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3);
+ strcpy(lexp->arg->argval,"CUR");
+ lexp->arg->argflag = ARG_RAW;
+ iof |= IOARITH;
+ fcseek(-1);
+ }
+ else if(token==EXPRSYM && (iof&IOLSEEK))
+ iof |= IOARITH;
+ else if(((token==IPROCSYM && !(iof&IOPUT)) || (token==OPROCSYM && (iof&IOPUT))) && !(iof&(IOLSEEK|IOREWRITE|IOMOV|IODOC)))
+ {
+ lexp->arg = process_sub(lexp,token);
+ iof |= IOPROCSUB;
+ }
+ else
+ sh_syntax(lexp);
+ }
+ if( (iof&IOPROCSUB) && !(iof&IOLSEEK))
+ iop->ioname= (char*)lexp->arg->argchn.ap;
+ else
+ iop->ioname=lexp->arg->argval;
+ iop->iovname = iovname;
+ if(iof&IODOC)
+ {
+ if(lexp->digits==2)
+ {
+ iof |= IOSTRG;
+ if(!(lexp->arg->argflag&ARG_RAW))
+ iof &= ~IORAW;
+ }
+ else
+ {
+ if(!lexp->sh->heredocs)
+ lexp->sh->heredocs = sftmp(HERE_MEM);
+ iop->iolst=lexp->heredoc;
+ lexp->heredoc=iop;
+ if(lexp->arg->argflag&ARG_QUOTED)
+ iof |= IOQUOTE;
+ if(lexp->digits==3)
+ iof |= IOLSEEK;
+ if(lexp->digits)
+ iof |= IOSTRIP;
+ }
+ }
+ else
+ {
+ iop->iolst = 0;
+ if(lexp->arg->argflag&ARG_RAW)
+ iof |= IORAW;
+ }
+ iop->iofile=iof;
+ if(flag>0)
+ /* allow alias substitutions and parameter assignments */
+ lexp->aliasok = lexp->assignok = 1;
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ {
+ int n = lexp->sh->inlineno-(lexp->token=='\n');
+ if(!(iof&IOMOV))
+ {
+ unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;%c;%d\n",lexp->current,r,n,n,(iof&IOPUT)?((iof&IOAPP)?'a':'w'):((iof&IODOC)?'h':'r'),iof&IOUFD);
+ }
+ }
+#endif /* SHOPT_KIA */
+ if(flag>=0)
+ {
+ struct ionod *ioq=iop;
+ sh_lex(lexp);
+ if(errout)
+ {
+ /* redirect standard output to standard error */
+ ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod));
+ memset(ioq,0,sizeof(*ioq));
+ ioq->ioname = "1";
+ ioq->iolst = 0;
+ ioq->iodelim = 0;
+ ioq->iofile = IORAW|IOPUT|IOMOV|2;
+ iop->ionxt=ioq;
+ }
+ ioq->ionxt=inout(lexp,lastio,flag);
+ }
+ else
+ iop->ionxt=0;
+ return(iop);
+}
+
+/*
+ * convert argument chain to argument list when no special arguments
+ */
+
+static struct argnod *qscan(struct comnod *ac,int argn)
+{
+ register char **cp;
+ register struct argnod *ap;
+ register struct dolnod* dp;
+ register int special=0;
+ /* special hack for test -t compatibility */
+ if((Namval_t*)ac->comnamp==SYSTEST)
+ special = 2;
+ else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0)
+ special = 3;
+ if(special)
+ {
+ ap = ac->comarg->argnxt.ap;
+ if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!')
+ ap = ap->argnxt.ap;
+ else if(argn!=special)
+ special=0;
+ }
+ if(special)
+ {
+ const char *message;
+ if(strcmp(ap->argval,"-t"))
+ {
+ message = "line %d: Invariant test";
+ special=0;
+ }
+ else
+ {
+ message = "line %d: -t requires argument";
+ argn++;
+ }
+ if(sh_isoption(SH_NOEXEC))
+ errormsg(SH_DICT,ERROR_warn(0),message,ac->comline);
+ }
+ /* leave space for an extra argument at the front */
+ dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
+ cp = dp->dolval+ARG_SPARE;
+ dp->dolnum = argn;
+ dp->dolbot = ARG_SPARE;
+ ap = ac->comarg;
+ while(ap)
+ {
+ *cp++ = ap->argval;
+ ap = ap->argnxt.ap;
+ }
+ if(special==3)
+ {
+ cp[0] = cp[-1];
+ cp[-1] = "1";
+ cp++;
+ }
+ else if(special)
+ *cp++ = "1";
+ *cp = 0;
+ return((struct argnod*)dp);
+}
+
+static Shnode_t *test_expr(Lex_t *lp,int sym)
+{
+ register Shnode_t *t = test_or(lp);
+ if(lp->token!=sym)
+ sh_syntax(lp);
+ return(t);
+}
+
+static Shnode_t *test_or(Lex_t *lp)
+{
+ register Shnode_t *t = test_and(lp);
+ while(lp->token==ORFSYM)
+ t = makelist(lp,TORF|TTEST,t,test_and(lp));
+ return(t);
+}
+
+static Shnode_t *test_and(Lex_t *lp)
+{
+ register Shnode_t *t = test_primary(lp);
+ while(lp->token==ANDFSYM)
+ t = makelist(lp,TAND|TTEST,t,test_primary(lp));
+ return(t);
+}
+
+/*
+ * convert =~ into == ~(E)
+ */
+static void ere_match(void)
+{
+ Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s");
+ register int c;
+ while( fcgetc(c),(c==' ' || c=='\t'));
+ if(c)
+ fcseek(-1);
+ if(!(base=fcfile()))
+ base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
+ fcclose();
+ sfstack(base,iop);
+ fcfopen(base);
+}
+
+static Shnode_t *test_primary(Lex_t *lexp)
+{
+ register struct argnod *arg;
+ register Shnode_t *t;
+ register int num,token;
+ token = skipnl(lexp,0);
+ num = lexp->digits;
+ switch(token)
+ {
+ case '(':
+ t = test_expr(lexp,')');
+ t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno));
+ break;
+ case '!':
+ if(!(t = test_primary(lexp)))
+ sh_syntax(lexp);
+ t->tre.tretyp |= TNEGATE;
+ return(t);
+ case TESTUNOP:
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+#if SHOPT_KIA
+ if(lexp->kiafile && !strchr("sntzoOG",num))
+ {
+ int line = lexp->sh->inlineno- (lexp->token==NL);
+ unsigned long r;
+ r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
+ }
+#endif /* SHOPT_KIA */
+ t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT),
+ (Shnode_t*)lexp->arg,(Shnode_t*)lexp->arg);
+ t->tst.tstline = lexp->sh->inlineno;
+ break;
+ /* binary test operators */
+ case 0:
+ arg = lexp->arg;
+ if((token=sh_lex(lexp))==TESTBINOP)
+ {
+ num = lexp->digits;
+ if(num==TEST_REP)
+ {
+ ere_match();
+ num = TEST_PEQ;
+ }
+ }
+ else if(token=='<')
+ num = TEST_SLT;
+ else if(token=='>')
+ num = TEST_SGT;
+ else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN)
+ {
+ t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT),
+ (Shnode_t*)arg,(Shnode_t*)arg);
+ t->tst.tstline = lexp->sh->inlineno;
+ return(t);
+ }
+ else
+ sh_syntax(lexp);
+#if SHOPT_KIA
+ if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
+ {
+ int line = lexp->sh->inlineno- (lexp->token==NL);
+ unsigned long r;
+ r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
+ }
+#endif /* SHOPT_KIA */
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+ if(num&TEST_PATTERN)
+ {
+ if(lexp->arg->argflag&(ARG_EXP|ARG_MAC))
+ num &= ~TEST_PATTERN;
+ }
+ t = getnode(tstnod);
+ t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT);
+ t->lst.lstlef = (Shnode_t*)arg;
+ t->lst.lstrit = (Shnode_t*)lexp->arg;
+ t->tst.tstline = lexp->sh->inlineno;
+#if SHOPT_KIA
+ if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
+ {
+ int line = lexp->sh->inlineno-(lexp->token==NL);
+ unsigned long r;
+ r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
+ }
+#endif /* SHOPT_KIA */
+ break;
+ default:
+ return(0);
+ }
+ skipnl(lexp,0);
+ return(t);
+}
+
+#if SHOPT_KIA
+/*
+ * return an entity checksum
+ * The entity is created if it doesn't exist
+ */
+unsigned long kiaentity(Lex_t *lexp,const char *name,int len,int type,int first,int last,unsigned long parent, int pkind, int width, const char *attr)
+{
+ Stk_t *stkp = lexp->sh->stk;
+ Namval_t *np;
+ long offset = stktell(stkp);
+ sfputc(stkp,type);
+ if(len>0)
+ sfwrite(stkp,name,len);
+ else
+ {
+ if(type=='p')
+ sfputr(stkp,path_basename(name),0);
+ else
+ sfputr(stkp,name,0);
+ }
+ np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD);
+ stkseek(stkp,offset);
+ np->nvalue.i = pkind;
+ nv_setsize(np,width);
+ if(!nv_isattr(np,NV_TAGGED) && first>=0)
+ {
+ nv_onattr(np,NV_TAGGED);
+ if(!pkind)
+ pkind = '0';
+ if(len>0)
+ sfprintf(lexp->kiafile,"%..64d;%c;%.*s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,len,name,first,last,parent,lexp->fscript,pkind,width,attr);
+ else
+ sfprintf(lexp->kiafile,"%..64d;%c;%s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,name,first,last,parent,lexp->fscript,pkind,width,attr);
+ }
+ return(np->hash);
+}
+
+static void kia_add(register Namval_t *np, void *data)
+{
+ char *name = nv_name(np);
+ Lex_t *lp = (Lex_t*)data;
+ NOT_USED(data);
+ kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),"");
+}
+
+int kiaclose(Lex_t *lexp)
+{
+ register off_t off1,off2;
+ register int n;
+ if(lexp->kiafile)
+ {
+ unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,"");
+ kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,"");
+ kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,"");
+ nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0);
+ off1 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
+ sfseek(lexp->kiatmp,(off_t)0,SEEK_SET);
+ sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1);
+ off2 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
+#ifdef SF_BUFCONST
+ if(off2==off1)
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin));
+ else
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nRELATIONSHIP;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin),(Sflong_t)off1,(size_t)(off2-off1));
+ if(off2 >= INT_MAX)
+ off2 = -(n+12);
+ sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12);
+#else
+ if(off2==off1)
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin);
+ else
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1);
+ sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12);
+#endif
+ }
+ return(sfclose(lexp->kiafile));
+}
+#endif /* SHOPT_KIA */
diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c
new file mode 100644
index 0000000..28d61ae
--- /dev/null
+++ b/src/cmd/ksh93/sh/path.c
@@ -0,0 +1,1824 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include <ls.h>
+#include <nval.h>
+#include "variables.h"
+#include "path.h"
+#include "io.h"
+#include "jobs.h"
+#include "history.h"
+#include "test.h"
+#include "FEATURE/dynamic"
+#include "FEATURE/externs"
+#if SHOPT_PFSH
+# ifdef _hdr_exec_attr
+# include <exec_attr.h>
+# endif
+# if _lib_vfork
+# include <ast_vfork.h>
+# else
+# define vfork() fork()
+# endif
+#endif
+
+#define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
+#define LIBCMD "cmd"
+
+
+static int canexecute(Shell_t*,char*,int);
+static void funload(Shell_t*,int,const char*);
+static void exscript(Shell_t*,char*, char*[], char**);
+static int path_chkpaths(Shell_t*,Pathcomp_t*,Pathcomp_t*,Pathcomp_t*,int);
+static void path_checkdup(Shell_t *shp,register Pathcomp_t*);
+
+static const char *std_path;
+
+static int onstdpath(const char *name)
+{
+ register const char *cp = std_path, *sp;
+ if(cp)
+ while(*cp)
+ {
+ for(sp=name; *sp && (*cp == *sp); sp++,cp++);
+ if(*sp==0 && (*cp==0 || *cp==':'))
+ return(1);
+ while(*cp && *cp++!=':');
+ }
+ return(0);
+}
+
+#if SHOPT_PFSH
+int path_xattr(Shell_t *shp, const char *path, char *rpath)
+{
+ char resolvedpath[PATH_MAX + 1];
+ if (shp->gd->user && *shp->gd->user)
+ {
+ execattr_t *pf;
+ if(!rpath)
+ rpath = resolvedpath;
+ if (!realpath(path, resolvedpath))
+ return -1;
+ if(pf=getexecuser(shp->gd->user, KV_COMMAND, resolvedpath, GET_ONE))
+ {
+ if (!pf->attr || pf->attr->length == 0)
+ {
+ free_execattr(pf);
+ return(0);
+ }
+ free_execattr(pf);
+ return(1);
+ }
+ }
+ errno = ENOENT;
+ return(-1);
+}
+#endif /* SHOPT_PFSH */
+
+static pid_t path_pfexecve(Shell_t *shp,const char *path, char *argv[],char *const envp[],int spawn)
+{
+#if SHOPT_PFSH
+ char resolvedpath[PATH_MAX + 1];
+ pid_t pid;
+ if(spawn)
+ {
+ while((pid = vfork()) < 0)
+ _sh_fork(shp,pid, 0, (int*)0);
+ if(pid)
+ return(pid);
+ }
+ if(!sh_isoption(SH_PFSH))
+ return(execve(path, argv, envp));
+ /* Solaris implements realpath(3C) using the resolvepath(2) */
+ /* system call so we can save us to call access(2) first */
+
+ /* we can exec the command directly instead of via pfexec(1) if */
+ /* there is a matching entry without attributes in exec_attr(4) */
+ if(!path_xattr(shp,path,resolvedpath))
+ return(execve(path, argv, envp));
+ --argv;
+ argv[0] = argv[1];
+ argv[1] = resolvedpath;
+ return(execve("/usr/bin/pfexec", argv, envp));
+#else
+ return(execve(path, argv, envp));
+#endif
+}
+
+
+static pid_t _spawnveg(Shell_t *shp,const char *path, char* const argv[], char* const envp[], pid_t pgid)
+{
+ int waitsafe = job.waitsafe;
+ pid_t pid;
+ job_lock();
+ while(1)
+ {
+ sh_stats(STAT_SPAWN);
+ pid = spawnveg(path,argv,envp,pgid);
+ if(pid>=0 || errno!=EAGAIN)
+ break;
+ _sh_fork(shp,pid, 0, (int*)0);
+ }
+ job.waitsafe = waitsafe;
+ if(pid>0)
+ job_fork(pid);
+ else
+ job_unlock();
+ return(pid);
+}
+/*
+ * used with command -x to run the command in multiple passes
+ * spawn is non-zero when invoked via spawn
+ * the exitval is set to the maximum for each execution
+ */
+static pid_t path_xargs(Shell_t *shp,const char *path, char *argv[],char *const envp[], int spawn)
+{
+ register char *cp, **av, **xv;
+ char **avlast= &argv[shp->xargmax], **saveargs=0;
+ char *const *ev;
+ long size, left;
+ int nlast=1,n,exitval=0;
+ pid_t pid;
+ if(shp->xargmin < 0)
+ return((pid_t)-1);
+ size = shp->gd->lim.arg_max-1024;
+ for(ev=envp; cp= *ev; ev++)
+ size -= strlen(cp)-1;
+ for(av=argv; (cp= *av) && av< &argv[shp->xargmin]; av++)
+ size -= strlen(cp)-1;
+ for(av=avlast; cp= *av; av++,nlast++)
+ size -= strlen(cp)-1;
+ av = &argv[shp->xargmin];
+ if(!spawn)
+ job_clear();
+ shp->exitval = 0;
+ while(av<avlast)
+ {
+ for(xv=av,left=size; left>0 && av<avlast;)
+ left -= strlen(*av++)+1;
+ /* leave at least two for last */
+ if(left<0 && (avlast-av)<2)
+ av--;
+ if(xv==&argv[shp->xargmin])
+ {
+ n = nlast*sizeof(char*);
+ saveargs = (char**)malloc(n);
+ memcpy((void*)saveargs, (void*)av, n);
+ memcpy((void*)av,(void*)avlast,n);
+ }
+ else
+ {
+ for(n=shp->xargmin; xv < av; xv++)
+ argv[n++] = *xv;
+ for(xv=avlast; cp= *xv; xv++)
+ argv[n++] = cp;
+ argv[n] = 0;
+ }
+ if(saveargs || av<avlast || (exitval && !spawn))
+ {
+ if((pid=_spawnveg(shp,path,argv,envp,0)) < 0)
+ return(-1);
+ job_post(shp,pid,0);
+ job_wait(pid);
+ if(shp->exitval>exitval)
+ exitval = shp->exitval;
+ if(saveargs)
+ {
+ memcpy((void*)av,saveargs,n);
+ free((void*)saveargs);
+ saveargs = 0;
+ }
+ }
+ else if(spawn && !sh_isoption(SH_PFSH))
+ {
+ shp->xargexit = exitval;
+ if(saveargs)
+ free((void*)saveargs);
+ return(_spawnveg(shp,path,argv,envp,spawn>>1));
+ }
+ else
+ {
+ if(saveargs)
+ free((void*)saveargs);
+ return(path_pfexecve(shp,path,argv,envp,spawn));
+ }
+ }
+ if(!spawn)
+ exit(exitval);
+ return((pid_t)-1);
+}
+
+/*
+ * make sure PWD is set up correctly
+ * Return the present working directory
+ * Invokes getcwd() if flag==0 and if necessary
+ * Sets the PWD variable to this value
+ */
+char *path_pwd(Shell_t *shp,int flag)
+{
+ register char *cp;
+ register char *dfault = (char*)e_dot;
+ register int count = 0;
+ if(shp->pwd)
+ return((char*)shp->pwd);
+ while(1)
+ {
+ /* try from lowest to highest */
+ switch(count++)
+ {
+ case 0:
+ cp = nv_getval(PWDNOD);
+ break;
+ case 1:
+ cp = nv_getval(HOME);
+ break;
+ case 2:
+ cp = "/";
+ break;
+ case 3:
+ cp = (char*)e_crondir;
+ if(flag) /* skip next case when non-zero flag */
+ ++count;
+ break;
+ case 4:
+ {
+ if(cp=getcwd(NIL(char*),0))
+ {
+ nv_offattr(PWDNOD,NV_NOFREE);
+ _nv_unset(PWDNOD,0);
+ PWDNOD->nvalue.cp = cp;
+ goto skip;
+ }
+ break;
+ }
+ case 5:
+ return(dfault);
+ }
+ if(cp && *cp=='/' && test_inode(cp,e_dot))
+ break;
+ }
+ if(count>1)
+ {
+ nv_offattr(PWDNOD,NV_NOFREE);
+ nv_putval(PWDNOD,cp,NV_RDONLY);
+ }
+skip:
+ nv_onattr(PWDNOD,NV_NOFREE|NV_EXPORT);
+ shp->pwd = (char*)(PWDNOD->nvalue.cp);
+ return(cp);
+}
+
+static void free_bltin(Namval_t *np,void *data)
+{
+ register Pathcomp_t *pp= (Pathcomp_t*)data;
+ if(pp->flags&PATH_STD_DIR)
+ {
+ int offset=staktell();;
+ if(strcmp(pp->name,"/bin")==0 || memcmp(pp->name,np->nvname,pp->len) || np->nvname[pp->len]!='/')
+ return;
+ stakputs("/bin");
+ stakputs(np->nvname+pp->len+1);
+ stakputc(0);
+ sh_addbuiltin(stakptr(offset),(Shbltin_f)np->nvalue.bfp,NiL);
+ stakseek(offset);
+ return;
+ }
+ if((void*)np->nvenv==pp->bltin_lib)
+ nv_delete(np,sh_bltin_tree(),NV_NOFREE);
+}
+
+/*
+ * delete current Pathcomp_t structure
+ */
+void path_delete(Pathcomp_t *first)
+{
+ register Pathcomp_t *pp=first, *old=0, *ppnext;
+ while(pp)
+ {
+ ppnext = pp->next;
+ if(--pp->refcount<=0)
+ {
+ if(pp->lib)
+ free((void*)pp->lib);
+ if(pp->blib)
+ free((void*)pp->blib);
+ if(pp->bltin_lib || (pp->flags&PATH_STD_DIR))
+ {
+ nv_scan(sh_bltin_tree(),free_bltin,pp,0,0);
+#if SHOPT_DYNAMIC
+ if(pp->bltin_lib)
+ dlclose(pp->bltin_lib);
+#endif /* SHOPT_DYNAMIC */
+ }
+ free((void*)pp);
+ if(old)
+ old->next = ppnext;
+ }
+ else
+ old = pp;
+ pp = ppnext;
+ }
+}
+
+/*
+ * returns library variable from .paths
+ * The value might be returned on the stack overwriting path
+ */
+static char *path_lib(Shell_t *shp,Pathcomp_t *pp, char *path)
+{
+ register char *last = strrchr(path,'/');
+ register int r;
+ struct stat statb;
+ if(last)
+ *last = 0;
+ else
+ path = ".";
+ r = stat(path,&statb);
+ if(last)
+ *last = '/';
+ if(r>=0)
+ {
+ Pathcomp_t pcomp;
+ char save[8];
+ for( ;pp; pp=pp->next)
+ {
+ path_checkdup(shp,pp);
+ if(pp->ino==statb.st_ino && pp->dev==statb.st_dev && pp->mtime==statb.st_mtime)
+ return(pp->lib);
+ }
+ pcomp.len = 0;
+ if(last)
+ pcomp.len = last-path;
+ memcpy((void*)save, (void*)stakptr(PATH_OFFSET+pcomp.len),sizeof(save));
+ if(path_chkpaths(shp,(Pathcomp_t*)0,(Pathcomp_t*)0,&pcomp,PATH_OFFSET))
+ return(stakfreeze(1));
+ memcpy((void*)stakptr(PATH_OFFSET+pcomp.len),(void*)save,sizeof(save));
+ }
+ return(0);
+}
+
+#if 0
+void path_dump(register Pathcomp_t *pp)
+{
+ sfprintf(sfstderr,"dump\n");
+ while(pp)
+ {
+ sfprintf(sfstderr,"pp=%x dev=%d ino=%d len=%d flags=%o name=%.*s\n",
+ pp,pp->dev,pp->ino,pp->len,pp->flags,pp->len,pp->name);
+ pp = pp->next;
+ }
+}
+#endif
+
+/*
+ * check for duplicate directories on PATH
+ */
+static void path_checkdup(Shell_t *shp,register Pathcomp_t *pp)
+{
+ register char *name = pp->name;
+ register Pathcomp_t *oldpp,*first;
+ register int flag=0;
+ struct stat statb;
+ if(stat(name,&statb)<0 || !S_ISDIR(statb.st_mode))
+ {
+ pp->flags |= PATH_SKIP;
+ pp->dev = *name=='/';
+ return;
+ }
+ pp->mtime = statb.st_mtime;
+ pp->ino = statb.st_ino;
+ pp->dev = statb.st_dev;
+ if(*name=='/' && onstdpath(name))
+ flag = PATH_STD_DIR;
+ first = (pp->flags&PATH_CDPATH)?(Pathcomp_t*)shp->cdpathlist:path_get(shp,"");
+ for(oldpp=first; oldpp && oldpp!=pp; oldpp=oldpp->next)
+ {
+ if(pp->ino==oldpp->ino && pp->dev==oldpp->dev && pp->mtime==oldpp->mtime)
+ {
+ flag |= PATH_SKIP;
+ break;
+ }
+ }
+ pp->flags |= flag;
+ if(((pp->flags&(PATH_PATH|PATH_SKIP))==PATH_PATH))
+ {
+ int offset = staktell();
+ stakputs(name);
+ path_chkpaths(shp,first,0,pp,offset);
+ stakseek(offset);
+ }
+}
+
+/*
+ * write the next path to search on the current stack
+ * if last is given, all paths that come before <last> are skipped
+ * the next pathcomp is returned.
+ */
+Pathcomp_t *path_nextcomp(Shell_t *shp,register Pathcomp_t *pp, const char *name, Pathcomp_t *last)
+{
+ Pathcomp_t *ppnext;
+ stakseek(PATH_OFFSET);
+ if(*name=='/')
+ pp = 0;
+ else
+ {
+ for(;pp && pp!=last;pp=ppnext)
+ {
+ ppnext = pp->next;
+ if(!pp->dev && !pp->ino)
+ path_checkdup(shp,pp);
+ if(pp->flags&PATH_SKIP)
+ continue;
+ if(!last || *pp->name!='/')
+ break;
+ }
+ if(!pp) /* this should not happen */
+ pp = last;
+ }
+ if(pp && (pp->name[0]!='.' || pp->name[1]))
+ {
+ if(*pp->name!='/')
+ {
+ stakputs(path_pwd(shp,1));
+ if(*stakptr(staktell()-1)!='/')
+ stakputc('/');
+ }
+ stakwrite(pp->name,pp->len);
+ if(pp->name[pp->len-1]!='/')
+ stakputc('/');
+ }
+ stakputs(name);
+ stakputc(0);
+ while(pp && pp!=last && (pp=pp->next))
+ {
+ if(!(pp->flags&PATH_SKIP))
+ return(pp);
+ }
+ return((Pathcomp_t*)0);
+}
+
+static Pathcomp_t* defpath_init(Shell_t *shp)
+{
+ Pathcomp_t *pp = (void*)path_addpath(shp,(Pathcomp_t*)0,(std_path),PATH_PATH);
+ return(pp);
+}
+
+static void path_init(Shell_t *shp)
+{
+ const char *val;
+ Pathcomp_t *pp;
+ if(!std_path && !(std_path=astconf("PATH",NIL(char*),NIL(char*))))
+ std_path = e_defpath;
+ if(val=sh_scoped(shp,(PATHNOD))->nvalue.cp)
+ {
+ shp->pathlist = pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_PATH);
+ }
+ else
+ {
+ if(!(pp=(Pathcomp_t*)shp->defpathlist))
+ pp = defpath_init(shp);
+ shp->pathlist = (void*)path_dup(pp);
+ }
+ if(val=sh_scoped(shp,(FPATHNOD))->nvalue.cp)
+ {
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
+ }
+}
+
+/*
+ * returns that pathlist to search
+ */
+Pathcomp_t *path_get(register Shell_t *shp,register const char *name)
+{
+ register Pathcomp_t *pp=0;
+ if(*name && strchr(name,'/'))
+ return(0);
+ if(!sh_isstate(SH_DEFPATH))
+ {
+ if(!shp->pathlist)
+ path_init(shp);
+ pp = (Pathcomp_t*)shp->pathlist;
+ }
+ if(!pp && (!(sh_scoped(shp,PATHNOD)->nvalue.cp)) || sh_isstate(SH_DEFPATH))
+ {
+ if(!(pp=(Pathcomp_t*)shp->defpathlist))
+ pp = defpath_init(shp);
+ }
+ return(pp);
+}
+
+/*
+ * open file corresponding to name using path give by <pp>
+ */
+static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp, int fun)
+{
+ register int fd= -1;
+ struct stat statb;
+ Pathcomp_t *oldpp;
+ if(!pp && !shp->pathlist)
+ path_init(shp);
+ if(!fun && strchr(name,'/'))
+ {
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,name);
+ }
+ do
+ {
+ pp = path_nextcomp(shp,oldpp=pp,name,0);
+ while(oldpp && (oldpp->flags&PATH_SKIP))
+ oldpp = oldpp->next;
+ if(fun && (!oldpp || !(oldpp->flags&PATH_FPATH)))
+ continue;
+ if((fd = sh_open(path_relative(shp,stakptr(PATH_OFFSET)),O_RDONLY,0)) >= 0)
+ {
+ if(fstat(fd,&statb)<0 || S_ISDIR(statb.st_mode))
+ {
+ errno = EISDIR;
+ sh_close(fd);
+ fd = -1;
+ }
+ }
+ }
+ while( fd<0 && pp);
+ if(fd>=0 && (fd = sh_iomovefd(fd)) > 0)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ return(fd);
+}
+
+/*
+ * open file corresponding to name using path give by <pp>
+ */
+int path_open(Shell_t *shp,const char *name, register Pathcomp_t *pp)
+{
+ return(path_opentype(shp,name,pp,0));
+}
+
+/*
+ * given a pathname return the base name
+ */
+
+char *path_basename(register const char *name)
+{
+ register const char *start = name;
+ while (*name)
+ if ((*name++ == '/') && *name) /* don't trim trailing / */
+ start = name;
+ return ((char*)start);
+}
+
+char *path_fullname(Shell_t *shp,const char *name)
+{
+ int len=strlen(name)+1,dirlen=0;
+ char *path,*pwd;
+ if(*name!='/')
+ {
+ pwd = path_pwd(shp,1);
+ dirlen = strlen(pwd)+1;
+ }
+ path = (char*)malloc(len+dirlen);
+ if(dirlen)
+ {
+ memcpy((void*)path,(void*)pwd,dirlen);
+ path[dirlen-1] = '/';
+ }
+ memcpy((void*)&path[dirlen],(void*)name,len);
+ pathcanon(path,0);
+ return(path);
+}
+
+/*
+ * load functions from file <fno>
+ */
+static void funload(Shell_t *shp,int fno, const char *name)
+{
+ char *pname,*oldname=shp->st.filename, buff[IOBSIZE+1];
+ Namval_t *np;
+ struct Ufunction *rp,*rpfirst;
+ int savestates = sh_getstate(), oldload=shp->funload;
+ pname = path_fullname(shp,stakptr(PATH_OFFSET));
+ if(shp->fpathdict && (rp = dtmatch(shp->fpathdict,(void*)pname)))
+ {
+ Dt_t *funtree = sh_subfuntree(1);
+ while(1)
+ {
+ rpfirst = dtprev(shp->fpathdict,rp);
+ if(!rpfirst || strcmp(pname,rpfirst->fname))
+ break;
+ rp = rpfirst;
+ }
+ do
+ {
+ if((np = dtsearch(funtree,rp->np)) && is_afunction(np))
+ {
+ if(np->nvalue.rp)
+ np->nvalue.rp->fdict = 0;
+ nv_delete(np,funtree,NV_NOFREE);
+ }
+ dtinsert(funtree,rp->np);
+ rp->fdict = funtree;
+ }
+ while((rp=dtnext(shp->fpathdict,rp)) && strcmp(pname,rp->fname)==0);
+ sh_close(fno);
+ return;
+ }
+ sh_onstate(SH_NOLOG);
+ sh_onstate(SH_NOALIAS);
+ shp->readscript = (char*)name;
+ shp->st.filename = pname;
+ shp->funload = 1;
+ error_info.line = 0;
+ sh_eval(sfnew(NIL(Sfio_t*),buff,IOBSIZE,fno,SF_READ),SH_FUNEVAL);
+ sh_close(fno);
+ shp->readscript = 0;
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ np = sh_fsearch(shp,name,0);
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = nv_search(name,shp->fun_tree,0);
+ if(!np || !np->nvalue.ip)
+ pname = stakcopy(shp->st.filename);
+ else
+ pname = 0;
+ free((void*)shp->st.filename);
+ shp->funload = oldload;
+ shp->st.filename = oldname;
+ sh_setstate(savestates);
+ if(pname)
+ errormsg(SH_DICT,ERROR_exit(ERROR_NOEXEC),e_funload,name,pname);
+}
+
+/*
+ * do a path search and track alias if requested
+ * if flag is 0, or if name not found, then try autoloading function
+ * if flag==2 or 3, returns 1 if name found on FPATH
+ * if flag==3 no tracked alias will be set
+ * returns 1, if function was autoloaded.
+ * If oldpp is not NULL, it will contain a pointer to the path component
+ * where it was found.
+ */
+
+int path_search(Shell_t *shp,register const char *name,Pathcomp_t **oldpp, int flag)
+{
+ register Namval_t *np;
+ register int fno;
+ Pathcomp_t *pp=0;
+ if(name && strchr(name,'/'))
+ {
+ stakseek(PATH_OFFSET);
+ stakputs(name);
+ if(canexecute(shp,stakptr(PATH_OFFSET),0)<0)
+ {
+ *stakptr(PATH_OFFSET) = 0;
+ return(0);
+ }
+ if(*name=='/')
+ return(1);
+ stakseek(PATH_OFFSET);
+ stakputs(path_pwd(shp,1));
+ stakputc('/');
+ stakputs(name);
+ stakputc(0);
+ return(0);
+ }
+ if(sh_isstate(SH_DEFPATH))
+ {
+ if(!shp->defpathlist)
+ defpath_init(shp);
+ }
+ else if(!shp->pathlist)
+ path_init(shp);
+ if(flag)
+ {
+ if(!(flag&1) && (np=nv_search(name,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && (pp=(Pathcomp_t*)np->nvalue.cp))
+ {
+ stakseek(PATH_OFFSET);
+ path_nextcomp(shp,pp,name,pp);
+ if(oldpp)
+ *oldpp = pp;
+ stakputc(0);
+ return(0);
+ }
+ pp = path_absolute(shp,name,oldpp?*oldpp:NIL(Pathcomp_t*));
+ if(oldpp)
+ *oldpp = pp;
+ if(!pp && (np=nv_search(name,shp->fun_tree,0))&&np->nvalue.ip)
+ return(1);
+ if(!pp)
+ *stakptr(PATH_OFFSET) = 0;
+ }
+ if(flag==0 || !pp || (pp->flags&PATH_FPATH))
+ {
+ if(!pp)
+ pp=sh_isstate(SH_DEFPATH)?shp->defpathlist:shp->pathlist;
+ if(pp && strmatch(name,e_alphanum) && (fno=path_opentype(shp,name,pp,1))>=0)
+ {
+ if(flag==2)
+ {
+ sh_close(fno);
+ return(1);
+ }
+ funload(shp,fno,name);
+ return(1);
+ }
+ *stakptr(PATH_OFFSET) = 0;
+ return(0);
+ }
+ else if(pp && !sh_isstate(SH_DEFPATH) && *name!='/' && flag<3)
+ {
+ if(np=nv_search(name,shp->track_tree,NV_ADD))
+ path_alias(np,pp);
+ }
+ return(0);
+}
+
+/*
+ * do a path search and find the full pathname of file name
+ */
+Pathcomp_t *path_absolute(Shell_t *shp,register const char *name, Pathcomp_t *pp)
+{
+ register int f,isfun;
+ int noexec=0;
+ Pathcomp_t *oldpp;
+ Namval_t *np;
+ char *cp;
+ shp->path_err = ENOENT;
+ if(!pp && !(pp=path_get(shp,"")))
+ return(0);
+ shp->path_err = 0;
+ while(1)
+ {
+ sh_sigcheck(shp);
+ isfun = (pp->flags&PATH_FPATH);
+ if(oldpp=pp)
+ {
+ pp = path_nextcomp(shp,pp,name,0);
+ while(oldpp->flags&PATH_SKIP)
+ {
+ if(!(oldpp=oldpp->next))
+ {
+ shp->path_err = ENOENT;
+ return(0);
+ }
+ }
+ }
+
+ if(!isfun && !sh_isoption(SH_RESTRICTED))
+ {
+ if(*stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),shp->bltin_tree,0))
+ return(oldpp);
+#if SHOPT_DYNAMIC
+ if(oldpp->blib)
+ {
+ Shbltin_f addr;
+ int n = staktell();
+ char *cp;
+ stakputs("b_");
+ stakputs(name);
+ stakputc(0);
+ if(!oldpp->bltin_lib)
+ {
+ if(cp = strrchr(oldpp->blib,'/'))
+ cp++;
+ else
+ cp = oldpp->blib;
+ if(!strcmp(cp,LIBCMD) && (addr=(Shbltin_f)dlllook((void*)0,stakptr(n))))
+ {
+ if((np = sh_addbuiltin(stakptr(PATH_OFFSET),addr,NiL)) && nv_isattr(np,NV_BLTINOPT))
+ return(oldpp);
+ }
+#ifdef SH_PLUGIN_VERSION
+ if (oldpp->bltin_lib = dllplugin(SH_ID, oldpp->blib, NiL, SH_PLUGIN_VERSION, NiL, RTLD_LAZY, NiL, 0))
+ sh_addlib(shp,oldpp->bltin_lib);
+#else
+#if (_AST_VERSION>=20040404)
+ if (oldpp->bltin_lib = dllplug(SH_ID, oldpp->blib, NiL, RTLD_LAZY, NiL, 0))
+#else
+ if (oldpp->bltin_lib = dllfind(oldpp->blib, NiL, RTLD_LAZY, NiL, 0))
+#endif
+ {
+ /*
+ * this detects the 2007-05-11 builtin context change and also
+ * the 2008-03-30 opt_info.num change that hit libcmd::b_head
+ */
+
+ if (libcmd && !dlllook(oldpp->bltin_lib, "b_pids"))
+ {
+ dlclose(oldpp->bltin_lib);
+ oldpp->bltin_lib = 0;
+ oldpp->blib = 0;
+ }
+ else
+ sh_addlib(shp,oldpp->bltin_lib);
+ }
+#endif
+ }
+ if(oldpp->bltin_lib &&
+ (addr=(Shbltin_f)dlllook(oldpp->bltin_lib,stakptr(n))) &&
+ (!(np = sh_addbuiltin(stakptr(PATH_OFFSET),NiL,NiL)) || np->nvalue.bfp!=(Nambfp_f)addr) &&
+ (np = sh_addbuiltin(stakptr(PATH_OFFSET),addr,NiL)))
+ {
+ np->nvenv = oldpp->bltin_lib;
+ return(oldpp);
+ }
+ }
+#endif /* SHOPT_DYNAMIC */
+ }
+ sh_stats(STAT_PATHS);
+ f = canexecute(shp,stakptr(PATH_OFFSET),isfun);
+ if(isfun && f>=0 && (cp = strrchr(name,'.')))
+ {
+ *cp = 0;
+ if(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE))
+ f = -1;
+ *cp = '.';
+ }
+ if(isfun && f>=0)
+ {
+ nv_onattr(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE),NV_LTOU|NV_FUNCTION);
+ funload(shp,f,name);
+ close(f);
+ f = -1;
+ return(0);
+ }
+ else if(f>=0 && (oldpp->flags & PATH_STD_DIR))
+ {
+ int n = staktell();
+ stakputs("/bin/");
+ stakputs(name);
+ stakputc(0);
+ np = nv_search(stakptr(n),shp->bltin_tree,0);
+ stakseek(n);
+ if(np)
+ {
+ n = np->nvflag;
+ np = sh_addbuiltin(stakptr(PATH_OFFSET),(Shbltin_f)np->nvalue.bfp,nv_context(np));
+ np->nvflag = n;
+ }
+ }
+ if(!pp || f>=0)
+ break;
+ if(errno!=ENOENT)
+ noexec = errno;
+ }
+ if(f<0)
+ {
+ shp->path_err = (noexec?noexec:ENOENT);
+ return(0);
+ }
+ stakputc(0);
+ return(oldpp);
+}
+
+/*
+ * returns 0 if path can execute
+ * sets exec_err if file is found but can't be executable
+ */
+#undef S_IXALL
+#ifdef S_IXUSR
+# define S_IXALL (S_IXUSR|S_IXGRP|S_IXOTH)
+#else
+# ifdef S_IEXEC
+# define S_IXALL (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))
+# else
+# define S_IXALL 0111
+# endif /*S_EXEC */
+#endif /* S_IXUSR */
+
+static int canexecute(Shell_t *shp,register char *path, int isfun)
+{
+ struct stat statb;
+ register int fd=0;
+ path = path_relative(shp,path);
+ if(isfun)
+ {
+ if((fd=open(path,O_RDONLY,0))<0 || fstat(fd,&statb)<0)
+ goto err;
+ }
+ else if(stat(path,&statb) < 0)
+ {
+#if _WINIX
+ /* check for .exe or .bat suffix */
+ char *cp;
+ if(errno==ENOENT && (!(cp=strrchr(path,'.')) || strlen(cp)>4 || strchr(cp,'/')))
+ {
+ int offset = staktell()-1;
+ stakseek(offset);
+ stakputs(".bat");
+ path = stakptr(PATH_OFFSET);
+ if(stat(path,&statb) < 0)
+ {
+ if(errno!=ENOENT)
+ goto err;
+ memcpy(stakptr(offset),".sh",4);
+ if(stat(path,&statb) < 0)
+ goto err;
+ }
+ }
+ else
+#endif /* _WINIX */
+ goto err;
+ }
+ errno = EPERM;
+ if(S_ISDIR(statb.st_mode))
+ errno = EISDIR;
+ else if((statb.st_mode&S_IXALL)==S_IXALL || sh_access(path,X_OK)>=0)
+ return(fd);
+ if(isfun && fd>=0)
+ sh_close(fd);
+err:
+ return(-1);
+}
+
+/*
+ * Return path relative to present working directory
+ */
+
+char *path_relative(Shell_t *shp,register const char* file)
+{
+ register const char *pwd;
+ register const char *fp = file;
+ /* can't relpath when shp->pwd not set */
+ if(!(pwd=shp->pwd))
+ return((char*)fp);
+ while(*pwd==*fp)
+ {
+ if(*pwd++==0)
+ return((char*)e_dot);
+ fp++;
+ }
+ if(*pwd==0 && *fp == '/')
+ {
+ while(*++fp=='/');
+ if(*fp)
+ return((char*)fp);
+ return((char*)e_dot);
+ }
+ return((char*)file);
+}
+
+void path_exec(Shell_t *shp,register const char *arg0,register char *argv[],struct argnod *local)
+{
+ char **envp;
+ const char *opath;
+ Pathcomp_t *libpath, *pp=0;
+ int slash=0;
+ nv_setlist(local,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
+ envp = sh_envgen();
+ if(strchr(arg0,'/'))
+ {
+ slash=1;
+ /* name containing / not allowed for restricted shell */
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,arg0);
+ }
+ else
+ pp=path_get(shp,arg0);
+ shp->path_err= ENOENT;
+ sfsync(NIL(Sfio_t*));
+ timerdel(NIL(void*));
+ /* find first path that has a library component */
+ while(pp && (pp->flags&PATH_SKIP))
+ pp = pp->next;
+ if(pp || slash) do
+ {
+ sh_sigcheck(shp);
+ if(libpath=pp)
+ {
+ pp = path_nextcomp(shp,pp,arg0,0);
+ opath = stakfreeze(1)+PATH_OFFSET;
+ }
+ else
+ opath = arg0;
+ path_spawn(shp,opath,argv,envp,libpath,0);
+ while(pp && (pp->flags&PATH_FPATH))
+ pp = path_nextcomp(shp,pp,arg0,0);
+ }
+ while(pp);
+ /* force an exit */
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
+ if((errno=shp->path_err)==ENOENT)
+ errormsg(SH_DICT,ERROR_exit(ERROR_NOENT),e_found,arg0);
+ else
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arg0);
+}
+
+pid_t path_spawn(Shell_t *shp,const char *opath,register char **argv, char **envp, Pathcomp_t *libpath, int spawn)
+{
+ register char *path;
+ char **xp=0, *xval, *libenv = (libpath?libpath->lib:0);
+ Namval_t* np;
+ char *s, *v;
+ int r, n, pidsize;
+ pid_t pid= -1;
+ /* leave room for inserting _= pathname in environment */
+ envp--;
+#if _lib_readlink
+ /* save original pathname */
+ stakseek(PATH_OFFSET);
+ pidsize = sfprintf(stkstd,"*%d*",spawn?getpid():getppid());
+ stakputs(opath);
+ opath = stakfreeze(1)+PATH_OFFSET+pidsize;
+ np=nv_search(argv[0],shp->track_tree,0);
+ while(libpath && !libpath->lib)
+ libpath=libpath->next;
+ if(libpath && (!np || nv_size(np)>0))
+ {
+ /* check for symlink and use symlink name */
+ char buff[PATH_MAX+1];
+ char save[PATH_MAX+1];
+ stakseek(PATH_OFFSET);
+ stakputs(opath);
+ path = stakptr(PATH_OFFSET);
+ while((n=readlink(path,buff,PATH_MAX))>0)
+ {
+ buff[n] = 0;
+ n = PATH_OFFSET;
+ r = 0;
+ if((v=strrchr(path,'/')) && *buff!='/')
+ {
+ if(buff[0]=='.' && buff[1]=='.' && (r = strlen(path) + 1) <= PATH_MAX)
+ memcpy(save, path, r);
+ else
+ r = 0;
+ n += (v+1-path);
+ }
+ stakseek(n);
+ stakputs(buff);
+ stakputc(0);
+ path = stakptr(PATH_OFFSET);
+ if(v && buff[0]=='.' && buff[1]=='.')
+ {
+ pathcanon(path, 0);
+ if(r && access(path,X_OK))
+ {
+ memcpy(path, save, r);
+ break;
+ }
+ }
+ if(libenv = path_lib(shp,libpath,path))
+ break;
+ }
+ stakseek(0);
+ }
+#endif
+ if(libenv && (v = strchr(libenv,'=')))
+ {
+ n = v - libenv;
+ *v = 0;
+ np = nv_open(libenv,shp->var_tree,0);
+ *v = '=';
+ s = nv_getval(np);
+ stakputs(libenv);
+ if(s)
+ {
+ stakputc(':');
+ stakputs(s);
+ }
+ v = stakfreeze(1);
+ r = 1;
+ xp = envp + 1;
+ while (s = *xp++)
+ {
+ if (strneq(s, v, n) && s[n] == '=')
+ {
+ xval = *--xp;
+ *xp = v;
+ r = 0;
+ break;
+ }
+ }
+ if (r)
+ {
+ *envp-- = v;
+ xp = 0;
+ }
+ }
+ if(!opath)
+ opath = stakptr(PATH_OFFSET);
+ envp[0] = (char*)opath-(PATH_OFFSET+pidsize);
+ envp[0][0] = '_';
+ envp[0][1] = '=';
+ sfsync(sfstderr);
+ sh_sigcheck(shp);
+ path = path_relative(shp,opath);
+#ifdef SHELLMAGIC
+ if(*path!='/' && path!=opath)
+ {
+ /*
+ * The following code because execv(foo,) and execv(./foo,)
+ * may not yield the same results
+ */
+ char *sp = (char*)malloc(strlen(path)+3);
+ sp[0] = '.';
+ sp[1] = '/';
+ strcpy(sp+2,path);
+ path = sp;
+ }
+#endif /* SHELLMAGIC */
+ if(spawn && !sh_isoption(SH_PFSH))
+ pid = _spawnveg(shp,opath, &argv[0],envp, spawn>>1);
+ else
+ pid = path_pfexecve(shp,opath, &argv[0] ,envp,spawn);
+ if(xp)
+ *xp = xval;
+#ifdef SHELLMAGIC
+ if(*path=='.' && path!=opath)
+ {
+ free(path);
+ path = path_relative(shp,opath);
+ }
+#endif /* SHELLMAGIC */
+ if(pid>0)
+ return(pid);
+retry:
+ switch(shp->path_err = errno)
+ {
+#ifdef apollo
+ /*
+ * On apollo's execve will fail with eacces when
+ * file has execute but not read permissions. So,
+ * for now we will pretend that EACCES and ENOEXEC
+ * mean the same thing.
+ */
+ case EACCES:
+#endif /* apollo */
+ case ENOEXEC:
+#if SHOPT_SUID_EXEC
+ case EPERM:
+ /* some systems return EPERM if setuid bit is on */
+#endif
+ errno = ENOEXEC;
+ if(spawn)
+ {
+#ifdef _lib_fork
+ if(shp->subshell)
+ return(-1);
+ do
+ {
+ if((pid=fork())>0)
+ return(pid);
+ }
+ while(_sh_fork(shp,pid,0,(int*)0) < 0);
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
+#else
+ return(-1);
+#endif
+ }
+ exscript(shp,path,argv,envp);
+#ifndef apollo
+ case EACCES:
+ {
+ struct stat statb;
+ if(stat(path,&statb)>=0)
+ {
+ if(S_ISDIR(statb.st_mode))
+ errno = EISDIR;
+#ifdef S_ISSOCK
+ if(S_ISSOCK(statb.st_mode))
+ exscript(shp,path,argv,envp);
+#endif
+ }
+ }
+ /* FALL THROUGH */
+#endif /* !apollo */
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG:
+#endif /* ENAMETOOLONG */
+#if !SHOPT_SUID_EXEC
+ case EPERM:
+#endif
+ shp->path_err = errno;
+ return(-1);
+ case ENOTDIR:
+ case ENOENT:
+ case EINTR:
+#ifdef EMLINK
+ case EMLINK:
+#endif /* EMLINK */
+ return(-1);
+ case E2BIG:
+ if(shp->xargmin)
+ {
+ pid = path_xargs(shp,opath, &argv[0] ,envp,spawn);
+ if(pid<0)
+ goto retry;
+ return(pid);
+ }
+ default:
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
+ }
+ return 0;
+}
+
+/*
+ * File is executable but not machine code.
+ * Assume file is a Shell script and execute it.
+ */
+
+static void exscript(Shell_t *shp,register char *path,register char *argv[],char **envp)
+{
+ register Sfio_t *sp;
+ path = path_relative(shp,path);
+ shp->comdiv=0;
+ shp->bckpid = 0;
+ shp->coshell = 0;
+ shp->st.ioset=0;
+ /* clean up any cooperating processes */
+ if(shp->cpipe[0]>0)
+ sh_pclose(shp->cpipe);
+ if(shp->cpid && shp->outpipe)
+ sh_close(*shp->outpipe);
+ shp->cpid = 0;
+ if(sp=fcfile())
+ while(sfstack(sp,SF_POPSTACK));
+ job_clear();
+ if(shp->infd>0 && (shp->fdstatus[shp->infd]&IOCLEX))
+ sh_close(shp->infd);
+ sh_setstate(sh_state(SH_FORKED));
+ sfsync(sfstderr);
+#if SHOPT_SUID_EXEC && !SHOPT_PFSH
+ /* check if file cannot open for read or script is setuid/setgid */
+ {
+ static char name[] = "/tmp/euidXXXXXXXXXX";
+ register int n;
+ register uid_t euserid;
+ char *savet=0;
+ struct stat statb;
+ if((n=sh_open(path,O_RDONLY,0)) >= 0)
+ {
+ /* move <n> if n=0,1,2 */
+ n = sh_iomovefd(n);
+ if(fstat(n,&statb)>=0 && !(statb.st_mode&(S_ISUID|S_ISGID)))
+ goto openok;
+ sh_close(n);
+ }
+ if((euserid=geteuid()) != shp->gd->userid)
+ {
+ strncpy(name+9,fmtbase((long)getpid(),10,0),sizeof(name)-10);
+ /* create a suid open file with owner equal effective uid */
+ if((n=open(name,O_CREAT|O_TRUNC|O_WRONLY,S_ISUID|S_IXUSR)) < 0)
+ goto fail;
+ unlink(name);
+ /* make sure that file has right owner */
+ if(fstat(n,&statb)<0 || statb.st_uid != euserid)
+ goto fail;
+ if(n!=10)
+ {
+ sh_close(10);
+ fcntl(n, F_DUPFD, 10);
+ sh_close(n);
+ n=10;
+ }
+ }
+ savet = *--argv;
+ *argv = path;
+ path_pfexecve(shp,e_suidexec,argv,envp,0);
+ fail:
+ /*
+ * The following code is just for compatibility
+ */
+ if((n=open(path,O_RDONLY,0)) < 0)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
+ if(savet)
+ *argv++ = savet;
+ openok:
+ shp->infd = n;
+ }
+#else
+ if((shp->infd = sh_open(path,O_RDONLY,0)) < 0)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
+#endif
+ shp->infd = sh_iomovefd(shp->infd);
+#if SHOPT_ACCT
+ sh_accbegin(path) ; /* reset accounting */
+#endif /* SHOPT_ACCT */
+ shp->arglist = sh_argcreate(argv);
+ shp->lastarg = strdup(path);
+ /* save name of calling command */
+ shp->readscript = error_info.id;
+ /* close history file if name has changed */
+ if(shp->gd->hist_ptr && (path=nv_getval(HISTFILE)) && strcmp(path,shp->gd->hist_ptr->histname))
+ {
+ hist_close(shp->gd->hist_ptr);
+ (HISTCUR)->nvalue.lp = 0;
+ }
+ sh_offstate(SH_FORKED);
+ if(shp->sigflag[SIGCHLD]==SH_SIGOFF)
+ shp->sigflag[SIGCHLD] = SH_SIGFAULT;
+ siglongjmp(*shp->jmplist,SH_JMPSCRIPT);
+}
+
+#if SHOPT_ACCT
+# include <sys/acct.h>
+# include "FEATURE/time"
+
+ static struct acct sabuf;
+ static struct tms buffer;
+ static clock_t before;
+ static char *SHACCT; /* set to value of SHACCT environment variable */
+ static shaccton; /* non-zero causes accounting record to be written */
+ static int compress(time_t);
+ /*
+ * initialize accounting, i.e., see if SHACCT variable set
+ */
+ void sh_accinit(void)
+ {
+ SHACCT = getenv("SHACCT");
+ }
+ /*
+ * suspend accounting until turned on by sh_accbegin()
+ */
+ void sh_accsusp(void)
+ {
+ shaccton=0;
+#ifdef AEXPAND
+ sabuf.ac_flag |= AEXPND;
+#endif /* AEXPAND */
+ }
+
+ /*
+ * begin an accounting record by recording start time
+ */
+ void sh_accbegin(const char *cmdname)
+ {
+ if(SHACCT)
+ {
+ sabuf.ac_btime = time(NIL(time_t *));
+ before = times(&buffer);
+ sabuf.ac_uid = getuid();
+ sabuf.ac_gid = getgid();
+ strncpy(sabuf.ac_comm, (char*)path_basename(cmdname),
+ sizeof(sabuf.ac_comm));
+ shaccton = 1;
+ }
+ }
+ /*
+ * terminate an accounting record and append to accounting file
+ */
+ void sh_accend(void)
+ {
+ int fd;
+ clock_t after;
+
+ if(shaccton)
+ {
+ after = times(&buffer);
+ sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime);
+ sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime);
+ sabuf.ac_etime = compress( (time_t)(after-before));
+ fd = open( SHACCT , O_WRONLY | O_APPEND | O_CREAT,RW_ALL);
+ write(fd, (const char*)&sabuf, sizeof( sabuf ));
+ close( fd);
+ }
+ }
+
+ /*
+ * Produce a pseudo-floating point representation
+ * with 3 bits base-8 exponent, 13 bits fraction.
+ */
+ static int compress(register time_t t)
+ {
+ register int exp = 0, rund = 0;
+
+ while (t >= 8192)
+ {
+ exp++;
+ rund = t&04;
+ t >>= 3;
+ }
+ if (rund)
+ {
+ t++;
+ if (t >= 8192)
+ {
+ t >>= 3;
+ exp++;
+ }
+ }
+ return((exp<<13) + t);
+ }
+#endif /* SHOPT_ACCT */
+
+
+
+/*
+ * add a pathcomponent to the path search list and eliminate duplicates
+ * and non-existing absolute paths.
+ */
+static Pathcomp_t *path_addcomp(Shell_t *shp,Pathcomp_t *first, Pathcomp_t *old,const char *name, int flag)
+{
+ register Pathcomp_t *pp, *oldpp;
+ int len, offset=staktell();
+ if(!(flag&PATH_BFPATH))
+ {
+ register const char *cp = name;
+ while(*cp && *cp!=':')
+ stakputc(*cp++);
+ len = staktell()-offset;
+ stakputc(0);
+ stakseek(offset);
+ name = (const char*)stakptr(offset);
+ }
+ else
+ len = strlen(name);
+ for(pp=first; pp; pp=pp->next)
+ {
+ if(memcmp(name,pp->name,len)==0 && (pp->name[len]==':' || pp->name[len]==0))
+ {
+ pp->flags |= flag;
+ return(first);
+ }
+ }
+ for(pp=first, oldpp=0; pp; oldpp=pp, pp=pp->next);
+ pp = newof((Pathcomp_t*)0,Pathcomp_t,1,len+1);
+ pp->shp = shp;
+ pp->refcount = 1;
+ memcpy((char*)(pp+1),name,len+1);
+ pp->name = (char*)(pp+1);
+ pp->len = len;
+ if(oldpp)
+ oldpp->next = pp;
+ else
+ first = pp;
+ pp->flags = flag;
+ if(strcmp(name,SH_CMDLIB_DIR)==0)
+ {
+ pp->dev = 1;
+ pp->flags |= PATH_BUILTIN_LIB;
+ pp->blib = malloc(4);
+ strcpy(pp->blib,LIBCMD);
+ return(first);
+ }
+ if((old||shp->pathinit) && ((flag&(PATH_PATH|PATH_SKIP))==PATH_PATH))
+ path_chkpaths(shp,first,old,pp,offset);
+ return(first);
+}
+
+/*
+ * This function checks for the .paths file in directory in <pp>
+ * it assumes that the directory is on the stack at <offset>
+ */
+static int path_chkpaths(Shell_t *shp,Pathcomp_t *first, Pathcomp_t* old,Pathcomp_t *pp, int offset)
+{
+ struct stat statb;
+ int k,m,n,fd;
+ char *sp,*cp,*ep;
+ stakseek(offset+pp->len);
+ if(pp->len==1 && *stakptr(offset)=='/')
+ stakseek(offset);
+ stakputs("/.paths");
+ if((fd=open(stakptr(offset),O_RDONLY))>=0)
+ {
+ fstat(fd,&statb);
+ n = statb.st_size;
+ stakseek(offset+pp->len+n+2);
+ sp = stakptr(offset+pp->len);
+ *sp++ = '/';
+ n=read(fd,cp=sp,n);
+ sp[n] = 0;
+ close(fd);
+ for(ep=0; n--; cp++)
+ {
+ if(*cp=='=')
+ {
+ ep = cp+1;
+ continue;
+ }
+ else if(*cp!='\r' && *cp!='\n')
+ continue;
+ if(*sp=='#' || sp==cp)
+ {
+ sp = cp+1;
+ continue;
+ }
+ *cp = 0;
+ m = ep ? (ep-sp) : 0;
+ if(m==0 || m==6 && memcmp((void*)sp,(void*)"FPATH=",6)==0)
+ {
+ if(first)
+ {
+ char *ptr = stakptr(offset+pp->len+1);
+ if(ep)
+ strcpy(ptr,ep);
+ path_addcomp(shp,first,old,stakptr(offset),PATH_FPATH|PATH_BFPATH);
+ }
+ }
+ else if(m==12 && memcmp((void*)sp,(void*)"BUILTIN_LIB=",12)==0)
+ {
+ if(!(pp->flags & PATH_BUILTIN_LIB) || strchr(ep,'-'))
+ {
+ if ((pp->flags & (PATH_BUILTIN_LIB|PATH_STD_DIR)) == PATH_BUILTIN_LIB)
+ {
+ free(pp->blib);
+ pp->blib = 0;
+ }
+ pp->flags |= PATH_BUILTIN_LIB;
+ if (*ep == '.' && !*(ep + 1))
+ pp->flags |= PATH_STD_DIR;
+ else
+ {
+ k = strlen(ep)+1;
+ if (*ep != '/')
+ k += pp->len+1;
+ pp->blib = sp = malloc(k);
+ if (*ep != '/')
+ {
+ strcpy(pp->blib,pp->name);
+ sp += pp->len;
+ *sp++ = '/';
+ }
+ strcpy(sp,ep);
+ }
+ }
+ }
+ else if(m)
+ {
+ pp->lib = (char*)malloc(cp-sp+pp->len+2);
+ memcpy((void*)pp->lib,(void*)sp,m);
+ memcpy((void*)&pp->lib[m],stakptr(offset),pp->len);
+ pp->lib[k=m+pp->len] = '/';
+ strcpy((void*)&pp->lib[k+1],ep);
+ pathcanon(&pp->lib[m],0);
+ if(!first)
+ {
+ stakseek(0);
+ stakputs(pp->lib);
+ free((void*)pp->lib);
+ return(1);
+ }
+ }
+ sp = cp+1;
+ ep = 0;
+ }
+ }
+ return(0);
+}
+
+
+Pathcomp_t *path_addpath(Shell_t *shp,Pathcomp_t *first, register const char *path,int type)
+{
+ register const char *cp;
+ Pathcomp_t *old=0;
+ int offset = staktell();
+ char *savptr;
+
+ if(!path && type!=PATH_PATH)
+ return(first);
+ if(type!=PATH_FPATH)
+ {
+ old = first;
+ first = 0;
+ }
+ if(offset)
+ savptr = stakfreeze(0);
+ if(path) while(*(cp=path))
+ {
+ if(*cp==':')
+ {
+ if(type!=PATH_FPATH)
+ first = path_addcomp(shp,first,old,".",type);
+ while(*++path == ':');
+ }
+ else
+ {
+ int c;
+ while(*path && *path!=':')
+ path++;
+ c = *path++;
+ first = path_addcomp(shp,first,old,cp,type);
+ if(c==0)
+ break;
+ if(*path==0)
+ path--;
+ }
+ }
+ if(old)
+ {
+ if(!first && !path)
+ {
+ Pathcomp_t *pp = (Pathcomp_t*)shp->defpathlist;
+ if(!pp)
+ pp = defpath_init(shp);
+ first = path_dup(pp);
+ }
+ if(cp=(sh_scoped(shp,FPATHNOD))->nvalue.cp)
+ first = (void*)path_addpath(shp,(Pathcomp_t*)first,cp,PATH_FPATH);
+ path_delete(old);
+ }
+ if(offset)
+ stakset(savptr,offset);
+ else
+ stakseek(0);
+ return(first);
+}
+
+/*
+ * duplicate the path give by <first> by incremented reference counts
+ */
+Pathcomp_t *path_dup(Pathcomp_t *first)
+{
+ register Pathcomp_t *pp=first;
+ while(pp)
+ {
+ pp->refcount++;
+ pp = pp->next;
+ }
+ return(first);
+}
+
+/*
+ * called whenever the directory is changed
+ */
+void path_newdir(Shell_t *shp,Pathcomp_t *first)
+{
+ register Pathcomp_t *pp=first, *next, *pq;
+ struct stat statb;
+ for(pp=first; pp; pp=pp->next)
+ {
+ pp->flags &= ~PATH_SKIP;
+ if(*pp->name=='/')
+ continue;
+ /* delete .paths component */
+ if((next=pp->next) && (next->flags&PATH_BFPATH))
+ {
+ pp->next = next->next;
+ if(--next->refcount<=0)
+ free((void*)next);
+ }
+ if(stat(pp->name,&statb)<0 || !S_ISDIR(statb.st_mode))
+ {
+ pp->dev = 0;
+ pp->ino = 0;
+ continue;
+ }
+ pp->dev = statb.st_dev;
+ pp->ino = statb.st_ino;
+ pp->mtime = statb.st_mtime;
+ for(pq=first;pq!=pp;pq=pq->next)
+ {
+ if(pp->ino==pq->ino && pp->dev==pq->dev)
+ pp->flags |= PATH_SKIP;
+ }
+ for(pq=pp;pq=pq->next;)
+ {
+ if(pp->ino==pq->ino && pp->dev==pq->dev)
+ pq->flags |= PATH_SKIP;
+ }
+ if((pp->flags&(PATH_PATH|PATH_SKIP))==PATH_PATH)
+ {
+ /* try to insert .paths component */
+ int offset = staktell();
+ stakputs(pp->name);
+ stakseek(offset);
+ next = pp->next;
+ pp->next = 0;
+ path_chkpaths(shp,first,(Pathcomp_t*)0,pp,offset);
+ if(pp->next)
+ pp = pp->next;
+ pp->next = next;
+ }
+ }
+#if 0
+ path_dump(first);
+#endif
+}
+
+Pathcomp_t *path_unsetfpath(Shell_t *shp)
+{
+ Pathcomp_t *first = (Pathcomp_t*)shp->pathlist;
+ register Pathcomp_t *pp=first, *old=0;
+ if(shp->fpathdict)
+ {
+ struct Ufunction *rp, *rpnext;
+ for(rp=(struct Ufunction*)dtfirst(shp->fpathdict);rp;rp=rpnext)
+ {
+ rpnext = (struct Ufunction*)dtnext(shp->fpathdict,rp);
+ if(rp->fdict)
+ nv_delete(rp->np,rp->fdict,NV_NOFREE);
+ rp->fdict = 0;
+ }
+ }
+ while(pp)
+ {
+ if((pp->flags&PATH_FPATH) && !(pp->flags&PATH_BFPATH))
+ {
+ if(pp->flags&PATH_PATH)
+ pp->flags &= ~PATH_FPATH;
+ else
+ {
+ Pathcomp_t *ppsave=pp;
+ if(old)
+ old->next = pp->next;
+ else
+ first = pp->next;
+ pp = pp->next;
+ if(--ppsave->refcount<=0)
+ {
+ if(ppsave->lib)
+ free((void*)ppsave->lib);
+ free((void*)ppsave);
+ }
+ continue;
+ }
+
+ }
+ old = pp;
+ pp = pp->next;
+ }
+ return(first);
+}
+
+Pathcomp_t *path_dirfind(Pathcomp_t *first,const char *name,int c)
+{
+ register Pathcomp_t *pp=first;
+ while(pp)
+ {
+ if(memcmp(name,pp->name,pp->len)==0 && name[pp->len]==c)
+ return(pp);
+ pp = pp->next;
+ }
+ return(0);
+}
+
+/*
+ * get discipline for tracked alias
+ */
+static char *talias_get(Namval_t *np, Namfun_t *nvp)
+{
+ Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
+ char *ptr;
+ if(!pp)
+ return(NULL);
+ path_nextcomp(pp->shp,pp,nv_name(np),pp);
+ ptr = stakfreeze(0);
+ return(ptr+PATH_OFFSET);
+}
+
+static void talias_put(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ if(!val && np->nvalue.cp)
+ {
+ Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
+ if(--pp->refcount<=0)
+ free((void*)pp);
+ }
+ nv_putv(np,val,flags,fp);
+}
+
+static const Namdisc_t talias_disc = { 0, talias_put, talias_get };
+static Namfun_t talias_init = { &talias_disc, 1 };
+
+/*
+ * set tracked alias node <np> to value <pp>
+ */
+void path_alias(register Namval_t *np,register Pathcomp_t *pp)
+{
+ if(pp)
+ {
+ struct stat statb;
+ char *sp;
+ nv_offattr(np,NV_NOPRINT);
+ nv_stack(np,&talias_init);
+ np->nvalue.cp = (char*)pp;
+ pp->refcount++;
+ nv_setattr(np,NV_TAGGED|NV_NOFREE);
+ path_nextcomp(pp->shp,pp,nv_name(np),pp);
+ sp = stakptr(PATH_OFFSET);
+ if(sp && lstat(sp,&statb)>=0 && S_ISLNK(statb.st_mode))
+ nv_setsize(np,statb.st_size+1);
+ else
+ nv_setsize(np,0);
+ }
+ else
+ _nv_unset(np,0);
+}
+
diff --git a/src/cmd/ksh93/sh/pmain.c b/src/cmd/ksh93/sh/pmain.c
new file mode 100644
index 0000000..8742195
--- /dev/null
+++ b/src/cmd/ksh93/sh/pmain.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <shell.h>
+
+#include "FEATURE/externs"
+
+#if defined(__sun) && _sys_mman && _lib_memcntl && defined(MHA_MAPSIZE_STACK) && defined(MC_HAT_ADVISE)
+# undef VM_FLAGS /* solaris vs vmalloc.h symbol clash */
+# include <sys/mman.h>
+#else
+# undef _lib_memcntl
+#endif
+
+typedef int (*Shnote_f)(int, long, int);
+
+int main(int argc, char *argv[])
+{
+#if _lib_memcntl
+ /* advise larger stack size */
+ struct memcntl_mha mha;
+ mha.mha_cmd = MHA_MAPSIZE_STACK;
+ mha.mha_flags = 0;
+ mha.mha_pagesize = 64 * 1024;
+ (void)memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mha, 0, 0);
+#endif
+ return(sh_main(argc, argv, (Shinit_f)0));
+}
diff --git a/src/cmd/ksh93/sh/shcomp.c b/src/cmd/ksh93/sh/shcomp.c
new file mode 100644
index 0000000..184637b
--- /dev/null
+++ b/src/cmd/ksh93/sh/shcomp.c
@@ -0,0 +1,177 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell script to shell binary converter
+ *
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: shcomp (AT&T Research) 2003-03-02 $\n]"
+USAGE_LICENSE
+"[+NAME?shcomp - compile a shell script]"
+"[+DESCRIPTION?Unless \b-D\b is specified, \bshcomp\b takes a shell script, "
+ "\ainfile\a, and creates a binary format file, \aoutfile\a, that "
+ "\bksh\b can read and execute with the same effect as the original "
+ "script.]"
+"[+?Since aliases are processed as the script is read, alias definitions "
+ "whose value requires variable expansion will not work correctly.]"
+"[+?If \b-D\b is specified, all double quoted strings that are preceded by "
+ "\b$\b are output. These are the messages that need to be "
+ "translated to locale specific versions for internationalization.]"
+"[+?If \aoutfile\a is omitted, then the results will be written to "
+ "standard output. If \ainfile\a is also omitted, the shell script "
+ "will be read from standard input.]"
+"[D:dictionary?Generate a list of strings that need to be placed in a message "
+ "catalog for internationalization.]"
+"[n:noexec?Displays warning messages for obsolete or non-conforming "
+ "constructs.] "
+"[v:verbose?Displays input from \ainfile\a onto standard error as it "
+ "reads it.]"
+"\n"
+"\n[infile [outfile]]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bksh\b(1)]"
+;
+
+#include <shell.h>
+#include "defs.h"
+#include "shnodes.h"
+#include "sys/stat.h"
+
+#define CNTL(x) ((x)&037)
+#define VERSION 3
+static const char header[6] = { CNTL('k'),CNTL('s'),CNTL('h'),0,VERSION,0 };
+
+int main(int argc, char *argv[])
+{
+ Sfio_t *in, *out;
+ Shell_t *shp;
+ Namval_t *np;
+ Shnode_t *t;
+ char *cp;
+ int n, nflag=0, vflag=0, dflag=0;
+ error_info.id = argv[0];
+ while(n = optget(argv, usage )) switch(n)
+ {
+ case 'D':
+ dflag=1;
+ break;
+ case 'v':
+ vflag=1;
+ break;
+ case 'n':
+ nflag=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2,"%s",opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg);
+ break;
+ }
+ shp = sh_init(argc,argv,(Shinit_f)0);
+ shp->shcomp = 1;
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc>2)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(cp= *argv)
+ {
+ argv++;
+ in = sh_pathopen(cp);
+ }
+ else
+ in = sfstdin;
+ if(cp= *argv)
+ {
+ struct stat statb;
+ if(!(out = sfopen((Sfio_t*)0,cp,"w")))
+ errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp);
+ if(fstat(sffileno(out),&statb) >=0)
+ chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH);
+ }
+ else
+ out = sfstdout;
+ if(dflag)
+ {
+ sh_onoption(SH_DICTIONARY);
+ sh_onoption(SH_NOEXEC);
+ }
+ if(nflag)
+ sh_onoption(SH_NOEXEC);
+ if(vflag)
+ sh_onoption(SH_VERBOSE);
+ if(!dflag)
+ sfwrite(out,header,sizeof(header));
+ shp->inlineno = 1;
+#if SHOPT_BRACEPAT
+ sh_onoption(SH_BRACEEXPAND);
+#endif
+ while(1)
+ {
+ stakset((char*)0,0);
+ if(t = (Shnode_t*)sh_parse(shp,in,0))
+ {
+ if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0)
+ sh_exec(t,0);
+ if(!dflag && sh_tdump(out,t) < 0)
+ errormsg(SH_DICT,ERROR_exit(1),"dump failed");
+ }
+ else if(sfeof(in))
+ break;
+ if(sferror(in))
+ errormsg(SH_DICT,ERROR_system(1),"I/O error");
+ if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np)))
+ {
+ if(strcmp(cp,"exit")==0)
+ break;
+ /* check for exec of a command */
+ if(strcmp(cp,"exec")==0)
+ {
+ if(t->com.comtyp&COMSCAN)
+ {
+ if(t->com.comarg->argnxt.ap)
+ break;
+ }
+ else
+ {
+ struct dolnod *ap = (struct dolnod*)t->com.comarg;
+ if(ap->dolnum>1)
+ break;
+ }
+ }
+ }
+ }
+ /* copy any remaining input */
+ sfmove(in,out,SF_UNBOUND,-1);
+ if(in!=sfstdin)
+ sfclose(in);
+ if(out!=sfstdout)
+ sfclose(out);
+ return(0);
+}
diff --git a/src/cmd/ksh93/sh/streval.c b/src/cmd/ksh93/sh/streval.c
new file mode 100644
index 0000000..d13e0f8
--- /dev/null
+++ b/src/cmd/ksh93/sh/streval.c
@@ -0,0 +1,1023 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * D. G. Korn
+ * AT&T Labs
+ *
+ * arithmetic expression evaluator
+ *
+ * this version compiles the expression onto a stack
+ * and has a separate executor
+ */
+
+#include "streval.h"
+#include <ctype.h>
+#include <error.h>
+#include <stak.h>
+#include "FEATURE/externs"
+#include "defs.h" /* for sh.decomma */
+
+#ifndef ERROR_dictionary
+# define ERROR_dictionary(s) (s)
+#endif
+#ifndef SH_DICT
+# define SH_DICT "libshell"
+#endif
+
+#define MAXLEVEL 9
+#define SMALL_STACK 12
+
+/*
+ * The following are used with tokenbits() macro
+ */
+#define T_OP 0x3f /* mask for operator number */
+#define T_BINARY 0x40 /* binary operators */
+#define T_NOFLOAT 0x80 /* non floating point operator */
+#define A_LVALUE (2*MAXPREC+2)
+
+#define pow2size(x) ((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64)
+#define round(x,size) (((x)+(size)-1)&~((size)-1))
+#define stakpush(v,val,type) ((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\
+ stakseek((v)->offset+sizeof(type)), \
+ *((type*)stakptr((v)->offset)) = (val)),(v)->offset)
+#define roundptr(ep,cp,type) (((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type))))
+
+static int level;
+
+struct vars /* vars stacked per invocation */
+{
+ Shell_t *shp;
+ const char *expr; /* current expression */
+ const char *nextchr; /* next char in current expression */
+ const char *errchr; /* next char after error */
+ const char *errstr; /* error string */
+ struct lval errmsg; /* error message text */
+ int offset; /* offset for pushchr macro */
+ int staksize; /* current stack size needed */
+ int stakmaxsize; /* maximum stack size needed */
+ unsigned char paren; /* parenthesis level */
+ char infun; /* incremented by comma inside function */
+ int emode;
+ Sfdouble_t (*convert)(const char**,struct lval*,int,Sfdouble_t);
+};
+
+typedef Sfdouble_t (*Math_f)(Sfdouble_t,...);
+typedef Sfdouble_t (*Math_1f_f)(Sfdouble_t);
+typedef int (*Math_1i_f)(Sfdouble_t);
+typedef Sfdouble_t (*Math_2f_f)(Sfdouble_t,Sfdouble_t);
+typedef Sfdouble_t (*Math_2f_i)(Sfdouble_t,int);
+typedef int (*Math_2i_f)(Sfdouble_t,Sfdouble_t);
+typedef Sfdouble_t (*Math_3f_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
+typedef int (*Math_3i_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
+
+#define getchr(vp) (*(vp)->nextchr++)
+#define peekchr(vp) (*(vp)->nextchr)
+#define ungetchr(vp) ((vp)->nextchr--)
+
+#if ('a'==97) /* ASCII encodings */
+# define getop(c) (((c) >= sizeof(strval_states))? \
+ ((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\
+ strval_states[(c)])
+#else
+# define getop(c) (isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \
+ (c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \
+ (c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \
+ (c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \
+ (c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \
+ (c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \
+ (c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \
+ (c=='\''?A_LIT: \
+ (c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG)))))))))))))))))))))))
+#endif
+
+#define seterror(v,msg) _seterror(v,ERROR_dictionary(msg))
+#define ERROR(vp,msg) return(seterror((vp),msg))
+
+/*
+ * set error message string and return(0)
+ */
+static int _seterror(struct vars *vp,const char *msg)
+{
+ if(!vp->errmsg.value)
+ vp->errmsg.value = (char*)msg;
+ vp->errchr = vp->nextchr;
+ vp->nextchr = "";
+ level = 0;
+ return(0);
+}
+
+
+static void arith_error(const char *message,const char *expr, int mode)
+{
+ level = 0;
+ mode = (mode&3)!=0;
+ errormsg(SH_DICT,ERROR_exit(mode),message,expr);
+}
+
+#if _ast_no_um2fm
+static Sfdouble_t U2F(Sfulong_t u)
+{
+ Sflong_t s = u;
+ Sfdouble_t f;
+
+ if (s >= 0)
+ return s;
+ s = u / 2;
+ f = s;
+ f *= 2;
+ if (u & 1)
+ f++;
+ return f;
+}
+#else
+#define U2F(x) x
+#endif
+
+Sfdouble_t arith_exec(Arith_t *ep)
+{
+ register Sfdouble_t num=0,*dp,*sp;
+ register unsigned char *cp = ep->code;
+ register int c,type=0;
+ register char *tp;
+ Sfdouble_t small_stack[SMALL_STACK+1],arg[9];
+ const char *ptr = "";
+ char *lastval=0;
+ int lastsub;
+ Math_f fun;
+ struct lval node;
+ Shell_t *shp = ep->shp;
+ node.shp = shp;
+ node.emode = ep->emode;
+ node.expr = ep->expr;
+ node.elen = ep->elen;
+ node.value = 0;
+ node.nosub = 0;
+ node.ptr = 0;
+ node.eflag = 0;
+ if(level++ >=MAXLEVEL)
+ {
+ arith_error(e_recursive,ep->expr,ep->emode);
+ return(0);
+ }
+ if(ep->staksize < SMALL_STACK)
+ sp = small_stack;
+ else
+ sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1));
+ tp = (char*)(sp+ep->staksize);
+ tp--,sp--;
+ while(c = *cp++)
+ {
+ if(c&T_NOFLOAT)
+ {
+ if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD && tp[-1]==1))
+ arith_error(e_incompatible,ep->expr,ep->emode);
+ }
+ switch(c&T_OP)
+ {
+ case A_JMP: case A_JMPZ: case A_JMPNZ:
+ c &= T_OP;
+ cp = roundptr(ep,cp,short);
+ if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num))
+ cp += sizeof(short);
+ else
+ cp = (unsigned char*)ep + *((short*)cp);
+ continue;
+ case A_NOTNOT:
+ num = (num!=0);
+ type=0;
+ break;
+ case A_PLUSPLUS:
+ node.nosub = -1;
+ (*ep->fun)(&ptr,&node,ASSIGN,num+1);
+ break;
+ case A_MINUSMINUS:
+ node.nosub = -1;
+ (*ep->fun)(&ptr,&node,ASSIGN,num-1);
+ break;
+ case A_INCR:
+ num = num+1;
+ node.nosub = -1;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,num);
+ break;
+ case A_DECR:
+ num = num-1;
+ node.nosub = -1;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,num);
+ break;
+ case A_SWAP:
+ num = sp[-1];
+ sp[-1] = *sp;
+ type = tp[-1];
+ tp[-1] = *tp;
+ break;
+ case A_POP:
+ sp--;
+ continue;
+ case A_ASSIGNOP1:
+ node.emode |= ARITH_ASSIGNOP;
+ case A_PUSHV:
+ cp = roundptr(ep,cp,Sfdouble_t*);
+ dp = *((Sfdouble_t**)cp);
+ cp += sizeof(Sfdouble_t*);
+ c = *(short*)cp;
+ cp += sizeof(short);
+ lastval = node.value = (char*)dp;
+ if(node.flag = c)
+ lastval = 0;
+ node.isfloat=0;
+ node.level = level;
+ node.nosub = 0;
+ num = (*ep->fun)(&ptr,&node,VALUE,num);
+ if(node.emode&ARITH_ASSIGNOP)
+ {
+ lastsub = node.nosub;
+ node.nosub = 0;
+ node.emode &= ~ARITH_ASSIGNOP;
+ }
+ if(node.value != (char*)dp)
+ arith_error(node.value,ptr,ep->emode);
+ *++sp = num;
+ type = node.isfloat;
+ if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
+ type = 1;
+ else
+ {
+ Sfdouble_t d=num;
+ if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX)
+ {
+ type = 2;
+ d -= LDBL_LLONG_MAX;
+ }
+ if((Sflong_t)d!=d)
+ type = 1;
+ }
+ *++tp = type;
+ c = 0;
+ break;
+ case A_ENUM:
+ node.eflag = 1;
+ continue;
+ case A_ASSIGNOP:
+ node.nosub = lastsub;
+ case A_STORE:
+ cp = roundptr(ep,cp,Sfdouble_t*);
+ dp = *((Sfdouble_t**)cp);
+ cp += sizeof(Sfdouble_t*);
+ c = *(short*)cp;
+ if(c<0)
+ c = 0;
+ cp += sizeof(short);
+ node.value = (char*)dp;
+ node.flag = c;
+ if(lastval)
+ node.eflag = 1;
+ node.ptr = 0;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,num);
+ if(lastval && node.ptr)
+ {
+ Sfdouble_t r;
+ node.flag = 0;
+ node.value = lastval;
+ r = (*ep->fun)(&ptr,&node,VALUE,num);
+ if(r!=num)
+ {
+ node.flag=c;
+ node.value = (char*)dp;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,r);
+ }
+
+ }
+ lastval = 0;
+ c=0;
+ break;
+ case A_PUSHF:
+ cp = roundptr(ep,cp,Math_f);
+ *++sp = (Sfdouble_t)(cp-ep->code);
+ cp += sizeof(Math_f);
+ *++tp = *cp++;
+ continue;
+ case A_PUSHN:
+ cp = roundptr(ep,cp,Sfdouble_t);
+ num = *((Sfdouble_t*)cp);
+ cp += sizeof(Sfdouble_t);
+ *++sp = num;
+ *++tp = type = *cp++;
+ break;
+ case A_NOT:
+ type=0;
+ num = !num;
+ break;
+ case A_UMINUS:
+ num = -num;
+ break;
+ case A_TILDE:
+ num = ~((Sflong_t)(num));
+ break;
+ case A_PLUS:
+ num += sp[-1];
+ break;
+ case A_MINUS:
+ num = sp[-1] - num;
+ break;
+ case A_TIMES:
+ num *= sp[-1];
+ break;
+ case A_POW:
+ num = pow(sp[-1],num);
+ break;
+ case A_MOD:
+ if(!(Sflong_t)num)
+ arith_error(e_divzero,ep->expr,ep->emode);
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) % (Sflong_t)(num);
+ break;
+ case A_DIV:
+ if(type==1 || tp[-1]==1)
+ {
+ num = sp[-1]/num;
+ type = 1;
+ }
+ else if((Sfulong_t)(num)==0)
+ arith_error(e_divzero,ep->expr,ep->emode);
+ else if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) / (Sflong_t)(num);
+ break;
+ case A_LSHIFT:
+ if(tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) << (long)(num));
+ else
+ num = (Sflong_t)(sp[-1]) << (long)(num);
+ break;
+ case A_RSHIFT:
+ if(tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) >> (long)(num));
+ else
+ num = (Sflong_t)(sp[-1]) >> (long)(num);
+ break;
+ case A_XOR:
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num);
+ break;
+ case A_OR:
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) | (Sflong_t)(num);
+ break;
+ case A_AND:
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) & (Sflong_t)(num);
+ break;
+ case A_EQ:
+ num = (sp[-1]==num);
+ type=0;
+ break;
+ case A_NEQ:
+ num = (sp[-1]!=num);
+ type=0;
+ break;
+ case A_LE:
+ num = (sp[-1]<=num);
+ type=0;
+ break;
+ case A_GE:
+ num = (sp[-1]>=num);
+ type=0;
+ break;
+ case A_GT:
+ num = (sp[-1]>num);
+ type=0;
+ break;
+ case A_LT:
+ num = (sp[-1]<num);
+ type=0;
+ break;
+ case A_CALL1F:
+ sp--,tp--;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ if(c&T_BINARY)
+ {
+ c &= ~T_BINARY;
+ arg[0] = num;
+ arg[1] = 0;
+ num = sh_mathfun(shp,(void*)fun,1,arg);
+ break;
+ }
+ num = (*((Math_1f_f)fun))(num);
+ break;
+ case A_CALL1I:
+ sp--,tp--;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ num = (*((Math_1i_f)fun))(num);
+ break;
+ case A_CALL2F:
+ sp-=2,tp-=2;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ if(c&T_BINARY)
+ {
+ c &= ~T_BINARY;
+ arg[0] = sp[1];
+ arg[1] = num;
+ arg[2] = 0;
+ num = sh_mathfun(shp,(void*)fun,2,arg);
+ break;
+ }
+ if(c&T_NOFLOAT)
+ num = (*((Math_2f_i)fun))(sp[1],(int)num);
+ else
+ num = (*((Math_2f_f)fun))(sp[1],num);
+ break;
+ case A_CALL2I:
+ sp-=2,tp-=2;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ num = (*((Math_2i_f)fun))(sp[1],num);
+ break;
+ case A_CALL3F:
+ sp-=3,tp-=3;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ if(c&T_BINARY)
+ {
+ c &= ~T_BINARY;
+ arg[0] = sp[1];
+ arg[1] = sp[2];
+ arg[2] = num;
+ arg[3] = 0;
+ num = sh_mathfun(shp,(void*)fun,3,arg);
+ break;
+ }
+ num = (*((Math_3f_f)fun))(sp[1],sp[2],num);
+ break;
+ }
+ if(c)
+ lastval = 0;
+ if(c&T_BINARY)
+ {
+ node.ptr = 0;
+ sp--,tp--;
+ type |= (*tp!=0);
+ }
+ *sp = num;
+ *tp = type;
+ }
+ if(level>0)
+ level--;
+ return(num);
+}
+
+/*
+ * This returns operator tokens or A_REG or A_NUM
+ */
+static int gettok(register struct vars *vp)
+{
+ register int c,op;
+ vp->errchr = vp->nextchr;
+ while(1)
+ {
+ c = getchr(vp);
+ switch(op=getop(c))
+ {
+ case 0:
+ vp->errchr = vp->nextchr;
+ continue;
+ case A_EOF:
+ vp->nextchr--;
+ break;
+ case A_COMMA:
+ if(vp->shp->decomma && (c=peekchr(vp))>='0' && c<='9')
+ {
+ op = A_DIG;
+ goto keep;
+ }
+ break;
+ case A_DOT:
+ if((c=peekchr(vp))>='0' && c<='9')
+ op = A_DIG;
+ else
+ op = A_REG;
+ /*FALL THRU*/
+ case A_DIG: case A_REG: case A_LIT:
+ keep:
+ ungetchr(vp);
+ break;
+ case A_QUEST:
+ if(peekchr(vp)==':')
+ {
+ getchr(vp);
+ op = A_QCOLON;
+ }
+ break;
+ case A_LT: case A_GT:
+ if(peekchr(vp)==c)
+ {
+ getchr(vp);
+ op -= 2;
+ break;
+ }
+ /* FALL THRU */
+ case A_NOT: case A_COLON:
+ c = '=';
+ /* FALL THRU */
+ case A_ASSIGN:
+ case A_TIMES:
+ case A_PLUS: case A_MINUS:
+ case A_OR: case A_AND:
+ if(peekchr(vp)==c)
+ {
+ getchr(vp);
+ op--;
+ }
+ }
+ return(op);
+ }
+}
+
+/*
+ * evaluate a subexpression with precedence
+ */
+
+static int expr(register struct vars *vp,register int precedence)
+{
+ register int c, op;
+ int invalid,wasop=0;
+ struct lval lvalue,assignop;
+ const char *pos;
+ Sfdouble_t d;
+
+ lvalue.value = 0;
+ lvalue.nargs = 0;
+ lvalue.fun = 0;
+ lvalue.shp = vp->shp;
+again:
+ op = gettok(vp);
+ c = 2*MAXPREC+1;
+ switch(op)
+ {
+ case A_PLUS:
+ goto again;
+ case A_EOF:
+ if(precedence>2)
+ ERROR(vp,e_moretokens);
+ return(1);
+ case A_MINUS:
+ op = A_UMINUS;
+ goto common;
+ case A_NOT:
+ goto common;
+ case A_MINUSMINUS:
+ c = A_LVALUE;
+ op = A_DECR|T_NOFLOAT;
+ goto common;
+ case A_PLUSPLUS:
+ c = A_LVALUE;
+ op = A_INCR|T_NOFLOAT;
+ /* FALL THRU */
+ case A_TILDE:
+ op |= T_NOFLOAT;
+ common:
+ if(!expr(vp,c))
+ return(0);
+ stakputc(op);
+ break;
+ default:
+ vp->nextchr = vp->errchr;
+ wasop = 1;
+ }
+ invalid = wasop;
+ while(1)
+ {
+ assignop.value = 0;
+ op = gettok(vp);
+ if(op==A_DIG || op==A_REG || op==A_LIT)
+ {
+ if(!wasop)
+ ERROR(vp,e_synbad);
+ goto number;
+ }
+ if(wasop++ && op!=A_LPAR)
+ ERROR(vp,e_synbad);
+ /* check for assignment operation */
+ if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN))
+ {
+ if((!lvalue.value || precedence > 3))
+ ERROR(vp,e_notlvalue);
+ if(precedence==3)
+ precedence = 2;
+ assignop = lvalue;
+ getchr(vp);
+ c = 3;
+ }
+ else
+ {
+ c = (strval_precedence[op]&PRECMASK);
+ if(c==MAXPREC || op==A_POW)
+ c++;
+ c *= 2;
+ }
+ /* from here on c is the new precedence level */
+ if(lvalue.value && (op!=A_ASSIGN))
+ {
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ if(op==A_EQ || op==A_NEQ)
+ stakputc(A_ENUM);
+ stakputc(assignop.value?A_ASSIGNOP1:A_PUSHV);
+ stakpush(vp,lvalue.value,char*);
+ if(lvalue.flag<0)
+ lvalue.flag = 0;
+ stakpush(vp,lvalue.flag,short);
+ if(vp->nextchr==0)
+ ERROR(vp,e_badnum);
+ if(!(strval_precedence[op]&SEQPOINT))
+ lvalue.value = 0;
+ invalid = 0;
+ }
+ else if(precedence==A_LVALUE)
+ ERROR(vp,e_notlvalue);
+ if(invalid && op>A_ASSIGN)
+ ERROR(vp,e_synbad);
+ if(precedence >= c)
+ goto done;
+ if(strval_precedence[op]&RASSOC)
+ c--;
+ if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT))
+ {
+ wasop = 0;
+ if(!expr(vp,c))
+ return(0);
+ }
+ switch(op)
+ {
+ case A_RPAR:
+ if(!vp->paren)
+ ERROR(vp,e_paren);
+ if(invalid)
+ ERROR(vp,e_synbad);
+ goto done;
+
+ case A_COMMA:
+ wasop = 0;
+ if(vp->infun)
+ vp->infun++;
+ else
+ {
+ stakputc(A_POP);
+ vp->staksize--;
+ }
+ if(!expr(vp,c))
+ {
+ stakseek(staktell()-1);
+ return(0);
+ }
+ lvalue.value = 0;
+ break;
+
+ case A_LPAR:
+ {
+ int infun = vp->infun;
+ int userfun=0;
+ Sfdouble_t (*fun)(Sfdouble_t,...);
+ int nargs = lvalue.nargs;
+ if(nargs<0)
+ nargs = -nargs;
+ fun = lvalue.fun;
+ lvalue.fun = 0;
+ if(fun)
+ {
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ vp->infun=1;
+ if((int)lvalue.nargs<0)
+ userfun = T_BINARY;
+ else if((int)lvalue.nargs&040)
+ userfun = T_NOFLOAT;
+ stakputc(A_PUSHF);
+ stakpush(vp,fun,Math_f);
+ stakputc(1);
+ }
+ else
+ vp->infun = 0;
+ if(!invalid)
+ ERROR(vp,e_synbad);
+ vp->paren++;
+ if(!expr(vp,1))
+ return(0);
+ vp->paren--;
+ if(fun)
+ {
+ int x= (nargs&010)?2:-1;
+ nargs &= 7;
+ if(vp->infun != nargs)
+ ERROR(vp,e_argcount);
+ if((vp->staksize+=nargs)>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize+nargs;
+ stakputc(A_CALL1F+userfun+nargs+x);
+ vp->staksize -= nargs;
+ }
+ vp->infun = infun;
+ if (gettok(vp) != A_RPAR)
+ ERROR(vp,e_paren);
+ wasop = 0;
+ break;
+ }
+
+ case A_PLUSPLUS:
+ case A_MINUSMINUS:
+ wasop=0;
+ op |= T_NOFLOAT;
+ case A_ASSIGN:
+ if(!lvalue.value)
+ ERROR(vp,e_notlvalue);
+ if(op==A_ASSIGN)
+ {
+ stakputc(A_STORE);
+ stakpush(vp,lvalue.value,char*);
+ stakpush(vp,lvalue.flag,short);
+ vp->staksize--;
+ }
+ else
+ stakputc(op);
+ lvalue.value = 0;
+ break;
+
+ case A_QUEST:
+ {
+ int offset1,offset2;
+ stakputc(A_JMPZ);
+ offset1 = stakpush(vp,0,short);
+ stakputc(A_POP);
+ if(!expr(vp,1))
+ return(0);
+ if(gettok(vp)!=A_COLON)
+ ERROR(vp,e_questcolon);
+ stakputc(A_JMP);
+ offset2 = stakpush(vp,0,short);
+ *((short*)stakptr(offset1)) = staktell();
+ stakputc(A_POP);
+ if(!expr(vp,3))
+ return(0);
+ *((short*)stakptr(offset2)) = staktell();
+ lvalue.value = 0;
+ wasop = 0;
+ break;
+ }
+
+ case A_COLON:
+ ERROR(vp,e_badcolon);
+ break;
+
+ case A_QCOLON:
+ case A_ANDAND:
+ case A_OROR:
+ {
+ int offset;
+ if(op==A_ANDAND)
+ op = A_JMPZ;
+ else
+ op = A_JMPNZ;
+ stakputc(op);
+ offset = stakpush(vp,0,short);
+ stakputc(A_POP);
+ if(!expr(vp,c))
+ return(0);
+ *((short*)stakptr(offset)) = staktell();
+ if(op!=A_QCOLON)
+ stakputc(A_NOTNOT);
+ lvalue.value = 0;
+ wasop=0;
+ break;
+ }
+ case A_AND: case A_OR: case A_XOR: case A_LSHIFT:
+ case A_RSHIFT: case A_MOD:
+ op |= T_NOFLOAT;
+ /* FALL THRU */
+ case A_PLUS: case A_MINUS: case A_TIMES: case A_DIV:
+ case A_EQ: case A_NEQ: case A_LT: case A_LE:
+ case A_GT: case A_GE: case A_POW:
+ stakputc(op|T_BINARY);
+ vp->staksize--;
+ break;
+ case A_NOT: case A_TILDE:
+ default:
+ ERROR(vp,e_synbad);
+ number:
+ wasop = 0;
+ if(*vp->nextchr=='L' && vp->nextchr[1]=='\'')
+ {
+ vp->nextchr++;
+ op = A_LIT;
+ }
+ pos = vp->nextchr;
+ lvalue.isfloat = 0;
+ lvalue.expr = vp->expr;
+ lvalue.emode = vp->emode;
+ if(op==A_LIT)
+ {
+ /* character constants */
+ if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'')
+ {
+ d = '\\';
+ vp->nextchr +=2;
+ }
+ else
+ d = chresc(pos+1,(char**)&vp->nextchr);
+ /* posix allows the trailing ' to be optional */
+ if(*vp->nextchr=='\'')
+ vp->nextchr++;
+ }
+ else
+ d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0);
+ if (vp->nextchr == pos)
+ {
+ if(vp->errmsg.value = lvalue.value)
+ vp->errstr = pos;
+ ERROR(vp,op==A_LIT?e_charconst:e_synbad);
+ }
+ if(op==A_DIG || op==A_LIT)
+ {
+ stakputc(A_PUSHN);
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ stakpush(vp,d,Sfdouble_t);
+ stakputc(lvalue.isfloat);
+ }
+
+ /* check for function call */
+ if(lvalue.fun)
+ continue;
+ break;
+ }
+ invalid = 0;
+ if(assignop.value)
+ {
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ if(assignop.flag<0)
+ assignop.flag = 0;
+ stakputc(c&1?A_ASSIGNOP:A_STORE);
+ stakpush(vp,assignop.value,char*);
+ stakpush(vp,assignop.flag,short);
+ }
+ }
+ done:
+ vp->nextchr = vp->errchr;
+ return(1);
+}
+
+Arith_t *arith_compile(Shell_t *shp,const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode)
+{
+ struct vars cur;
+ register Arith_t *ep;
+ int offset;
+ memset((void*)&cur,0,sizeof(cur));
+ cur.shp = shp;
+ cur.expr = cur.nextchr = string;
+ cur.convert = fun;
+ cur.emode = emode;
+ cur.errmsg.value = 0;
+ cur.errmsg.emode = emode;
+ stakseek(sizeof(Arith_t));
+ if(!expr(&cur,0) && cur.errmsg.value)
+ {
+ if(cur.errstr)
+ string = cur.errstr;
+ if((*fun)( &string , &cur.errmsg, MESSAGE, 0) < 0)
+ {
+ stakseek(0);
+ *last = (char*)Empty;
+ return(0);
+ }
+ cur.nextchr = cur.errchr;
+ }
+ stakputc(0);
+ offset = staktell();
+ ep = (Arith_t*)stakfreeze(0);
+ ep->shp = shp;
+ ep->expr = string;
+ ep->elen = strlen(string);
+ ep->code = (unsigned char*)(ep+1);
+ ep->fun = fun;
+ ep->emode = emode;
+ ep->size = offset - sizeof(Arith_t);
+ ep->staksize = cur.stakmaxsize+1;
+ if(last)
+ *last = (char*)(cur.nextchr);
+ return(ep);
+}
+
+/*
+ * evaluate an integer arithmetic expression in s
+ *
+ * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value)
+ * is a user supplied conversion routine that is called when unknown
+ * chars are encountered.
+ * *end points to the part to be converted and must be adjusted by convert to
+ * point to the next non-converted character; if typ is MESSAGE then string
+ * points to an error message string
+ *
+ * NOTE: (*convert)() may call strval()
+ */
+
+Sfdouble_t strval(Shell_t *shp,const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode)
+{
+ Arith_t *ep;
+ Sfdouble_t d;
+ char *sp=0;
+ int offset;
+ if(offset=staktell())
+ sp = stakfreeze(1);
+ ep = arith_compile(shp,s,end,conv,emode);
+ ep->emode = emode;
+ d = arith_exec(ep);
+ stakset(sp?sp:(char*)ep,offset);
+ return(d);
+}
+
+#if _mem_name__exception
+#undef _mem_name_exception
+#define _mem_name_exception 1
+#undef exception
+#define exception _exception
+#undef matherr
+#endif
+
+#if _mem_name_exception
+
+#undef error
+
+#if _BLD_shell && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#ifndef DOMAIN
+#define DOMAIN _DOMAIN
+#endif
+#ifndef OVERFLOW
+#define OVERFLOW _OVERFLOW
+#endif
+#ifndef SING
+#define SING _SING
+#endif
+
+ extern int matherr(struct exception *ep)
+ {
+ const char *message;
+ switch(ep->type)
+ {
+#ifdef DOMAIN
+ case DOMAIN:
+ message = ERROR_dictionary(e_domain);
+ break;
+#endif
+#ifdef OVERFLOW
+ case OVERFLOW:
+ message = ERROR_dictionary(e_overflow);
+ break;
+#endif
+#ifdef SING
+ case SING:
+ message = ERROR_dictionary(e_singularity);
+ break;
+#endif
+ default:
+ return(1);
+ }
+ level=0;
+ errormsg(SH_DICT,ERROR_exit(1),message,ep->name);
+ return(0);
+ }
+
+#undef extern
+
+#endif /* _mem_name_exception */
diff --git a/src/cmd/ksh93/sh/string.c b/src/cmd/ksh93/sh/string.c
new file mode 100644
index 0000000..2765e8d
--- /dev/null
+++ b/src/cmd/ksh93/sh/string.c
@@ -0,0 +1,730 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * string processing routines for Korn shell
+ *
+ */
+
+#include <ast.h>
+#include <ast_wchar.h>
+#include "defs.h"
+#include <stak.h>
+#include <ccode.h>
+#include "shtable.h"
+#include "lexstates.h"
+#include "national.h"
+
+#if _hdr_wctype
+# include <wctype.h>
+#endif
+
+#if !_lib_iswprint && !defined(iswprint)
+# define iswprint(c) (((c)&~0377) || isprint(c))
+#endif
+
+
+/*
+ * Table lookup routine
+ * <table> is searched for string <sp> and corresponding value is returned
+ * This is only used for small tables and is used to save non-sharable memory
+ */
+
+const Shtable_t *sh_locate(register const char *sp,const Shtable_t *table,int size)
+{
+ register int first;
+ register const Shtable_t *tp;
+ register int c;
+ static const Shtable_t empty = {0,0};
+ if(sp==0 || (first= *sp)==0)
+ return(&empty);
+ tp=table;
+ while((c= *tp->sh_name) && (CC_NATIVE!=CC_ASCII || c <= first))
+ {
+ if(first == c && strcmp(sp,tp->sh_name)==0)
+ return(tp);
+ tp = (Shtable_t*)((char*)tp+size);
+ }
+ return(&empty);
+}
+
+/*
+ * shtab_options lookup routine
+ */
+
+#define sep(c) ((c)=='-'||(c)=='_')
+
+int sh_lookopt(register const char *sp, int *invert)
+{
+ register int first;
+ register const Shtable_t *tp;
+ register int c;
+ register const char *s, *t, *sw, *tw;
+ int amb;
+ int hit;
+ int inv;
+ int no;
+ if(sp==0)
+ return(0);
+ if(*sp=='n' && *(sp+1)=='o' && (*(sp+2)!='t' || *(sp+3)!='i'))
+ {
+ sp+=2;
+ if(sep(*sp))
+ sp++;
+ *invert = !*invert;
+ }
+ if((first= *sp)==0)
+ return(0);
+ tp=shtab_options;
+ amb=hit=0;
+ for(;;)
+ {
+ t=tp->sh_name;
+ if(no = *t=='n' && *(t+1)=='o' && *(t+2)!='t')
+ t+=2;
+ if(!(c= *t))
+ break;
+ if(first == c)
+ {
+ if(strcmp(sp,t)==0)
+ {
+ *invert ^= no;
+ return(tp->sh_number);
+ }
+ s=sw=sp;
+ tw=t;
+ for(;;)
+ {
+ if(!*s || *s=='=')
+ {
+ if (*s == '=' && !strtol(s+1, NiL, 0))
+ no = !no;
+ if (!*t)
+ {
+ *invert ^= no;
+ return(tp->sh_number);
+ }
+ if (hit || amb)
+ {
+ hit = 0;
+ amb = 1;
+ }
+ else
+ {
+ hit = tp->sh_number;
+ inv = no;
+ }
+ break;
+ }
+ else if(!*t)
+ break;
+ else if(sep(*s))
+ sw = ++s;
+ else if(sep(*t))
+ tw = ++t;
+ else if(*s==*t)
+ {
+ s++;
+ t++;
+ }
+ else if(s==sw && t==tw)
+ break;
+ else
+ {
+ if(t!=tw)
+ {
+ while(*t && !sep(*t))
+ t++;
+ if(!*t)
+ break;
+ tw = ++t;
+ }
+ while (s>sw && *s!=*t)
+ s--;
+ }
+ }
+ }
+ tp = (Shtable_t*)((char*)tp+sizeof(*shtab_options));
+ }
+ if(hit)
+ *invert ^= inv;
+ return(hit);
+}
+
+/*
+ * look for the substring <oldsp> in <string> and replace with <newsp>
+ * The new string is put on top of the stack
+ */
+char *sh_substitute(const char *string,const char *oldsp,char *newsp)
+/*@
+ assume string!=NULL && oldsp!=NULL && newsp!=NULL;
+ return x satisfying x==NULL ||
+ strlen(x)==(strlen(in string)+strlen(in newsp)-strlen(in oldsp));
+@*/
+{
+ register const char *sp = string;
+ register const char *cp;
+ const char *savesp = 0;
+ stakseek(0);
+ if(*sp==0)
+ return((char*)0);
+ if(*(cp=oldsp) == 0)
+ goto found;
+#if SHOPT_MULTIBYTE
+ mbinit();
+#endif /* SHOPT_MULTIBYTE */
+ do
+ {
+ /* skip to first character which matches start of oldsp */
+ while(*sp && (savesp==sp || *sp != *cp))
+ {
+#if SHOPT_MULTIBYTE
+ /* skip a whole character at a time */
+ int c = mbsize(sp);
+ if(c < 0)
+ sp++;
+ while(c-- > 0)
+#endif /* SHOPT_MULTIBYTE */
+ stakputc(*sp++);
+ }
+ if(*sp == 0)
+ return((char*)0);
+ savesp = sp;
+ for(;*cp;cp++)
+ {
+ if(*cp != *sp++)
+ break;
+ }
+ if(*cp==0)
+ /* match found */
+ goto found;
+ sp = savesp;
+ cp = oldsp;
+ }
+ while(*sp);
+ return((char*)0);
+
+found:
+ /* copy new */
+ stakputs(newsp);
+ /* copy rest of string */
+ stakputs(sp);
+ return(stakfreeze(1));
+}
+
+/*
+ * TRIM(sp)
+ * Remove escape characters from characters in <sp> and eliminate quoted nulls.
+ */
+
+void sh_trim(register char *sp)
+/*@
+ assume sp!=NULL;
+ promise strlen(in sp) <= in strlen(sp);
+@*/
+{
+ register char *dp;
+ register int c;
+ if(sp)
+ {
+ dp = sp;
+ while(c= *sp)
+ {
+#if SHOPT_MULTIBYTE
+ int len;
+ if(mbwide() && (len=mbsize(sp))>1)
+ {
+ memmove(dp, sp, len);
+ dp += len;
+ sp += len;
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ sp++;
+ if(c == '\\')
+ c = *sp++;
+ if(c)
+ *dp++ = c;
+ }
+ *dp = 0;
+ }
+}
+
+/*
+ * copy <str1> to <str2> changing upper case to lower case
+ * <str2> must be big enough to hold <str1>
+ * <str1> and <str2> may point to the same place.
+ */
+
+void sh_utol(register char const *str1,register char *str2)
+/*@
+ assume str1!=0 && str2!=0
+ return x satisfying strlen(in str1)==strlen(in str2);
+@*/
+{
+ register int c;
+ for(; c= *((unsigned char*)str1); str1++,str2++)
+ {
+ if(isupper(c))
+ *str2 = tolower(c);
+ else
+ *str2 = c;
+ }
+ *str2 = 0;
+}
+
+/*
+ * format string as a csv field
+ */
+static char *sh_fmtcsv(const char *string)
+{
+ register const char *cp = string, *op;
+ register int c;
+ int offset;
+ if(!cp)
+ return((char*)0);
+ offset = staktell();
+ while((c=mbchar(cp)),isaname(c));
+ if(c==0)
+ return((char*)string);
+ stakputc('"');
+ stakwrite(string,cp-string);
+ if(c=='"')
+ stakputc('"');
+ string = cp;
+ while(c=mbchar(cp))
+ {
+ if(c=='"')
+ {
+ stakwrite(string,cp-string);
+ string = cp;
+ stakputc('"');
+ }
+ }
+ if(--cp>string)
+ stakwrite(string,cp-string);
+ stakputc('"');
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+/*
+ * print <str> quoting chars so that it can be read by the shell
+ * puts null terminated result on stack, but doesn't freeze it
+ */
+char *sh_fmtq(const char *string)
+{
+ register const char *cp = string, *op;
+ register int c, state;
+ int offset;
+ if(!cp)
+ return((char*)0);
+ offset = staktell();
+ state = ((c= mbchar(cp))==0);
+ if(isaletter(c))
+ {
+ while((c=mbchar(cp)),isaname(c));
+ if(c==0)
+ return((char*)string);
+ if(c=='=')
+ {
+ if(*cp==0)
+ return((char*)string);
+ if(*cp=='=')
+ cp++;
+ c = cp - string;
+ stakwrite(string,c);
+ string = cp;
+ c = mbchar(cp);
+ }
+ }
+ if(c==0 || c=='#' || c=='~')
+ state = 1;
+ for(;c;c= mbchar(cp))
+ {
+#if SHOPT_MULTIBYTE
+ if(c=='\'' || !iswprint(c))
+#else
+ if(c=='\'' || !isprint(c))
+#endif /* SHOPT_MULTIBYTE */
+ state = 2;
+ else if(c==']' || c=='=' || (c!=':' && c<=0x7f && (c=sh_lexstates[ST_NORM][c]) && c!=S_EPAT))
+ state |=1;
+ }
+ if(state<2)
+ {
+ if(state==1)
+ stakputc('\'');
+ if(c = --cp - string)
+ stakwrite(string,c);
+ if(state==1)
+ stakputc('\'');
+ }
+ else
+ {
+ stakwrite("$'",2);
+ cp = string;
+#if SHOPT_MULTIBYTE
+ while(op = cp, c= mbchar(cp))
+#else
+ while(op = cp, c= *(unsigned char*)cp++)
+#endif
+ {
+ state=1;
+ switch(c)
+ {
+ case ('a'==97?'\033':39):
+ c = 'E';
+ break;
+ case '\n':
+ c = 'n';
+ break;
+ case '\r':
+ c = 'r';
+ break;
+ case '\t':
+ c = 't';
+ break;
+ case '\f':
+ c = 'f';
+ break;
+ case '\b':
+ c = 'b';
+ break;
+ case '\a':
+ c = 'a';
+ break;
+ case '\\': case '\'':
+ break;
+ default:
+#if SHOPT_MULTIBYTE
+ if(!iswprint(c))
+ {
+ while(op<cp)
+ sfprintf(staksp,"\\%.3o",*(unsigned char*)op++);
+ continue;
+ }
+#else
+ if(!isprint(c))
+ {
+ sfprintf(staksp,"\\%.3o",c);
+ continue;
+ }
+#endif
+ state=0;
+ break;
+ }
+ if(state)
+ {
+ stakputc('\\');
+ stakputc(c);
+ }
+ else
+ stakwrite(op, cp-op);
+ }
+ stakputc('\'');
+ }
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+/*
+ * print <str> quoting chars so that it can be read by the shell
+ * puts null terminated result on stack, but doesn't freeze it
+ * single!=0 limits quoting to '...'
+ * fold>0 prints raw newlines and inserts appropriately
+ * escaped newlines every (fold-x) chars
+ */
+char *sh_fmtqf(const char *string, int single, int fold)
+{
+ register const char *cp = string;
+ register const char *bp;
+ register const char *vp;
+ register int c;
+ register int n;
+ register int q;
+ register int a;
+ int offset;
+
+ if (--fold < 8)
+ fold = 0;
+ if(single)
+ return sh_fmtcsv(cp);
+ if (!cp || !*cp || !fold || fold && strlen(string) < fold)
+ return sh_fmtq(cp);
+ offset = staktell();
+ single = single ? 1 : 3;
+ c = mbchar(string);
+ a = isaletter(c) ? '=' : 0;
+ vp = cp + 1;
+ do
+ {
+ q = 0;
+ n = fold;
+ bp = cp;
+ while ((!n || n-- > 0) && (c = mbchar(cp)))
+ {
+ if (a && !isaname(c))
+ a = 0;
+#if SHOPT_MULTIBYTE
+ if (c >= 0x200)
+ continue;
+ if (c == '\'' || !iswprint(c))
+#else
+ if (c == '\'' || !isprint(c))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ q = single;
+ break;
+ }
+ if (c == '\n')
+ q = 1;
+ else if (c == a)
+ {
+ stakwrite(bp, cp - bp);
+ bp = cp;
+ vp = cp + 1;
+ a = 0;
+ }
+ else if ((c == '#' || c == '~') && cp == vp || c == ']' || c != ':' && (c = sh_lexstates[ST_NORM][c]) && c != S_EPAT)
+ q = 1;
+ }
+ if (q & 2)
+ {
+ stakputc('$');
+ stakputc('\'');
+ cp = bp;
+ n = fold - 3;
+ q = 1;
+ while (c = mbchar(cp))
+ {
+ switch (c)
+ {
+ case ('a'==97?'\033':39):
+ c = 'E';
+ break;
+ case '\n':
+ q = 0;
+ n = fold - 1;
+ break;
+ case '\r':
+ c = 'r';
+ break;
+ case '\t':
+ c = 't';
+ break;
+ case '\f':
+ c = 'f';
+ break;
+ case '\b':
+ c = 'b';
+ break;
+ case '\a':
+ c = 'a';
+ break;
+ case '\\':
+ if (*cp == 'n')
+ {
+ c = '\n';
+ q = 0;
+ n = fold - 1;
+ break;
+ }
+ case '\'':
+ break;
+ default:
+#if SHOPT_MULTIBYTE
+ if(!iswprint(c))
+#else
+ if(!isprint(c))
+#endif
+ {
+ if ((n -= 4) <= 0)
+ {
+ stakwrite("'\\\n$'", 5);
+ n = fold - 7;
+ }
+ sfprintf(staksp, "\\%03o", c);
+ continue;
+ }
+ q = 0;
+ break;
+ }
+ if ((n -= q + 1) <= 0)
+ {
+ if (!q)
+ {
+ stakputc('\'');
+ cp = bp;
+ break;
+ }
+ stakwrite("'\\\n$'", 5);
+ n = fold - 5;
+ }
+ if (q)
+ stakputc('\\');
+ else
+ q = 1;
+ stakputc(c);
+ bp = cp;
+ }
+ if (!c)
+ stakputc('\'');
+ }
+ else if (q & 1)
+ {
+ stakputc('\'');
+ cp = bp;
+ n = fold ? (fold - 2) : 0;
+ while (c = mbchar(cp))
+ {
+ if (c == '\n')
+ n = fold - 1;
+ else if (n && --n <= 0)
+ {
+ n = fold - 2;
+ stakwrite(bp, --cp - bp);
+ bp = cp;
+ stakwrite("'\\\n'", 4);
+ }
+ else if (n == 1 && *cp == '\'')
+ {
+ n = fold - 5;
+ stakwrite(bp, --cp - bp);
+ bp = cp;
+ stakwrite("'\\\n\\''", 6);
+ }
+ else if (c == '\'')
+ {
+ stakwrite(bp, cp - bp - 1);
+ bp = cp;
+ if (n && (n -= 4) <= 0)
+ {
+ n = fold - 5;
+ stakwrite("'\\\n\\''", 6);
+ }
+ else
+ stakwrite("'\\''", 4);
+ }
+ }
+ stakwrite(bp, cp - bp - 1);
+ stakputc('\'');
+ }
+ else if (n = fold)
+ {
+ cp = bp;
+ while (c = mbchar(cp))
+ {
+ if (--n <= 0)
+ {
+ n = fold;
+ stakwrite(bp, --cp - bp);
+ bp = cp;
+ stakwrite("\\\n", 2);
+ }
+ }
+ stakwrite(bp, cp - bp - 1);
+ }
+ else
+ stakwrite(bp, cp - bp);
+ if (c)
+ {
+ stakputc('\\');
+ stakputc('\n');
+ }
+ } while (c);
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+#if SHOPT_MULTIBYTE
+ int sh_strchr(const char *string, register const char *dp)
+ {
+ wchar_t c, d;
+ register const char *cp=string;
+ mbinit();
+ d = mbchar(dp);
+ mbinit();
+ while(c = mbchar(cp))
+ {
+ if(c==d)
+ return(cp-string);
+ }
+ if(d==0)
+ return(cp-string);
+ return(-1);
+ }
+#endif /* SHOPT_MULTIBYTE */
+
+const char *_sh_translate(const char *message)
+{
+#if ERROR_VERSION >= 20000317L
+ return(ERROR_translate(0,0,e_dict,message));
+#else
+#if ERROR_VERSION >= 20000101L
+ return(ERROR_translate(e_dict,message));
+#else
+ return(ERROR_translate(message,1));
+#endif
+#endif
+}
+
+/*
+ * change '['identifier']' to identifier
+ * character before <str> must be a '['
+ * returns pointer to last character
+ */
+char *sh_checkid(char *str, char *last)
+{
+ register unsigned char *cp = (unsigned char*)str;
+ register unsigned char *v = cp;
+ register int c;
+ if(c=mbchar(cp),isaletter(c))
+ while(c=mbchar(cp),isaname(c));
+ if(c==']' && (!last || ((char*)cp==last)))
+ {
+ /* eliminate [ and ] */
+ while(v < cp)
+ {
+ v[-1] = *v;
+ v++;
+ }
+ if(last)
+ last -=2;
+ else
+ {
+ while(*v)
+ {
+ v[-2] = *v;
+ v++;
+ }
+ v[-2] = 0;
+ last = (char*)v;
+ }
+ }
+ return(last);
+}
+
+#if _AST_VERSION <= 20000317L
+char *fmtident(const char *string)
+{
+ return((char*)string);
+}
+#endif
diff --git a/src/cmd/ksh93/sh/subshell.c b/src/cmd/ksh93/sh/subshell.c
new file mode 100644
index 0000000..c7c022b
--- /dev/null
+++ b/src/cmd/ksh93/sh/subshell.c
@@ -0,0 +1,780 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Create and manage subshells avoiding forks when possible
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <ls.h>
+#include "io.h"
+#include "fault.h"
+#include "shnodes.h"
+#include "shlex.h"
+#include "jobs.h"
+#include "variables.h"
+#include "path.h"
+
+#ifndef PIPE_BUF
+# define PIPE_BUF 512
+#endif
+
+/*
+ * Note that the following structure must be the same
+ * size as the Dtlink_t structure
+ */
+struct Link
+{
+ struct Link *next;
+ Namval_t *child;
+ Dt_t *dict;
+ Namval_t *node;
+};
+
+/*
+ * The following structure is used for command substitution and (...)
+ */
+static struct subshell
+{
+ Shell_t *shp; /* shell interpreter */
+ struct subshell *prev; /* previous subshell data */
+ struct subshell *pipe; /* subshell where output goes to pipe on fork */
+ Dt_t *var; /* variable table at time of subshell */
+ struct Link *svar; /* save shell variable table */
+ Dt_t *sfun; /* function scope for subshell */
+ Dt_t *salias;/* alias scope for subshell */
+ Pathcomp_t *pathlist; /* for PATH variable */
+#if (ERROR_VERSION >= 20030214L)
+ struct Error_context_s *errcontext;
+#else
+ struct errorcontext *errcontext;
+#endif
+ Shopt_t options;/* save shell options */
+ pid_t subpid; /* child process id */
+ Sfio_t* saveout;/*saved standard output */
+ char *pwd; /* present working directory */
+ const char *shpwd; /* saved pointer to sh.pwd */
+ void *jobs; /* save job info */
+ mode_t mask; /* saved umask */
+ short tmpfd; /* saved tmp file descriptor */
+ short pipefd; /* read fd if pipe is created */
+ char jobcontrol;
+ char monitor;
+ unsigned char fdstatus;
+ int fdsaved; /* bit make for saved files */
+ int sig; /* signal for $$ */
+ pid_t bckpid;
+ pid_t cpid;
+ int coutpipe;
+ int cpipe;
+ int nofork;
+ int subdup;
+ char subshare;
+ char comsub;
+#if SHOPT_COSHELL
+ void *coshell;
+#endif /* SHOPT_COSHELL */
+} *subshell_data;
+
+static int subenv;
+
+
+/*
+ * This routine will turn the sftmp() file into a real /tmp file or pipe
+ * if the /tmp file create fails
+ */
+void sh_subtmpfile(Shell_t *shp)
+{
+ if(sfset(sfstdout,0,0)&SF_STRING)
+ {
+ register int fd;
+ register struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ register struct subshell *sp = subshell_data->pipe;
+ /* save file descriptor 1 if open */
+ if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX;
+ close(1);
+ }
+ else if(errno!=EBADF)
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ /* popping a discipline forces a /tmp file create */
+ sfdisc(sfstdout,SF_POPDISC);
+ if((fd=sffileno(sfstdout))<0)
+ {
+ /* unable to create the /tmp file so use a pipe */
+ int fds[3];
+ Sfoff_t off;
+ fds[2] = 0;
+ sh_pipe(fds);
+ sp->pipefd = fds[0];
+ sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC);
+ /* write the data to the pipe */
+ if(off = sftell(sfstdout))
+ write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
+ sfclose(sfstdout);
+ if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1)
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ sh_close(fds[1]);
+ }
+ else
+ {
+ shp->fdstatus[fd] = IOREAD|IOWRITE;
+ sfsync(sfstdout);
+ if(fd==1)
+ fcntl(1,F_SETFD,0);
+ else
+ {
+ sfsetfd(sfstdout,1);
+ shp->fdstatus[1] = shp->fdstatus[fd];
+ shp->fdstatus[fd] = IOCLOSE;
+ }
+ }
+ sh_iostream(shp,1);
+ sfset(sfstdout,SF_SHARE|SF_PUBLIC,1);
+ sfpool(sfstdout,shp->outpool,SF_WRITE);
+ if(pp && pp->olist && pp->olist->strm == sfstdout)
+ pp->olist->strm = 0;
+ }
+}
+
+
+/*
+ * This routine creates a temp file if necessary and creates a subshell.
+ * The parent routine longjmps back to sh_subshell()
+ * The child continues possibly with its standard output replaced by temp file
+ */
+void sh_subfork(void)
+{
+ register struct subshell *sp = subshell_data;
+ Shell_t *shp = sp->shp;
+ int curenv = shp->curenv;
+ pid_t pid;
+ char *trap = shp->st.trapcom[0];
+ if(trap)
+ trap = strdup(trap);
+ /* see whether inside $(...) */
+ if(sp->pipe)
+ sh_subtmpfile(shp);
+ shp->curenv = 0;
+ shp->savesig = -1;
+ if(pid = sh_fork(shp,FSHOWME,NIL(int*)))
+ {
+ shp->curenv = curenv;
+ /* this is the parent part of the fork */
+ if(sp->subpid==0)
+ sp->subpid = pid;
+ if(trap)
+ free((void*)trap);
+ siglongjmp(*shp->jmplist,SH_JMPSUB);
+ }
+ else
+ {
+ /* this is the child part of the fork */
+ /* setting subpid to 1 causes subshell to exit when reached */
+ sh_onstate(SH_FORKED);
+ sh_onstate(SH_NOLOG);
+ sh_offoption(SH_MONITOR);
+ sh_offstate(SH_MONITOR);
+ subshell_data = 0;
+ shp->subshell = 0;
+ shp->comsub = 0;
+ SH_SUBSHELLNOD->nvalue.s = 0;
+ sp->subpid=0;
+ shp->st.trapcom[0] = trap;
+ shp->savesig = 0;
+ }
+}
+
+int nv_subsaved(register Namval_t *np)
+{
+ register struct subshell *sp;
+ register struct Link *lp;
+ for(sp = (struct subshell*)subshell_data; sp; sp=sp->prev)
+ {
+ for(lp=sp->svar; lp; lp = lp->next)
+ {
+ if(lp->node==np)
+ return(1);
+ }
+ }
+ return(0);
+}
+
+/*
+ * This routine will make a copy of the given node in the
+ * layer created by the most recent subshell_fork if the
+ * node hasn't already been copied
+ */
+Namval_t *sh_assignok(register Namval_t *np,int add)
+{
+ register Namval_t *mp;
+ register struct Link *lp;
+ register struct subshell *sp = (struct subshell*)subshell_data;
+ Shell_t *shp = sp->shp;
+ Dt_t *dp= shp->var_tree;
+ Namval_t *mpnext;
+ Namarr_t *ap;
+ int save;
+ /* don't bother with this */
+ if(!sp->shpwd || np==SH_LEVELNOD || np==L_ARGNOD || np==SH_SUBSCRNOD || np==SH_NAMENOD)
+ return(np);
+ /* don't bother to save if in newer scope */
+ if(sp->var!=shp->var_tree && sp->var!=shp->var_base && shp->last_root==shp->var_tree)
+ return(np);
+ if((ap=nv_arrayptr(np)) && (mp=nv_opensub(np)))
+ {
+ shp->last_root = ap->table;
+ sh_assignok(mp,add);
+ if(!add || array_assoc(ap))
+ return(np);
+ }
+ for(lp=sp->svar; lp;lp = lp->next)
+ {
+ if(lp->node==np)
+ return(np);
+ }
+ /* first two pointers use linkage from np */
+ lp = (struct Link*)malloc(sizeof(*np)+2*sizeof(void*));
+ memset(lp,0, sizeof(*mp)+2*sizeof(void*));
+ lp->node = np;
+ if(!add && nv_isvtree(np))
+ {
+ Namval_t fake;
+ Dt_t *walk, *root=shp->var_tree;
+ char *name = nv_name(np);
+ int len = strlen(name);
+ fake.nvname = name;
+ mpnext = dtnext(root,&fake);
+ dp = root->walk?root->walk:root;
+ while(mp=mpnext)
+ {
+ walk = root->walk?root->walk:root;
+ mpnext = dtnext(root,mp);
+ if(memcmp(name,mp->nvname,len) || mp->nvname[len]!='.')
+ break;
+ nv_delete(mp,walk,NV_NOFREE);
+ *((Namval_t**)mp) = lp->child;
+ lp->child = mp;
+
+ }
+ }
+ lp->dict = dp;
+ mp = (Namval_t*)&lp->dict;
+ lp->next = subshell_data->svar;
+ subshell_data->svar = lp;
+ save = shp->subshell;
+ shp->subshell = 0;
+ mp->nvname = np->nvname;
+ if(nv_isattr(np,NV_NOFREE))
+ nv_onattr(mp,NV_IDENT);
+ nv_clone(np,mp,(add?(nv_isnull(np)?0:NV_NOFREE)|NV_ARRAY:NV_MOVE));
+ shp->subshell = save;
+ return(np);
+}
+
+/*
+ * restore the variables
+ */
+static void nv_restore(struct subshell *sp)
+{
+ register struct Link *lp, *lq;
+ register Namval_t *mp, *np;
+ const char *save = sp->shpwd;
+ Namval_t *mpnext;
+ int flags,nofree;
+ sp->shpwd = 0; /* make sure sh_assignok doesn't save with nv_unset() */
+ for(lp=sp->svar; lp; lp=lq)
+ {
+ np = (Namval_t*)&lp->dict;
+ lq = lp->next;
+ mp = lp->node;
+ if(!mp->nvname)
+ continue;
+ flags = 0;
+ if(nv_isattr(mp,NV_MINIMAL) && !nv_isattr(np,NV_EXPORT))
+ flags |= NV_MINIMAL;
+ if(nv_isarray(mp))
+ nv_putsub(mp,NIL(char*),ARRAY_SCAN);
+ nofree = mp->nvfun?mp->nvfun->nofree:0;
+ _nv_unset(mp,NV_RDONLY|NV_CLONE);
+ if(nv_isarray(np))
+ {
+ nv_clone(np,mp,NV_MOVE);
+ goto skip;
+ }
+ nv_setsize(mp,nv_size(np));
+ if(!(flags&NV_MINIMAL))
+ mp->nvenv = np->nvenv;
+ if(!nofree)
+ mp->nvfun = np->nvfun;
+ if(nv_isattr(np,NV_IDENT))
+ {
+ nv_offattr(np,NV_IDENT);
+ flags |= NV_NOFREE;
+ }
+ mp->nvflag = np->nvflag|(flags&NV_MINIMAL);
+ if(nv_cover(mp))
+ nv_putval(mp, nv_getval(np),np->nvflag|NV_NOFREE);
+ else
+ mp->nvalue.cp = np->nvalue.cp;
+ if(nofree && np->nvfun && !np->nvfun->nofree)
+ free((char*)np->nvfun);
+ np->nvfun = 0;
+ if(nv_isattr(mp,NV_EXPORT))
+ {
+ char *name = nv_name(mp);
+ sh_envput(sp->shp->env,mp);
+ if(*name=='_' && strcmp(name,"_AST_FEATURES")==0)
+ astconf(NiL, NiL, NiL);
+ }
+ else if(nv_isattr(np,NV_EXPORT))
+ env_delete(sp->shp->env,nv_name(mp));
+ nv_onattr(mp,flags);
+ skip:
+ for(mp=lp->child; mp; mp=mpnext)
+ {
+ mpnext = *((Namval_t**)mp);
+ dtinsert(lp->dict,mp);
+ }
+ free((void*)lp);
+ sp->svar = lq;
+ }
+ sp->shpwd=save;
+}
+
+/*
+ * return pointer to alias tree
+ * create new one if in a subshell and one doesn't exist and create is non-zero
+ */
+Dt_t *sh_subaliastree(int create)
+{
+ register struct subshell *sp = subshell_data;
+ if(!sp || sp->shp->curenv==0)
+ return(sh.alias_tree);
+ if(!sp->salias && create)
+ {
+ sp->salias = dtopen(&_Nvdisc,Dtoset);
+ dtview(sp->salias,sp->shp->alias_tree);
+ sp->shp->alias_tree = sp->salias;
+ }
+ return(sp->salias);
+}
+
+/*
+ * return pointer to function tree
+ * create new one if in a subshell and one doesn't exist and create is non-zero
+ */
+Dt_t *sh_subfuntree(int create)
+{
+ register struct subshell *sp = subshell_data;
+ if(!sp || sp->shp->curenv==0)
+ return(sh.fun_tree);
+ if(!sp->sfun && create)
+ {
+ sp->sfun = dtopen(&_Nvdisc,Dtoset);
+ dtview(sp->sfun,sp->shp->fun_tree);
+ sp->shp->fun_tree = sp->sfun;
+ }
+ return(sp->shp->fun_tree);
+}
+
+static void table_unset(register Dt_t *root,int fun)
+{
+ register Namval_t *np,*nq;
+ int flag;
+ for(np=(Namval_t*)dtfirst(root);np;np=nq)
+ {
+ nq = (Namval_t*)dtnext(root,np);
+ flag=0;
+ if(fun && np->nvalue.rp && np->nvalue.rp->fname && *np->nvalue.rp->fname=='/')
+ {
+ np->nvalue.rp->fdict = 0;
+ flag = NV_NOFREE;
+ }
+ else
+ _nv_unset(np,NV_RDONLY);
+ nv_delete(np,root,flag|NV_FUNCTION);
+ }
+}
+
+int sh_subsavefd(register int fd)
+{
+ register struct subshell *sp = subshell_data;
+ register int old=0;
+ if(sp)
+ {
+ old = !(sp->fdsaved&(1<<(fd-1)));
+ sp->fdsaved |= (1<<(fd-1));
+ }
+ return(old);
+}
+
+void sh_subjobcheck(pid_t pid)
+{
+ register struct subshell *sp = subshell_data;
+ while(sp)
+ {
+ if(sp->cpid==pid)
+ {
+ sh_close(sp->coutpipe);
+ sh_close(sp->cpipe);
+ sp->coutpipe = sp->cpipe = -1;
+ return;
+ }
+ sp = sp->prev;
+ }
+}
+
+/*
+ * Run command tree <t> in a virtual sub-shell
+ * If comsub is not null, then output will be placed in temp file (or buffer)
+ * If comsub is not null, the return value will be a stream consisting of
+ * output of command <t>. Otherwise, NULL will be returned.
+ */
+
+Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, int flags, int comsub)
+{
+ struct subshell sub_data;
+ register struct subshell *sp = &sub_data;
+ int jmpval,nsig=0,duped=0;
+ int savecurenv = shp->curenv;
+ int savejobpgid = job.curpgid;
+ int *saveexitval = job.exitval;
+ int16_t subshell;
+ char *savsig;
+ Sfio_t *iop=0;
+ struct checkpt buff;
+ struct sh_scoped savst;
+ struct dolnod *argsav=0;
+ int argcnt;
+ memset((char*)sp, 0, sizeof(*sp));
+ sfsync(shp->outpool);
+ sh_sigcheck(shp);
+ shp->savesig = -1;
+ if(argsav = sh_arguse(shp))
+ argcnt = argsav->dolrefcnt;
+ if(shp->curenv==0)
+ {
+ subshell_data=0;
+ subenv = 0;
+ }
+ shp->curenv = ++subenv;
+ savst = shp->st;
+ sh_pushcontext(shp,&buff,SH_JMPSUB);
+ subshell = shp->subshell+1;
+ SH_SUBSHELLNOD->nvalue.s = subshell;
+ shp->subshell = subshell;
+ sp->prev = subshell_data;
+ sp->shp = shp;
+ sp->sig = 0;
+ subshell_data = sp;
+ sp->errcontext = &buff.err;
+ sp->var = shp->var_tree;
+ sp->options = shp->options;
+ sp->jobs = job_subsave();
+ sp->subdup = shp->subdup;
+#if SHOPT_COSHELL
+ sp->coshell = shp->coshell;
+ shp->coshell = 0;
+#endif /* SHOPT_COSHELL */
+ /* make sure initialization has occurred */
+ if(!shp->pathlist)
+ {
+ shp->pathinit = 1;
+ path_get(shp,".");
+ shp->pathinit = 0;
+ }
+ sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
+ if(!shp->pwd)
+ path_pwd(shp,0);
+ sp->bckpid = shp->bckpid;
+ if(comsub)
+ sh_stats(STAT_COMSUB);
+ else
+ job.curpgid = 0;
+ sp->subshare = shp->subshare;
+ sp->comsub = shp->comsub;
+ shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
+ if(comsub)
+ shp->comsub = comsub;
+ if(!comsub || !shp->subshare)
+ {
+ sp->shpwd = shp->pwd;
+ sp->pwd = (shp->pwd?strdup(shp->pwd):0);
+ sp->mask = shp->mask;
+ sh_stats(STAT_SUBSHELL);
+ /* save trap table */
+ shp->st.otrapcom = 0;
+ if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
+ {
+ nsig += sizeof(char*);
+ memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
+ /* this nonsense needed for $(trap) */
+ shp->st.otrapcom = (char**)savsig;
+ }
+ sp->cpid = shp->cpid;
+ sp->coutpipe = shp->coutpipe;
+ sp->cpipe = shp->cpipe[1];
+ shp->cpid = 0;
+ sh_sigreset(0);
+ }
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval==0)
+ {
+ if(comsub)
+ {
+ /* disable job control */
+ shp->spid = 0;
+ sp->jobcontrol = job.jobcontrol;
+ sp->monitor = (sh_isstate(SH_MONITOR)!=0);
+ job.jobcontrol=0;
+ sh_offstate(SH_MONITOR);
+ sp->pipe = sp;
+ /* save sfstdout and status */
+ sp->saveout = sfswap(sfstdout,NIL(Sfio_t*));
+ sp->fdstatus = shp->fdstatus[1];
+ sp->tmpfd = -1;
+ sp->pipefd = -1;
+ /* use sftmp() file for standard output */
+ if(!(iop = sftmp(PIPE_BUF)))
+ {
+ sfswap(sp->saveout,sfstdout);
+ errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
+ }
+ sfswap(iop,sfstdout);
+ sfset(sfstdout,SF_READ,0);
+ shp->fdstatus[1] = IOWRITE;
+ if(!(sp->nofork = sh_state(SH_NOFORK)))
+ sh_onstate(SH_NOFORK);
+ flags |= sh_state(SH_NOFORK);
+ }
+ else if(sp->prev)
+ {
+ sp->pipe = sp->prev->pipe;
+ flags &= ~sh_state(SH_NOFORK);
+ }
+ if(shp->savesig < 0)
+ {
+ shp->savesig = 0;
+ sh_exec(t,flags);
+ }
+ }
+ if(comsub!=2 && jmpval!=SH_JMPSUB && shp->st.trapcom[0] && shp->subshell)
+ {
+ /* trap on EXIT not handled by child */
+ char *trap=shp->st.trapcom[0];
+ shp->st.trapcom[0] = 0; /* prevent recursion */
+ shp->oldexit = shp->exitval;
+ sh_trap(trap,0);
+ free(trap);
+ }
+ sh_popcontext(shp,&buff);
+ if(shp->subshell==0) /* must be child process */
+ {
+ subshell_data = sp->prev;
+ if(jmpval==SH_JMPSCRIPT)
+ siglongjmp(*shp->jmplist,jmpval);
+ shp->exitval &= SH_EXITMASK;
+ sh_done(shp,0);
+ }
+ if(!shp->savesig)
+ shp->savesig = -1;
+ if(comsub)
+ {
+ /* re-enable job control */
+ if(!sp->nofork)
+ sh_offstate(SH_NOFORK);
+ job.jobcontrol = sp->jobcontrol;
+ if(sp->monitor)
+ sh_onstate(SH_MONITOR);
+ if(sp->pipefd>=0)
+ {
+ /* sftmp() file has been returned into pipe */
+ iop = sh_iostream(shp,sp->pipefd);
+ sfclose(sfstdout);
+ }
+ else
+ {
+ /* move tmp file to iop and restore sfstdout */
+ iop = sfswap(sfstdout,NIL(Sfio_t*));
+ if(!iop)
+ {
+ /* maybe locked try again */
+ sfclrlock(sfstdout);
+ iop = sfswap(sfstdout,NIL(Sfio_t*));
+ }
+ if(iop && sffileno(iop)==1)
+ {
+ int fd=sfsetfd(iop,3);
+ if(fd<0)
+ {
+ shp->toomany = 1;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ }
+ if(fd >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ shp->sftable[fd] = iop;
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] = (shp->fdstatus[1]|IOCLEX);
+ shp->fdstatus[1] = IOCLOSE;
+ }
+ sfset(iop,SF_READ,1);
+ }
+ sfswap(sp->saveout,sfstdout);
+ /* check if standard output was preserved */
+ if(sp->tmpfd>=0)
+ {
+ close(1);
+ if (fcntl(sp->tmpfd,F_DUPFD,1) != 1)
+ duped++;
+ sh_close(sp->tmpfd);
+ }
+ shp->fdstatus[1] = sp->fdstatus;
+ }
+ path_delete((Pathcomp_t*)shp->pathlist);
+ shp->pathlist = (void*)sp->pathlist;
+ job_subrestore(sp->jobs);
+ shp->jobenv = savecurenv;
+ job.curpgid = savejobpgid;
+ job.exitval = saveexitval;
+ shp->bckpid = sp->bckpid;
+ if(sp->shpwd) /* restore environment if saved */
+ {
+ int n;
+ shp->options = sp->options;
+ nv_restore(sp);
+ if(sp->salias)
+ {
+ shp->alias_tree = dtview(sp->salias,0);
+ table_unset(sp->salias,0);
+ dtclose(sp->salias);
+ }
+ if(sp->sfun)
+ {
+ shp->fun_tree = dtview(sp->sfun,0);
+ table_unset(sp->sfun,1);
+ dtclose(sp->sfun);
+ }
+ n = shp->st.trapmax-savst.trapmax;
+ sh_sigreset(1);
+ if(n>0)
+ memset(&shp->st.trapcom[savst.trapmax],0,n*sizeof(char*));
+ shp->st = savst;
+ shp->curenv = savecurenv;
+ if(nsig)
+ {
+ memcpy((char*)&shp->st.trapcom[0],savsig,nsig);
+ free((void*)savsig);
+ }
+ shp->options = sp->options;
+ if(!shp->pwd || strcmp(sp->pwd,shp->pwd))
+ {
+ /* restore PWDNOD */
+ Namval_t *pwdnod = sh_scoped(shp,PWDNOD);
+ if(shp->pwd)
+ {
+ chdir(shp->pwd=sp->pwd);
+ path_newdir(shp,shp->pathlist);
+ }
+ if(nv_isattr(pwdnod,NV_NOFREE))
+ pwdnod->nvalue.cp = (const char*)sp->pwd;
+ }
+ else if(sp->shpwd != shp->pwd)
+ {
+ shp->pwd = sp->pwd;
+ if(PWDNOD->nvalue.cp==sp->shpwd)
+ PWDNOD->nvalue.cp = sp->pwd;
+ }
+ else
+ free((void*)sp->pwd);
+ if(sp->mask!=shp->mask)
+ umask(shp->mask=sp->mask);
+ if(shp->coutpipe!=sp->coutpipe)
+ {
+ sh_close(shp->coutpipe);
+ sh_close(shp->cpipe[1]);
+ }
+ shp->cpid = sp->cpid;
+ shp->cpipe[1] = sp->cpipe;
+ shp->coutpipe = sp->coutpipe;
+ }
+ shp->subshare = sp->subshare;
+ shp->comsub = sp->comsub;
+ shp->subdup = sp->subdup;
+#if SHOPT_COSHELL
+ shp->coshell = sp->coshell;
+#endif /* SHOPT_COSHELL */
+ if(shp->subshell)
+ SH_SUBSHELLNOD->nvalue.s = --shp->subshell;
+ subshell = shp->subshell;
+ subshell_data = sp->prev;
+ if(!argsav || argsav->dolrefcnt==argcnt)
+ sh_argfree(shp,argsav,0);
+ if(shp->topfd != buff.topfd)
+ sh_iorestore(shp,buff.topfd|IOSUBSHELL,jmpval);
+ if(sp->sig)
+ {
+ if(sp->prev)
+ sp->prev->sig = sp->sig;
+ else
+ {
+ sh_fault(sp->sig);
+ sh_chktrap(shp);
+ }
+ }
+ sh_sigcheck(shp);
+ shp->trapnote = 0;
+ nsig = shp->savesig;
+ shp->savesig = 0;
+ if(nsig>0)
+ sh_fault(nsig);
+ if(sp->subpid)
+ job_wait(sp->subpid);
+ if(comsub && iop && sp->pipefd<0)
+ sfseek(iop,(off_t)0,SEEK_SET);
+ if(shp->trapnote)
+ sh_chktrap(shp);
+ if(shp->exitval > SH_EXITSIG)
+ {
+ int sig = shp->exitval&SH_EXITMASK;
+ if(sig==SIGINT || sig== SIGQUIT)
+ sh_fault(sig);
+ }
+ if(duped)
+ {
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ shp->toomany = 1;
+ errormsg(SH_DICT,ERROR_system(1),e_redirect);
+ }
+ if(shp->ignsig)
+ sh_fault(shp->ignsig);
+ if(jmpval==SH_JMPSUB && shp->lastsig)
+ sh_fault(shp->lastsig);
+ if(jmpval && shp->toomany)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(iop);
+}
diff --git a/src/cmd/ksh93/sh/suid_exec.c b/src/cmd/ksh93/sh/suid_exec.c
new file mode 100644
index 0000000..a635b63
--- /dev/null
+++ b/src/cmd/ksh93/sh/suid_exec.c
@@ -0,0 +1,509 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * This is a program to execute 'execute only' and suid/sgid shell scripts.
+ * This program must be owned by root and must have the set uid bit set.
+ * It must not have the set group id bit set. This program must be installed
+ * where the define parameter THISPROG indicates to work correctly on system V
+ *
+ * Written by David Korn
+ * AT&T Labs
+ * Enhanced by Rob Stampfli
+ */
+
+/* The file name of the script to execute is argv[0]
+ * Argv[1] is the program name
+ * The basic idea is to open the script as standard input, set the effective
+ * user and group id correctly, and then exec the shell.
+ * The complicated part is getting the effective uid of the caller and
+ * setting the effective uid/gid. The program which execs this program
+ * may pass file descriptor FDIN as an open file with mode SPECIAL if
+ * the effective user id is not the real user id. The effective
+ * user id for authentication purposes will be the owner of this
+ * open file. On systems without the setreuid() call, e[ug]id is set
+ * by copying this program to a /tmp/file, making it a suid and/or sgid
+ * program, and then execing this program.
+ * A forked version of this program waits until it can unlink the /tmp
+ * file and then exits. Actually, we fork() twice so the parent can
+ * wait for the child to complete. A pipe is used to guarantee that we
+ * do not remove the /tmp file too soon.
+ */
+
+#include <ast.h>
+#include "FEATURE/externs"
+#include <ls.h>
+#include <sig.h>
+#include <error.h>
+#include <sys/wait.h>
+#include "version.h"
+
+#define SPECIAL 04100 /* setuid execute only by owner */
+#define FDIN 10 /* must be same as /dev/fd below */
+#undef FDSYNC
+#define FDSYNC 11 /* used on sys5 to synchronize cleanup */
+#define FDVERIFY 12 /* used to validate /tmp process */
+#undef BLKSIZE
+#define BLKSIZE sizeof(char*)*1024
+#define THISPROG "/etc/suid_exec"
+#define DEFSHELL "/bin/sh"
+
+static void error_exit(const char*);
+static int in_dir(const char*, const char*);
+static int endsh(const char*);
+#ifndef _lib_setregid
+# undef _lib_setreuid
+#endif
+#ifndef _lib_setreuid
+ static void setids(int,uid_t,gid_t);
+ static int mycopy(int, int);
+ static void maketemp(char*);
+#else
+ static void setids(int,int,int);
+#endif /* _lib_setreuid */
+
+static const char version[] = "\n@(#)$Id: suid_exec "SH_RELEASE" $\n";
+static const char badopen[] = "cannot open";
+static const char badexec[] = "cannot exec";
+static const char devfd[] = "/dev/fd/10"; /* must match FDIN above */
+static char tmpname[] = "/tmp/SUIDXXXXXX";
+static char **arglist;
+
+static char *shell;
+static char *command;
+static uid_t ruserid;
+static uid_t euserid;
+static gid_t rgroupid;
+static gid_t egroupid;
+static struct stat statb;
+
+int main(int argc,char *argv[])
+{
+ register int m,n;
+ register char *p;
+ struct stat statx;
+ int mode;
+ uid_t effuid;
+ gid_t effgid;
+ NOT_USED(argc);
+ arglist = argv;
+ if((command = argv[1]) == 0)
+ error_exit(badexec);
+ ruserid = getuid();
+ euserid = geteuid();
+ rgroupid = getgid();
+ egroupid = getegid();
+ p = argv[0];
+#ifndef _lib_setreuid
+ maketemp(tmpname);
+ if(strcmp(p,tmpname)==0)
+ {
+ /* At this point, the presumption is that we are the
+ * version of THISPROG copied into /tmp, with the owner,
+ * group, and setuid/gid bits correctly set. This copy of
+ * the program is executable by anyone, so we must be careful
+ * not to allow just any invocation of it to succeed, since
+ * it is setuid/gid. Validate the proper execution by
+ * examining the FDVERIFY file descriptor -- if it is owned
+ * by root and is mode SPECIAL, then this is proof that it was
+ * passed by a program with superuser privileges -- hence we
+ * can presume legitimacy. Otherwise, bail out, as we suspect
+ * an impostor.
+ */
+ if(fstat(FDVERIFY,&statb) < 0 || statb.st_uid != 0 ||
+ (statb.st_mode & ~S_IFMT) != SPECIAL || close(FDVERIFY)<0)
+ error_exit(badexec);
+ /* This enables the grandchild to clean up /tmp file */
+ close(FDSYNC);
+ /* Make sure that this is a valid invocation of the clone.
+ * Perhaps unnecessary, given FDVERIFY, but what the heck...
+ */
+ if(stat(tmpname,&statb) < 0 || statb.st_nlink != 1 ||
+ !S_ISREG(statb.st_mode))
+ error_exit(badexec);
+ if(ruserid != euserid &&
+ ((statb.st_mode & S_ISUID) == 0 || statb.st_uid != euserid))
+ error_exit(badexec);
+ goto exec;
+ }
+ /* Make sure that this is the real setuid program, not the clone.
+ * It is possible by clever hacking to get past this point in the
+ * clone, but it doesn't do the hacker any good that I can see.
+ */
+ if(euserid)
+ error_exit(badexec);
+#endif /* _lib_setreuid */
+ /* Open the script for reading first and then validate it. This
+ * prevents someone from pulling a switcheroo while we are validating.
+ */
+ n = open(p,0);
+ if(n == FDIN)
+ {
+ n = dup(n);
+ close(FDIN);
+ }
+ if(n < 0)
+ error_exit(badopen);
+ /* validate execution rights to this script */
+ if(fstat(FDIN,&statb) < 0 || (statb.st_mode & ~S_IFMT) != SPECIAL)
+ euserid = ruserid;
+ else
+ euserid = statb.st_uid;
+ /* do it the easy way if you can */
+ if(euserid == ruserid && egroupid == rgroupid)
+ {
+ if(access(p,X_OK) < 0)
+ error_exit(badexec);
+ }
+ else
+ {
+ /* have to check access on each component */
+ while(*p++)
+ {
+ if(*p == '/' || *p == 0)
+ {
+ m = *p;
+ *p = 0;
+ if(eaccess(argv[0],X_OK) < 0)
+ error_exit(badexec);
+ *p = m;
+ }
+ }
+ p = argv[0];
+ }
+ if(fstat(n, &statb) < 0 || !S_ISREG(statb.st_mode))
+ error_exit(badopen);
+ if(stat(p, &statx) < 0 ||
+ statb.st_ino != statx.st_ino || statb.st_dev != statx.st_dev)
+ error_exit(badexec);
+ if(stat(THISPROG, &statx) < 0 ||
+ (statb.st_ino == statx.st_ino && statb.st_dev == statx.st_dev))
+ error_exit(badexec);
+ close(FDIN);
+ if(fcntl(n,F_DUPFD,FDIN) != FDIN)
+ error_exit(badexec);
+ close(n);
+
+ /* compute the desired new effective user and group id */
+ effuid = euserid;
+ effgid = egroupid;
+ mode = 0;
+ if(statb.st_mode & S_ISUID)
+ effuid = statb.st_uid;
+ if(statb.st_mode & S_ISGID)
+ effgid = statb.st_gid;
+
+ /* see if group needs setting */
+ if(effgid != egroupid)
+ if(effgid != rgroupid || setgid(rgroupid) < 0)
+ mode = S_ISGID;
+
+ /* now see if the uid needs setting */
+ if(mode)
+ {
+ if(effuid != ruserid)
+ mode |= S_ISUID;
+ }
+ else if(effuid)
+ {
+ if(effuid != ruserid || setuid(ruserid) < 0)
+ mode = S_ISUID;
+ }
+
+ if(mode)
+ setids(mode, effuid, effgid);
+#ifndef _lib_setreuid
+exec:
+#endif /* _lib_setreuid */
+ /* only use SHELL if file is in trusted directory and ends in sh */
+ shell = getenv("SHELL");
+ if(shell == 0 || !endsh(shell) || (
+ !in_dir("/bin",shell) &&
+ !in_dir("/usr/bin",shell) &&
+ !in_dir("/usr/lbin",shell) &&
+ !in_dir("/usr/local/bin",shell)))
+ shell = DEFSHELL;
+ argv[0] = command;
+ argv[1] = (char*)devfd;
+ execv(shell,argv);
+ error_exit(badexec);
+}
+
+/*
+ * return true of shell ends in sh of ksh
+ */
+
+static int endsh(register const char *shell)
+{
+ while(*shell)
+ shell++;
+ if(*--shell != 'h' || *--shell != 's')
+ return(0);
+ if(*--shell=='/')
+ return(1);
+ if(*shell=='k' && *--shell=='/')
+ return(1);
+ return(0);
+}
+
+
+/*
+ * return true of shell is in <dir> directory
+ */
+
+static int in_dir(register const char *dir,register const char *shell)
+{
+ while(*dir)
+ {
+ if(*dir++ != *shell++)
+ return(0);
+ }
+ /* return true if next character is a '/' */
+ return(*shell=='/');
+}
+
+static void error_exit(const char *message)
+{
+ sfprintf(sfstdout,"%s: %s\n",command,message);
+ exit(126);
+}
+
+
+/*
+ * This version of access checks against effective uid and effective gid
+ */
+
+int eaccess(register const char *name, register int mode)
+{
+ struct stat statb;
+ if (stat(name, &statb) == 0)
+ {
+ if(euserid == 0)
+ {
+ if(!S_ISREG(statb.st_mode) || mode != 1)
+ return(0);
+ /* root needs execute permission for someone */
+ mode = (S_IXUSR|S_IXGRP|S_IXOTH);
+ }
+ else if(euserid == statb.st_uid)
+ mode <<= 6;
+ else if(egroupid == statb.st_gid)
+ mode <<= 3;
+#ifdef _lib_getgroups
+ /* on some systems you can be in several groups */
+ else
+ {
+ static int maxgroups;
+ gid_t *groups=0;
+ register int n;
+ if(maxgroups==0)
+ {
+ /* first time */
+ if((maxgroups=getgroups(0,groups)) < 0)
+ {
+ /* pre-POSIX system */
+ maxgroups=NGROUPS_MAX;
+ }
+ }
+ groups = (gid_t*)malloc((maxgroups+1)*sizeof(gid_t));
+ n = getgroups(maxgroups,groups);
+ while(--n >= 0)
+ {
+ if(groups[n] == statb.st_gid)
+ {
+ mode <<= 3;
+ break;
+ }
+ }
+ }
+#endif /* _lib_getgroups */
+ if(statb.st_mode & mode)
+ return(0);
+ }
+ return(-1);
+}
+
+#ifdef _lib_setreuid
+static void setids(int mode,int owner,int group)
+{
+ if(mode & S_ISGID)
+ setregid(rgroupid,group);
+
+ /* set effective uid even if S_ISUID is not set. This is because
+ * we are *really* executing EUID root at this point. Even if S_ISUID
+ * is not set, the value for owner that is passsed should be correct.
+ */
+ setreuid(ruserid,owner);
+}
+
+#else
+/*
+ * This version of setids creats a /tmp file and copies itself into it.
+ * The "clone" file is made executable with appropriate suid/sgid bits.
+ * Finally, the clone is exec'ed. This file is unlinked by a grandchild
+ * of this program, who waits around until the text is free.
+ */
+
+static void setids(int mode,uid_t owner,gid_t group)
+{
+ register int n,m;
+ int pv[2];
+
+ /*
+ * Create a token to pass to the new program for validation.
+ * This token can only be procured by someone running with an
+ * effective userid of root, and hence gives the clone a way to
+ * certify that it was really invoked by THISPROG. Someone who
+ * is already root could spoof us, but why would they want to?
+ *
+ * Since we are root here, we must be careful: What if someone
+ * linked a valuable file to tmpname?
+ */
+ unlink(tmpname); /* should normally fail */
+#ifdef O_EXCL
+ if((n = open(tmpname, O_WRONLY | O_CREAT | O_EXCL, SPECIAL)) < 0 ||
+ unlink(tmpname) < 0)
+#else
+ if((n = open(tmpname, O_WRONLY | O_CREAT ,SPECIAL)) < 0 || unlink(tmpname) < 0)
+#endif
+ error_exit(badexec);
+ if(n != FDVERIFY)
+ {
+ close(FDVERIFY);
+ if(fcntl(n,F_DUPFD,FDVERIFY) != FDVERIFY)
+ error_exit(badexec);
+ }
+ mode |= S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6);
+ /* create a pipe for synchronization */
+ if(pipe(pv) < 0)
+ error_exit(badexec);
+ if((n=fork()) == 0)
+ { /* child */
+ close(FDVERIFY);
+ close(pv[1]);
+ if((n=fork()) == 0)
+ { /* grandchild -- cleans up clone file */
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ read(pv[0],pv,1); /* wait for clone to close pipe */
+ while(unlink(tmpname) < 0 && errno == ETXTBSY)
+ sleep(1);
+ exit(0);
+ }
+ else if(n == -1)
+ exit(1);
+ else
+ {
+ /* Create a set[ug]id file that will become the clone.
+ * To make this atomic, without need for chown(), the
+ * child takes on desired user and group. The only
+ * downsize of this that I can see is that it may
+ * screw up some per- * user accounting.
+ */
+ if((m = open(THISPROG, O_RDONLY)) < 0)
+ exit(1);
+ if((mode & S_ISGID) && setgid(group) < 0)
+ exit(1);
+ if((mode & S_ISUID) && owner && setuid(owner) < 0)
+ exit(1);
+#ifdef O_EXCL
+ if((n = open(tmpname,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, mode)) < 0)
+#else
+ unlink(tmpname);
+ if((n = open(tmpname,O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0)
+#endif /* O_EXCL */
+ exit(1);
+ /* populate the clone */
+ m = mycopy(m,n);
+ if(chmod(tmpname,mode) <0)
+ exit(1);
+ exit(m);
+ }
+ }
+ else if(n == -1)
+ error_exit(badexec);
+ else
+ {
+ arglist[0] = (char*)tmpname;
+ close(pv[0]);
+ /* move write end of pipe into FDSYNC */
+ if(pv[1] != FDSYNC)
+ {
+ close(FDSYNC);
+ if(fcntl(pv[1],F_DUPFD,FDSYNC) != FDSYNC)
+ error_exit(badexec);
+ }
+ /* wait for child to die */
+ while((m = wait(0)) != n)
+ if(m == -1 && errno != EINTR)
+ break;
+ /* Kill any setuid status at this point. That way, if the
+ * clone is not setuid, we won't exec it as root. Also, don't
+ * neglect to consider that someone could have switched the
+ * clone file on us.
+ */
+ if(setuid(ruserid) < 0)
+ error_exit(badexec);
+ execv(tmpname,arglist);
+ error_exit(badexec);
+ }
+}
+
+/*
+ * create a unique name into the <template>
+ */
+
+static void maketemp(char *template)
+{
+ register char *cp = template;
+ register pid_t n = getpid();
+ /* skip to end of string */
+ while(*++cp);
+ /* convert process id to string */
+ while(n > 0)
+ {
+ *--cp = (n%10) + '0';
+ n /= 10;
+ }
+
+}
+
+/*
+ * copy THISPROG into the open file number <fdo> and close <fdo>
+ */
+
+static int mycopy(int fdi, int fdo)
+{
+ char buffer[BLKSIZE];
+ register int n;
+
+ while((n = read(fdi,buffer,BLKSIZE)) > 0)
+ if(write(fdo,buffer,n) != n)
+ break;
+ close(fdi);
+ close(fdo);
+ return n;
+}
+
+#endif /* _lib_setreuid */
+
+
diff --git a/src/cmd/ksh93/sh/tdump.c b/src/cmd/ksh93/sh/tdump.c
new file mode 100644
index 0000000..d3d82d8
--- /dev/null
+++ b/src/cmd/ksh93/sh/tdump.c
@@ -0,0 +1,262 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell parse tree dump
+ *
+ */
+
+#include "defs.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+#include <ccode.h>
+
+static int p_comlist(const struct dolnod*);
+static int p_arg(const struct argnod*);
+static int p_comarg(const struct comnod*);
+static int p_redirect(const struct ionod*);
+static int p_switch(const struct regnod*);
+static int p_tree(const Shnode_t*);
+static int p_string(const char*);
+
+static Sfio_t *outfile;
+
+int sh_tdump(Sfio_t *out, const Shnode_t *t)
+{
+ outfile = out;
+ return(p_tree(t));
+}
+
+/*
+ * convert to ASCII to write and back again if needed
+ */
+static int outstring(Sfio_t *out, const char *string, int n)
+{
+ int r;
+ char *cp = (char*)string;
+ ccmaps(cp, n, CC_NATIVE, CC_ASCII);
+ r = sfwrite(out,cp,n);
+ ccmaps(cp, n, CC_ASCII, CC_NATIVE);
+ return(r);
+}
+
+/*
+ * print script corresponding to shell tree <t>
+ */
+static int p_tree(register const Shnode_t *t)
+{
+ if(!t)
+ return(sfputl(outfile,-1));
+ if(sfputl(outfile,t->tre.tretyp)<0)
+ return(-1);
+ switch(t->tre.tretyp&COMMSK)
+ {
+ case TTIME:
+ case TPAR:
+ return(p_tree(t->par.partre));
+ case TCOM:
+ return(p_comarg((struct comnod*)t));
+ case TSETIO:
+ case TFORK:
+ if(sfputu(outfile,t->fork.forkline)<0)
+ return(-1);
+ if(p_tree(t->fork.forktre)<0)
+ return(-1);
+ return(p_redirect(t->fork.forkio));
+ case TIF:
+ if(p_tree(t->if_.iftre)<0)
+ return(-1);
+ if(p_tree(t->if_.thtre)<0)
+ return(-1);
+ return(p_tree(t->if_.eltre));
+ case TWH:
+ if(t->wh.whinc)
+ {
+ if(p_tree((Shnode_t*)(t->wh.whinc))<0)
+ return(-1);
+ }
+ else
+ {
+ if(sfputl(outfile,-1)<0)
+ return(-1);
+ }
+ if(p_tree(t->wh.whtre)<0)
+ return(-1);
+ return(p_tree(t->wh.dotre));
+ case TLST:
+ case TAND:
+ case TORF:
+ case TFIL:
+ if(p_tree(t->lst.lstlef)<0)
+ return(-1);
+ return(p_tree(t->lst.lstrit));
+ case TARITH:
+ if(sfputu(outfile,t->ar.arline)<0)
+ return(-1);
+ return(p_arg(t->ar.arexpr));
+ case TFOR:
+ if(sfputu(outfile,t->for_.forline)<0)
+ return(-1);
+ if(p_tree(t->for_.fortre)<0)
+ return(-1);
+ if(p_string(t->for_.fornam)<0)
+ return(-1);
+ return(p_tree((Shnode_t*)t->for_.forlst));
+ case TSW:
+ if(sfputu(outfile,t->sw.swline)<0)
+ return(-1);
+ if(p_arg(t->sw.swarg)<0)
+ return(-1);
+ return(p_switch(t->sw.swlst));
+ case TFUN:
+ if(sfputu(outfile,t->funct.functline)<0)
+ return(-1);
+ if(p_string(t->funct.functnam)<0)
+ return(-1);
+ if(p_tree(t->funct.functtre)<0)
+ return(-1);
+ return(p_tree((Shnode_t*)t->funct.functargs));
+ case TTST:
+ if(sfputu(outfile,t->tst.tstline)<0)
+ return(-1);
+ if((t->tre.tretyp&TPAREN)==TPAREN)
+ return(p_tree(t->lst.lstlef));
+ else
+ {
+ if(p_arg(&(t->lst.lstlef->arg))<0)
+ return(-1);
+ if((t->tre.tretyp&TBINARY))
+ return(p_arg(&(t->lst.lstrit->arg)));
+ return(0);
+ }
+ }
+ return(-1);
+}
+
+static int p_arg(register const struct argnod *arg)
+{
+ register int n;
+ struct fornod *fp;
+ while(arg)
+ {
+ if((n = strlen(arg->argval)) || (arg->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED)))
+ fp=0;
+ else
+ {
+ fp=(struct fornod*)arg->argchn.ap;
+ n = strlen(fp->fornam)+1;
+ }
+ sfputu(outfile,n+1);
+ if(fp)
+ {
+ sfputc(outfile,0);
+ outstring(outfile,fp->fornam,n-1);
+ }
+ else
+ outstring(outfile,arg->argval,n);
+ sfputc(outfile,arg->argflag);
+ if(fp)
+ {
+ sfputu(outfile,fp->fortyp);
+ p_tree(fp->fortre);
+ }
+ else if(n==0 && (arg->argflag&ARG_EXP) && arg->argchn.ap)
+ p_tree((Shnode_t*)arg->argchn.ap);
+ arg = arg->argnxt.ap;
+ }
+ return(sfputu(outfile,0));
+}
+
+static int p_redirect(register const struct ionod *iop)
+{
+ while(iop)
+ {
+ if(iop->iovname)
+ sfputl(outfile,iop->iofile|IOVNM);
+ else
+ sfputl(outfile,iop->iofile);
+ p_string(iop->ioname);
+ if(iop->iodelim)
+ {
+ p_string(iop->iodelim);
+ sfputl(outfile,iop->iosize);
+ sfseek(sh.heredocs,iop->iooffset,SEEK_SET);
+ sfmove(sh.heredocs,outfile, iop->iosize,-1);
+ }
+ else
+ sfputu(outfile,0);
+ if(iop->iovname)
+ p_string(iop->iovname);
+ iop = iop->ionxt;
+ }
+ return(sfputl(outfile,-1));
+}
+
+static int p_comarg(register const struct comnod *com)
+{
+ p_redirect(com->comio);
+ p_arg(com->comset);
+ if(!com->comarg)
+ sfputl(outfile,-1);
+ else if(com->comtyp&COMSCAN)
+ p_arg(com->comarg);
+ else
+ p_comlist((struct dolnod*)com->comarg);
+ return(sfputu(outfile,com->comline));
+}
+
+static int p_comlist(const struct dolnod *dol)
+{
+ register char *cp, *const*argv;
+ register int n;
+ argv = dol->dolval+ARG_SPARE;
+ while(cp = *argv)
+ argv++;
+ n = argv - (dol->dolval+1);
+ sfputl(outfile,n);
+ argv = dol->dolval+ARG_SPARE;
+ while(cp = *argv++)
+ p_string(cp);
+ return(sfputu(outfile,0));
+}
+
+static int p_switch(register const struct regnod *reg)
+{
+ while(reg)
+ {
+ sfputl(outfile,reg->regflag);
+ p_arg(reg->regptr);
+ p_tree(reg->regcom);
+ reg = reg->regnxt;
+ }
+ return(sfputl(outfile,-1));
+}
+
+static int p_string(register const char *string)
+{
+ register size_t n=strlen(string);
+ if(sfputu(outfile,n+1)<0)
+ return(-1);
+ return(outstring(outfile,string,n));
+}
diff --git a/src/cmd/ksh93/sh/timers.c b/src/cmd/ksh93/sh/timers.c
new file mode 100644
index 0000000..d9ace52
--- /dev/null
+++ b/src/cmd/ksh93/sh/timers.c
@@ -0,0 +1,248 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <sig.h>
+#include <error.h>
+#include "fault.h"
+#include "defs.h"
+#include "FEATURE/sigfeatures"
+#include "FEATURE/time"
+
+typedef struct _timer
+{
+ double wakeup;
+ double incr;
+ struct _timer *next;
+ void (*action)(void*);
+ void *handle;
+} Timer_t;
+
+#define IN_ADDTIMEOUT 1
+#define IN_SIGALRM 2
+#define DEFER_SIGALRM 4
+#define SIGALRM_CALL 8
+
+static Timer_t *tptop, *tpmin, *tpfree;
+static char time_state;
+
+static double getnow(void)
+{
+ register double now;
+#ifdef timeofday
+ struct timeval tp;
+ timeofday(&tp);
+ now = tp.tv_sec + 1.e-6*tp.tv_usec;
+
+#else
+ now = (double)time((time_t*)0);
+#endif /* timeofday */
+ return(now+.001);
+}
+
+/*
+ * set an alarm for <t> seconds
+ */
+static double setalarm(register double t)
+{
+#if defined(_lib_setitimer) && defined(ITIMER_REAL)
+ struct itimerval tnew, told;
+ tnew.it_value.tv_sec = t;
+ tnew.it_value.tv_usec = 1.e6*(t- (double)tnew.it_value.tv_sec);
+ if(t && tnew.it_value.tv_sec==0 && tnew.it_value.tv_usec<1000)
+ tnew.it_value.tv_usec = 1000;
+ tnew.it_interval.tv_sec = 0;
+ tnew.it_interval.tv_usec = 0;
+ if(setitimer(ITIMER_REAL,&tnew,&told) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_alarm);
+ t = told.it_value.tv_sec + 1.e-6*told.it_value.tv_usec;
+#else
+ unsigned seconds = (unsigned)t;
+ if(t && seconds<1)
+ seconds=1;
+ t = (double)alarm(seconds);
+#endif
+ return(t);
+}
+
+/* signal handler for alarm call */
+static void sigalrm(int sig)
+{
+ register Timer_t *tp, *tplast, *tpold, *tpnext;
+ double now;
+ static double left;
+ NOT_USED(sig);
+ left = 0;
+ if(time_state&SIGALRM_CALL)
+ time_state &= ~SIGALRM_CALL;
+ else if(alarm(0))
+ sh_fault(SIGALRM|SH_TRAP);
+ if(time_state)
+ {
+ if(time_state&IN_ADDTIMEOUT)
+ time_state |= DEFER_SIGALRM;
+ errno = EINTR;
+ return;
+ }
+ time_state |= IN_SIGALRM;
+ sigrelease(SIGALRM);
+ while(1)
+ {
+ now = getnow();
+ tpold = tpmin = 0;
+ for(tplast=0,tp=tptop; tp; tp=tpnext)
+ {
+ tpnext = tp->next;
+ if(tp->action)
+ {
+ if(tp->wakeup <=now)
+ {
+ if(!tpold || tpold->wakeup>tp->wakeup)
+ tpold = tp;
+ }
+ else
+ {
+ if(!tpmin || tpmin->wakeup>tp->wakeup)
+ tpmin=tp;
+ }
+ tplast = tp;
+ }
+ else
+ {
+ if(tplast)
+ tplast->next = tp->next;
+ else
+ tptop = tp->next;
+ tp->next = tpfree;
+ tpfree = tp;
+ }
+ }
+ if((tp=tpold) && tp->incr)
+ {
+ while((tp->wakeup += tp->incr) <= now);
+ if(!tpmin || tpmin->wakeup>tp->wakeup)
+ tpmin=tp;
+ }
+ if(tpmin && (left==0 || (tp && tpmin->wakeup < (now+left))))
+ {
+ if(left==0)
+ signal(SIGALRM,sigalrm);
+ left = setalarm(tpmin->wakeup-now);
+ if(left && (now+left) < tpmin->wakeup)
+ setalarm(left);
+ else
+ left=tpmin->wakeup-now;
+ }
+ if(tp)
+ {
+ void (*action)(void*);
+ action = tp->action;
+ if(!tp->incr)
+ tp->action = 0;
+ errno = EINTR;
+ time_state &= ~IN_SIGALRM;
+ (*action)(tp->handle);
+ time_state |= IN_SIGALRM;
+ }
+ else
+ break;
+ }
+ if(!tpmin)
+ signal(SIGALRM,(sh.sigflag[SIGALRM]&SH_SIGFAULT)?sh_fault:SIG_DFL);
+ time_state &= ~IN_SIGALRM;
+ errno = EINTR;
+}
+
+static void oldalrm(void *handle)
+{
+ Handler_t fn = *(Handler_t*)handle;
+ free(handle);
+ (*fn)(SIGALRM);
+}
+
+void *sh_timeradd(unsigned long msec,int flags,void (*action)(void*),void *handle)
+{
+ register Timer_t *tp;
+ double t;
+ Handler_t fn;
+ t = ((double)msec)/1000.;
+ if(t<=0 || !action)
+ return((void*)0);
+ if(tp=tpfree)
+ tpfree = tp->next;
+ else if(!(tp=(Timer_t*)malloc(sizeof(Timer_t))))
+ return((void*)0);
+ tp->wakeup = getnow() + t;
+ tp->incr = (flags?t:0);
+ tp->action = action;
+ tp->handle = handle;
+ time_state |= IN_ADDTIMEOUT;
+ tp->next = tptop;
+ tptop = tp;
+ if(!tpmin || tp->wakeup < tpmin->wakeup)
+ {
+ tpmin = tp;
+ fn = (Handler_t)signal(SIGALRM,sigalrm);
+ if((t= setalarm(t))>0 && fn && fn!=(Handler_t)sigalrm)
+ {
+ Handler_t *hp = (Handler_t*)malloc(sizeof(Handler_t));
+ if(hp)
+ {
+ *hp = fn;
+ sh_timeradd((long)(1000*t), 0, oldalrm, (void*)hp);
+ }
+ }
+ tp = tptop;
+ }
+ else if(tpmin && !tpmin->action)
+ time_state |= DEFER_SIGALRM;
+ time_state &= ~IN_ADDTIMEOUT;
+ if(time_state&DEFER_SIGALRM)
+ {
+ time_state=SIGALRM_CALL;
+ sigalrm(SIGALRM);
+ if(tp!=tptop)
+ tp=0;
+ }
+ return((void*)tp);
+}
+
+/*
+ * delete timer <tp>. If <tp> is NULL, all timers are deleted
+ */
+void timerdel(void *handle)
+{
+ register Timer_t *tp = (Timer_t*)handle;
+ if(tp)
+ tp->action = 0;
+ else
+ {
+ for(tp=tptop; tp; tp=tp->next)
+ tp->action = 0;
+ if(tpmin)
+ {
+ tpmin = 0;
+ setalarm((double)0);
+ }
+ signal(SIGALRM,(sh.sigflag[SIGALRM]&SH_SIGFAULT)?sh_fault:SIG_DFL);
+ }
+}
+
diff --git a/src/cmd/ksh93/sh/trestore.c b/src/cmd/ksh93/sh/trestore.c
new file mode 100644
index 0000000..c209b73
--- /dev/null
+++ b/src/cmd/ksh93/sh/trestore.c
@@ -0,0 +1,353 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell intermediate code reader
+ *
+ */
+
+#include "defs.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+#include <ccode.h>
+
+static struct dolnod *r_comlist(Shell_t*);
+static struct argnod *r_arg(Shell_t*);
+static struct ionod *r_redirect(Shell_t*);
+static struct regnod *r_switch(Shell_t*);
+static Shnode_t *r_tree(Shell_t*);
+static char *r_string(Stk_t*);
+static void r_comarg(Shell_t*,struct comnod*);
+
+static Sfio_t *infile;
+
+#define getnode(s,type) ((Shnode_t*)stkalloc((s),sizeof(struct type)))
+
+Shnode_t *sh_trestore(Shell_t *shp,Sfio_t *in)
+{
+ Shnode_t *t;
+ infile = in;
+ t = r_tree(shp);
+ return(t);
+}
+/*
+ * read in a shell tree
+ */
+static Shnode_t *r_tree(Shell_t *shp)
+{
+ long l = sfgetl(infile);
+ register int type;
+ register Shnode_t *t=0;
+ if(l<0)
+ return(t);
+ type = l;
+ switch(type&COMMSK)
+ {
+ case TTIME:
+ case TPAR:
+ t = getnode(shp->stk,parnod);
+ t->par.partre = r_tree(shp);
+ break;
+ case TCOM:
+ t = getnode(shp->stk,comnod);
+ t->tre.tretyp = type;
+ r_comarg(shp,(struct comnod*)t);
+ break;
+ case TSETIO:
+ case TFORK:
+ t = getnode(shp->stk,forknod);
+ t->fork.forkline = sfgetu(infile);
+ t->fork.forktre = r_tree(shp);
+ t->fork.forkio = r_redirect(shp);
+ break;
+ case TIF:
+ t = getnode(shp->stk,ifnod);
+ t->if_.iftre = r_tree(shp);
+ t->if_.thtre = r_tree(shp);
+ t->if_.eltre = r_tree(shp);
+ break;
+ case TWH:
+ t = getnode(shp->stk,whnod);
+ t->wh.whinc = (struct arithnod*)r_tree(shp);
+ t->wh.whtre = r_tree(shp);
+ t->wh.dotre = r_tree(shp);
+ break;
+ case TLST:
+ case TAND:
+ case TORF:
+ case TFIL:
+ t = getnode(shp->stk,lstnod);
+ t->lst.lstlef = r_tree(shp);
+ t->lst.lstrit = r_tree(shp);
+ break;
+ case TARITH:
+ t = getnode(shp->stk,arithnod);
+ t->ar.arline = sfgetu(infile);
+ t->ar.arexpr = r_arg(shp);
+ t->ar.arcomp = 0;
+ if((t->ar.arexpr)->argflag&ARG_RAW)
+ t->ar.arcomp = sh_arithcomp(shp,(t->ar.arexpr)->argval);
+ break;
+ case TFOR:
+ t = getnode(shp->stk,fornod);
+ t->for_.forline = 0;
+ if(type&FLINENO)
+ t->for_.forline = sfgetu(infile);
+ t->for_.fortre = r_tree(shp);
+ t->for_.fornam = r_string(shp->stk);
+ t->for_.forlst = (struct comnod*)r_tree(shp);
+ break;
+ case TSW:
+ t = getnode(shp->stk,swnod);
+ t->sw.swline = 0;
+ if(type&FLINENO)
+ t->sw.swline = sfgetu(infile);
+ t->sw.swarg = r_arg(shp);
+ if(type&COMSCAN)
+ t->sw.swio = r_redirect(shp);
+ else
+ t->sw.swio = 0;
+ t->sw.swlst = r_switch(shp);
+ break;
+ case TFUN:
+ {
+ Stak_t *savstak;
+ struct slnod *slp;
+ struct functnod *fp;
+ t = getnode(shp->stk,functnod);
+ t->funct.functloc = -1;
+ t->funct.functline = sfgetu(infile);
+ t->funct.functnam = r_string(shp->stk);
+ savstak = stakcreate(STAK_SMALL);
+ savstak = stakinstall(savstak, 0);
+ slp = (struct slnod*)stkalloc(shp->stk,sizeof(struct slnod)+sizeof(struct functnod));
+ slp->slchild = 0;
+ slp->slnext = shp->st.staklist;
+ shp->st.staklist = 0;
+ fp = (struct functnod*)(slp+1);
+ memset(fp, 0, sizeof(*fp));
+ fp->functtyp = TFUN|FAMP;
+ if(shp->st.filename)
+ fp->functnam = stkcopy(shp->stk,shp->st.filename);
+ t->funct.functtre = r_tree(shp);
+ t->funct.functstak = slp;
+ t->funct.functargs = (struct comnod*)r_tree(shp);
+ slp->slptr = stakinstall(savstak,0);
+ slp->slchild = shp->st.staklist;
+ break;
+ }
+ case TTST:
+ t = getnode(shp->stk,tstnod);
+ t->tst.tstline = sfgetu(infile);
+ if((type&TPAREN)==TPAREN)
+ t->lst.lstlef = r_tree(shp);
+ else
+ {
+ t->lst.lstlef = (Shnode_t*)r_arg(shp);
+ if((type&TBINARY))
+ t->lst.lstrit = (Shnode_t*)r_arg(shp);
+ }
+ }
+ if(t)
+ t->tre.tretyp = type;
+ return(t);
+}
+
+static struct argnod *r_arg(Shell_t *shp)
+{
+ register struct argnod *ap=0, *apold, *aptop=0;
+ register long l;
+ Stk_t *stkp=shp->stk;
+ while((l=sfgetu(infile))>0)
+ {
+ ap = (struct argnod*)stkseek(stkp,(unsigned)l+ARGVAL);
+ if(!aptop)
+ aptop = ap;
+ else
+ apold->argnxt.ap = ap;
+ if(--l > 0)
+ {
+ sfread(infile,ap->argval,(size_t)l);
+ ccmaps(ap->argval, l, CC_ASCII, CC_NATIVE);
+ }
+ ap->argval[l] = 0;
+ ap->argchn.cp = 0;
+ ap->argflag = sfgetc(infile);
+#if 0
+ if((ap->argflag&ARG_MESSAGE) && *ap->argval)
+ {
+ /* replace international messages */
+ sh_endword(shp,1);
+ ap->argflag &= ~ARG_MESSAGE;
+ if(!(ap->argflag&(ARG_MAC|ARG_EXP)))
+ ap = sh_endword(shp,0);
+ else
+ {
+ ap = (struct argnod*)stkfreeze(stkp,0);
+ if(ap->argflag==0)
+ ap->argflag = ARG_RAW;
+ }
+ }
+ else
+#endif
+ ap = (struct argnod*)stkfreeze(stkp,0);
+ if(*ap->argval==0 && (ap->argflag&ARG_EXP))
+ ap->argchn.ap = (struct argnod*)r_tree(shp);
+ else if(*ap->argval==0 && (ap->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED))==0)
+ {
+ struct fornod *fp = (struct fornod*)getnode(shp->stk,fornod);
+ fp->fortyp = sfgetu(infile);
+ fp->fortre = r_tree(shp);
+ fp->fornam = ap->argval+1;
+ ap->argchn.ap = (struct argnod*)fp;
+ }
+ apold = ap;
+ }
+ if(ap)
+ ap->argnxt.ap = 0;
+ return(aptop);
+}
+
+static struct ionod *r_redirect(Shell_t* shp)
+{
+ register long l;
+ register struct ionod *iop=0, *iopold, *ioptop=0;
+ while((l=sfgetl(infile))>=0)
+ {
+ iop = (struct ionod*)getnode(shp->stk,ionod);
+ if(!ioptop)
+ ioptop = iop;
+ else
+ iopold->ionxt = iop;
+ iop->iofile = l;
+ iop->ioname = r_string(shp->stk);
+ if(iop->iodelim = r_string(shp->stk))
+ {
+ iop->iosize = sfgetl(infile);
+ if(shp->heredocs)
+ iop->iooffset = sfseek(shp->heredocs,(off_t)0,SEEK_END);
+ else
+ {
+ shp->heredocs = sftmp(512);
+ iop->iooffset = 0;
+ }
+ sfmove(infile,shp->heredocs, iop->iosize, -1);
+ }
+ iopold = iop;
+ if(iop->iofile&IOVNM)
+ iop->iovname = r_string(shp->stk);
+ else
+ iop->iovname = 0;
+ iop->iofile &= ~IOVNM;
+ }
+ if(iop)
+ iop->ionxt = 0;
+ return(ioptop);
+}
+
+static void r_comarg(Shell_t *shp,struct comnod *com)
+{
+ char *cmdname=0;
+ com->comio = r_redirect(shp);
+ com->comset = r_arg(shp);
+ com->comstate = 0;
+ if(com->comtyp&COMSCAN)
+ {
+ com->comarg = r_arg(shp);
+ if(com->comarg->argflag==ARG_RAW)
+ cmdname = com->comarg->argval;
+ }
+ else if(com->comarg = (struct argnod*)r_comlist(shp))
+ cmdname = ((struct dolnod*)(com->comarg))->dolval[ARG_SPARE];
+ com->comline = sfgetu(infile);
+ com->comnamq = 0;
+ if(cmdname)
+ {
+ char *cp;
+ com->comnamp = (void*)nv_search(cmdname,shp->fun_tree,0);
+ if(com->comnamp && (cp =strrchr(cmdname+1,'.')))
+ {
+ *cp = 0;
+ com->comnamp = (void*)nv_open(cmdname,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOARRAY);
+ *cp = '.';
+ }
+ }
+ else
+ com->comnamp = 0;
+}
+
+static struct dolnod *r_comlist(Shell_t *shp)
+{
+ register struct dolnod *dol=0;
+ register long l;
+ register char **argv;
+ if((l=sfgetl(infile))>0)
+ {
+ dol = (struct dolnod*)stkalloc(shp->stk,sizeof(struct dolnod) + sizeof(char*)*(l+ARG_SPARE));
+ dol->dolnum = l;
+ dol->dolbot = ARG_SPARE;
+ argv = dol->dolval+ARG_SPARE;
+ while(*argv++ = r_string(shp->stk));
+ }
+ return(dol);
+}
+
+static struct regnod *r_switch(Shell_t *shp)
+{
+ register long l;
+ struct regnod *reg=0,*regold,*regtop=0;
+ while((l=sfgetl(infile))>=0)
+ {
+ reg = (struct regnod*)getnode(shp->stk,regnod);
+ if(!regtop)
+ regtop = reg;
+ else
+ regold->regnxt = reg;
+ reg->regflag = l;
+ reg->regptr = r_arg(shp);
+ reg->regcom = r_tree(shp);
+ regold = reg;
+ }
+ if(reg)
+ reg->regnxt = 0;
+ return(regtop);
+}
+
+static char *r_string(Stk_t *stkp)
+{
+ register Sfio_t *in = infile;
+ register unsigned long l = sfgetu(in);
+ register char *ptr;
+ if(l == 0)
+ return(NIL(char*));
+ ptr = stkalloc(stkp,(unsigned)l);
+ if(--l > 0)
+ {
+ if(sfread(in,ptr,(size_t)l)!=(size_t)l)
+ return(NIL(char*));
+ ccmaps(ptr, l, CC_ASCII, CC_NATIVE);
+ }
+ ptr[l] = 0;
+ return(ptr);
+}
diff --git a/src/cmd/ksh93/sh/waitevent.c b/src/cmd/ksh93/sh/waitevent.c
new file mode 100644
index 0000000..e868116
--- /dev/null
+++ b/src/cmd/ksh93/sh/waitevent.c
@@ -0,0 +1,54 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "defs.h"
+/*
+ * This installs a hook to allow the processing of events when
+ * the shell is waiting for input and when the shell is
+ * waiting for job completion.
+ * The previous waitevent hook function is returned
+ */
+
+
+void *sh_waitnotify(int(*newevent)(int,long,int))
+{
+ int (*old)(int,long,int);
+ old = shgd->waitevent;
+ shgd->waitevent = newevent;
+ return((void*)old);
+}
+
+#if __OBSOLETE__ < 20080101
+/*
+ * this used to be a private symbol
+ * retain the old name for a bit for a smooth transition
+ */
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void *_sh_waitnotify(int(*newevent)(int,long,int))
+{
+ return sh_waitnotify(newevent);
+}
+
+#endif
diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c
new file mode 100644
index 0000000..28ad1e1
--- /dev/null
+++ b/src/cmd/ksh93/sh/xec.c
@@ -0,0 +1,3991 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell parse tree executer
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include "variables.h"
+#include "path.h"
+#include "name.h"
+#include "io.h"
+#include "shnodes.h"
+#include "jobs.h"
+#include "test.h"
+#include "builtins.h"
+#include "FEATURE/time"
+#include "FEATURE/externs"
+#include "FEATURE/locale"
+#include "streval.h"
+
+#if !_std_malloc
+# include <vmalloc.h>
+#endif
+
+#if _lib_vfork
+# include <ast_vfork.h>
+#else
+# define vfork() fork()
+#endif
+
+#define SH_NTFORK SH_TIMING
+#define NV_BLTPFSH NV_ARRAY
+
+#if _lib_nice
+ extern int nice(int);
+#endif /* _lib_nice */
+#if !_lib_spawnveg
+# define spawnveg(a,b,c,d) spawnve(a,b,c)
+#endif /* !_lib_spawnveg */
+#if SHOPT_SPAWN
+ static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int);
+#endif /* SHOPT_SPAWN */
+
+static void sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int);
+static int trim_eq(const char*, const char*);
+static void coproc_init(Shell_t*, int pipes[]);
+
+static void *timeout;
+static char pipejob;
+static char nopost;
+static int restorefd;
+
+struct funenv
+{
+ Namval_t *node;
+ struct argnod *env;
+ Namval_t **nref;
+};
+
+/* ======== command execution ========*/
+
+#if !SHOPT_DEVFD
+ static void fifo_check(void *handle)
+ {
+ Shell_t *shp = (Shell_t*)handle;
+ pid_t pid = getppid();
+ if(pid==1)
+ {
+ unlink(shp->fifo);
+ sh_done(shp,0);
+ }
+ }
+#endif /* !SHOPT_DEVFD */
+
+/*
+ * The following two functions allow command substituion for non-builtins
+ * to use a pipe and to wait for the pipe to close before restoring to a
+ * temp file.
+ */
+static int subpipe[3] = {-1};
+static int subdup,tsetio,usepipe;
+static void iousepipe(Shell_t *shp)
+{
+ int i;
+ usepipe++;
+ fcntl(subpipe[0],F_SETFD,FD_CLOEXEC);
+ subpipe[2] = fcntl(1,F_DUPFD,10);
+ fcntl(subpipe[2],F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[subpipe[2]] = shp->fdstatus[1];
+ close(1);
+ fcntl(subpipe[1],F_DUPFD,1);
+ shp->fdstatus[1] = shp->fdstatus[subpipe[1]];
+ sh_close(subpipe[1]);
+ if(subdup=shp->subdup) for(i=0; i < 10; i++)
+ {
+ if(subdup&(1<<i))
+ {
+ sh_close(i);
+ fcntl(1,F_DUPFD,i);
+ shp->fdstatus[i] = shp->fdstatus[1];
+ }
+ }
+}
+
+static void iounpipe(Shell_t *shp)
+{
+ int n;
+ char buff[SF_BUFSIZE];
+ usepipe = 0;
+ close(1);
+ fcntl(subpipe[2], F_DUPFD, 1);
+ shp->fdstatus[1] = shp->fdstatus[subpipe[2]];
+ if(subdup) for(n=0; n < 10; n++)
+ {
+ if(subdup&(1<<n))
+ {
+ sh_close(n);
+ fcntl(1, F_DUPFD, n);
+ shp->fdstatus[n] = shp->fdstatus[1];
+ }
+ }
+ shp->subdup = 0;
+ sh_close(subpipe[2]);
+ while((n = read(subpipe[0],buff,sizeof(buff)))!=0)
+ {
+ if(n>0)
+ sfwrite(sfstdout,buff,n);
+ else if(errno!=EINTR)
+ break;
+ }
+ sh_close(subpipe[0]);
+ subpipe[0] = -1;
+ tsetio = 0;
+}
+
+/*
+ * print time <t> in h:m:s format with precision <p>
+ */
+static void l_time(Sfio_t *outfile,register clock_t t,int p)
+{
+ register int min, sec, frac;
+ register int hr;
+ if(p)
+ {
+ frac = t%shgd->lim.clk_tck;
+ frac = (frac*100)/shgd->lim.clk_tck;
+ }
+ t /= shgd->lim.clk_tck;
+ sec = t%60;
+ t /= 60;
+ min = t%60;
+ if(hr=t/60)
+ sfprintf(outfile,"%dh",hr);
+ if(p)
+ sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac);
+ else
+ sfprintf(outfile,"%dm%ds",min,sec);
+}
+
+static int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
+{
+ int c,p,l,n,offset = staktell();
+ const char *first;
+ double d;
+ Stk_t *stkp = shp->stk;
+ for(first=format ; c= *format; format++)
+ {
+ if(c!='%')
+ continue;
+ sfwrite(stkp, first, format-first);
+ n = l = 0;
+ p = 3;
+ if((c= *++format) == '%')
+ {
+ first = format;
+ continue;
+ }
+ if(c>='0' && c <='9')
+ {
+ p = (c>'3')?3:(c-'0');
+ c = *++format;
+ }
+ else if(c=='P')
+ {
+ if(d=tm[0])
+ d = 100.*(((double)(tm[1]+tm[2]))/d);
+ p = 2;
+ goto skip;
+ }
+ if(c=='l')
+ {
+ l = 1;
+ c = *++format;
+ }
+ if(c=='U')
+ n = 1;
+ else if(c=='S')
+ n = 2;
+ else if(c!='R')
+ {
+ stkseek(stkp,offset);
+ errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);
+ return(0);
+ }
+ d = (double)tm[n]/shp->gd->lim.clk_tck;
+ skip:
+ if(l)
+ l_time(stkp, tm[n], p);
+ else
+ sfprintf(stkp,"%.*f",p, d);
+ first = format+1;
+ }
+ if(format>first)
+ sfwrite(stkp,first, format-first);
+ sfputc(stkp,'\n');
+ n = stktell(stkp)-offset;
+ sfwrite(out,stkptr(stkp,offset),n);
+ stkseek(stkp,offset);
+ return(n);
+}
+
+#if SHOPT_OPTIMIZE
+/*
+ * clear argument pointers that point into the stack
+ */
+static int p_arg(struct argnod*,int);
+static int p_switch(struct regnod*);
+static int p_comarg(register struct comnod *com)
+{
+ Namval_t *np=com->comnamp;
+ int n = p_arg(com->comset,ARG_ASSIGN);
+ if(com->comarg && (com->comtyp&COMSCAN))
+ n+= p_arg(com->comarg,0);
+ if(com->comstate && np)
+ {
+ /* call builtin to cleanup state */
+ Shbltin_t *bp = &sh.bltindata;
+ void *save_ptr = bp->ptr;
+ void *save_data = bp->data;
+ bp->bnode = np;
+ bp->vnode = com->comnamq;
+ bp->ptr = nv_context(np);
+ bp->data = com->comstate;
+ bp->flags = SH_END_OPTIM;
+ ((Shbltin_f)funptr(np))(0,(char**)0, bp);
+ bp->ptr = save_ptr;
+ bp->data = save_data;
+ }
+ com->comstate = 0;
+ if(com->comarg && !np)
+ n++;
+ return(n);
+}
+
+extern void sh_optclear(Shell_t*, void*);
+
+static int sh_tclear(register Shnode_t *t)
+{
+ int n=0;
+ if(!t)
+ return(0);
+ switch(t->tre.tretyp&COMMSK)
+ {
+ case TTIME:
+ case TPAR:
+ return(sh_tclear(t->par.partre));
+ case TCOM:
+ return(p_comarg((struct comnod*)t));
+ case TSETIO:
+ case TFORK:
+ return(sh_tclear(t->fork.forktre));
+ case TIF:
+ n=sh_tclear(t->if_.iftre);
+ n+=sh_tclear(t->if_.thtre);
+ n+=sh_tclear(t->if_.eltre);
+ return(n);
+ case TWH:
+ if(t->wh.whinc)
+ n=sh_tclear((Shnode_t*)(t->wh.whinc));
+ n+=sh_tclear(t->wh.whtre);
+ n+=sh_tclear(t->wh.dotre);
+ return(n);
+ case TLST:
+ case TAND:
+ case TORF:
+ case TFIL:
+ n=sh_tclear(t->lst.lstlef);
+ return(n+sh_tclear(t->lst.lstrit));
+ case TARITH:
+ return(p_arg(t->ar.arexpr,ARG_ARITH));
+ case TFOR:
+ n=sh_tclear(t->for_.fortre);
+ return(n+sh_tclear((Shnode_t*)t->for_.forlst));
+ case TSW:
+ n=p_arg(t->sw.swarg,0);
+ return(n+p_switch(t->sw.swlst));
+ case TFUN:
+ n=sh_tclear(t->funct.functtre);
+ return(n+sh_tclear((Shnode_t*)t->funct.functargs));
+ case TTST:
+ if((t->tre.tretyp&TPAREN)==TPAREN)
+ return(sh_tclear(t->lst.lstlef));
+ else
+ {
+ n=p_arg(&(t->lst.lstlef->arg),0);
+ if(t->tre.tretyp&TBINARY)
+ n+=p_arg(&(t->lst.lstrit->arg),0);
+ }
+ }
+ return(n);
+}
+
+static int p_arg(register struct argnod *arg,int flag)
+{
+ while(arg)
+ {
+ if(strlen(arg->argval) || (arg->argflag==ARG_RAW))
+ arg->argchn.ap = 0;
+ else if(flag==0)
+ sh_tclear((Shnode_t*)arg->argchn.ap);
+ else
+ sh_tclear(((struct fornod*)arg->argchn.ap)->fortre);
+ arg = arg->argnxt.ap;
+ }
+ return(0);
+}
+
+static int p_switch(register struct regnod *reg)
+{
+ int n=0;
+ while(reg)
+ {
+ n+=p_arg(reg->regptr,0);
+ n+=sh_tclear(reg->regcom);
+ reg = reg->regnxt;
+ }
+ return(n);
+}
+# define OPTIMIZE_FLAG (ARG_OPTIMIZE)
+# define OPTIMIZE (flags&OPTIMIZE_FLAG)
+#else
+# define OPTIMIZE_FLAG (0)
+# define OPTIMIZE (0)
+# define sh_tclear(x)
+#endif /* SHOPT_OPTIMIZE */
+
+static void out_pattern(Sfio_t *iop, register const char *cp, int n)
+{
+ register int c;
+ do
+ {
+ switch(c= *cp)
+ {
+ case 0:
+ if(n<0)
+ return;
+ c = n;
+ break;
+ case '\n':
+ sfputr(iop,"$'\\n",'\'');
+ continue;
+ case '\\':
+ if (!(c = *++cp))
+ c = '\\';
+ /*FALLTHROUGH*/
+ case ' ':
+ case '<': case '>': case ';':
+ case '$': case '`': case '\t':
+ sfputc(iop,'\\');
+ break;
+ }
+ sfputc(iop,c);
+ }
+ while(*cp++);
+}
+
+static void out_string(Sfio_t *iop, register const char *cp, int c, int quoted)
+{
+ if(quoted)
+ {
+ int n = stktell(stkstd);
+ cp = sh_fmtq(cp);
+ if(iop==stkstd && cp==stkptr(stkstd,n))
+ {
+ *stkptr(stkstd,stktell(stkstd)-1) = c;
+ return;
+ }
+ }
+ sfputr(iop,cp,c);
+}
+
+struct Level
+{
+ Namfun_t hdr;
+ short maxlevel;
+};
+
+/*
+ * this is for a debugger but it hasn't been tested yet
+ * if a debug script sets .sh.level it should set up the scope
+ * as if you were executing in that level
+ */
+static void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shscope_t *sp;
+ struct Level *lp = (struct Level*)fp;
+ int16_t level, oldlevel = (int16_t)nv_getnum(np);
+ nv_putv(np,val,flags,fp);
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ return;
+ }
+ level = nv_getnum(np);
+ if(level<0 || level > lp->maxlevel)
+ {
+ nv_putv(np, (char*)&oldlevel, NV_INT16, fp);
+ /* perhaps this should be an error */
+ return;
+ }
+ if(level==oldlevel)
+ return;
+ if(sp = sh_getscope(level,SEEK_SET))
+ {
+ sh_setscope(sp);
+ error_info.id = sp->cmdname;
+
+ }
+}
+
+static const Namdisc_t level_disc = { sizeof(struct Level), put_level };
+
+static struct Level *init_level(Shell_t *shp,int level)
+{
+ struct Level *lp = newof(NiL,struct Level,1,0);
+ lp->maxlevel = level;
+ _nv_unset(SH_LEVELNOD,0);
+ nv_onattr(SH_LEVELNOD,NV_INT16|NV_NOFREE);
+ shp->last_root = nv_dict(DOTSHNOD);
+ nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16);
+ lp->hdr.disc = &level_disc;
+ nv_disc(SH_LEVELNOD,&lp->hdr,NV_FIRST);
+ return(lp);
+}
+
+/*
+ * write the current command on the stack and make it available as .sh.command
+ */
+int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags)
+{
+ Stk_t *stkp=shp->stk;
+ struct sh_scoped savst;
+ Namval_t *np = SH_COMMANDNOD;
+ char *sav = stkptr(stkp,0);
+ int n=4, offset=stktell(stkp);
+ const char *cp = "+=( ";
+ Sfio_t *iop = stkstd;
+ short level;
+ if(shp->indebug)
+ return(0);
+ shp->indebug = 1;
+ if(name)
+ {
+ sfputr(iop,name,-1);
+ if(subscript)
+ {
+ sfputc(iop,'[');
+ out_string(iop,subscript,']',1);
+ }
+ if(!(flags&ARG_APPEND))
+ cp+=1, n-=1;
+ if(!(flags&ARG_ASSIGN))
+ n -= 2;
+ sfwrite(iop,cp,n);
+ }
+ if(*argv && !(flags&ARG_RAW))
+ out_string(iop, *argv++,' ', 0);
+ n = (flags&ARG_ARITH);
+ while(cp = *argv++)
+ {
+ if((flags&ARG_EXP) && argv[1]==0)
+ out_pattern(iop, cp,' ');
+ else
+ out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
+ }
+ if(flags&ARG_ASSIGN)
+ sfputc(iop,')');
+ else if(iop==stkstd)
+ *stkptr(stkp,stktell(stkp)-1) = 0;
+ np->nvalue.cp = stkfreeze(stkp,1);
+ /* now setup .sh.level variable */
+ shp->st.lineno = error_info.line;
+ level = shp->fn_depth+shp->dot_depth;
+ shp->last_root = nv_dict(DOTSHNOD);
+ if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE))
+ init_level(shp,level);
+ else
+ nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
+ savst = shp->st;
+ shp->st.trap[SH_DEBUGTRAP] = 0;
+ n = sh_trap(trap,0);
+ np->nvalue.cp = 0;
+ shp->indebug = 0;
+ if(shp->st.cmdname)
+ error_info.id = shp->st.cmdname;
+ nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
+ nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
+ shp->st = savst;
+ if(sav != stkptr(stkp,0))
+ stkset(stkp,sav,0);
+ else
+ stkseek(stkp,offset);
+ return(n);
+}
+
+/*
+ * Given stream <iop> compile and execute
+ */
+int sh_eval(register Sfio_t *iop, int mode)
+{
+ register Shnode_t *t;
+ Shell_t *shp = sh_getinterp();
+ struct slnod *saveslp = shp->st.staklist;
+ int jmpval;
+ struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ static Sfio_t *io_save;
+ volatile int traceon=0, lineno=0;
+ int binscript=shp->binscript;
+ char comsub = shp->comsub;
+ io_save = iop; /* preserve correct value across longjmp */
+ shp->binscript = 0;
+ shp->comsub = 0;
+#define SH_TOPFUN 0x8000 /* this is a temporary tksh hack */
+ if (mode & SH_TOPFUN)
+ {
+ mode ^= SH_TOPFUN;
+ shp->fn_reset = 1;
+ }
+ sh_pushcontext(shp,buffp,SH_JMPEVAL);
+ buffp->olist = pp->olist;
+ jmpval = sigsetjmp(buffp->buff,0);
+ while(jmpval==0)
+ {
+ if(mode&SH_READEVAL)
+ {
+ lineno = shp->inlineno;
+ if(traceon=sh_isoption(SH_XTRACE))
+ sh_offoption(SH_XTRACE);
+ }
+ t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL);
+ if(!(mode&SH_FUNEVAL) || !sfreserve(iop,0,0))
+ {
+ if(!(mode&SH_READEVAL))
+ sfclose(iop);
+ io_save = 0;
+ mode &= ~SH_FUNEVAL;
+ }
+ mode &= ~SH_READEVAL;
+ if(!sh_isoption(SH_VERBOSE))
+ sh_offstate(SH_VERBOSE);
+ if((mode&~SH_FUNEVAL) && shp->gd->hist_ptr)
+ {
+ hist_flush(shp->gd->hist_ptr);
+ mode = sh_state(SH_INTERACTIVE);
+ }
+ sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL));
+ if(!(mode&SH_FUNEVAL))
+ break;
+ }
+ sh_popcontext(shp,buffp);
+ shp->binscript = binscript;
+ shp->comsub = comsub;
+ if(traceon)
+ sh_onoption(SH_XTRACE);
+ if(lineno)
+ shp->inlineno = lineno;
+ if(io_save)
+ sfclose(io_save);
+ sh_freeup(shp);
+ shp->st.staklist = saveslp;
+ shp->fn_reset = 0;
+ if(jmpval>SH_JMPEVAL)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(shp->exitval);
+}
+
+/*
+ * returns 1 when option -<c> is specified
+ */
+static int checkopt(char *argv[], int c)
+{
+ char *cp;
+ while(cp = *++argv)
+ {
+ if(*cp=='+')
+ continue;
+ if(*cp!='-' || cp[1]=='-')
+ break;
+ if(strchr(++cp,c))
+ return(1);
+ if(*cp=='h' && cp[1]==0 && *++argv==0)
+ break;
+ }
+ return(0);
+}
+
+static void free_list(struct openlist *olist)
+{
+ struct openlist *item,*next;
+ for(item=olist;item;item=next)
+ {
+ next = item->next;
+ free((void*)item);
+ }
+}
+
+/*
+ * set ${.sh.name} and ${.sh.subscript}
+ * set _ to reference for ${.sh.name}[$.sh.subscript]
+ */
+static int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr)
+{
+ char *sp=0,*cp;
+ Namarr_t *ap;
+ Namval_t *np;
+ if(!nv_isattr(nq,NV_MINIMAL|NV_EXPORT|NV_ARRAY) && (np=(Namval_t*)nq->nvenv) && nv_isarray(np))
+ nq = np;
+ cp = nv_name(nq);
+ memset(nr,0,sizeof(*nr));
+ nr->np = nq;
+ nr->root = shp->var_tree;
+ nr->table = shp->last_table;
+#if SHOPT_NAMESPACE
+ if(!nr->table && shp->namespace)
+ nr->table = shp->namespace;
+#endif /* SHOPT_NAMESPACE */
+ shp->instance = 1;
+ if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq)))
+ sp = strdup(sp);
+ shp->instance = 0;
+ if(shp->var_tree!=shp->var_base && !nv_search((char*)nq,nr->root,HASH_BUCKET|HASH_NOSCOPE))
+ {
+#if SHOPT_NAMESPACE
+ nr->root = shp->namespace?nv_dict(shp->namespace):shp->var_base;
+#else
+ nr->root = shp->var_base;
+#endif /* SHOPT_NAMESPACE */
+ }
+ nv_putval(SH_NAMENOD, cp, NV_NOFREE);
+ memcpy(node,L_ARGNOD,sizeof(*node));
+ L_ARGNOD->nvalue.nrp = nr;
+ L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
+ L_ARGNOD->nvfun = 0;
+ L_ARGNOD->nvenv = 0;
+ if(sp)
+ {
+ nv_putval(SH_SUBSCRNOD,nr->sub=sp,NV_NOFREE);
+ return(ap->nelem&ARRAY_SCAN);
+ }
+ return(0);
+}
+
+static void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode)
+{
+ L_ARGNOD->nvalue.nrp = node->nvalue.nrp;
+ L_ARGNOD->nvflag = node->nvflag;
+ L_ARGNOD->nvfun = node->nvfun;
+ if(nr->sub)
+ {
+ nv_putsub(nr->np, nr->sub, mode);
+ free((void*)nr->sub);
+ }
+ _nv_unset(SH_NAMENOD,0);
+ _nv_unset(SH_SUBSCRNOD,0);
+}
+
+#if SHOPT_COSHELL
+uintmax_t coused;
+/*
+ * print out function definition
+ */
+static void print_fun(register Namval_t* np, void *data)
+{
+ register char *format;
+ NOT_USED(data);
+ if(!is_afunction(np) || !np->nvalue.ip)
+ return;
+ if(nv_isattr(np,NV_FPOSIX))
+ format="%s()\n{ ";
+ else
+ format="function %s\n{ ";
+ sfprintf(sfstdout,format,nv_name(np));
+ sh_deparse(sfstdout,(Shnode_t*)(nv_funtree(np)),0);
+ sfwrite(sfstdout,"}\n",2);
+}
+
+static void *sh_coinit(Shell_t *shp,char **argv)
+{
+ struct cosh *csp = job.colist;
+ const char *name = argv?argv[0]:0;
+ int id, open=1;
+ if(!name)
+ return(0);
+ if(*name=='-')
+ {
+ name++;
+ open=0;
+ }
+ nv_open(name,shp->var_tree,NV_IDENT|NV_NOADD);
+ while(csp)
+ {
+ if(strcmp(name,csp->name)==0)
+ {
+ if(open)
+ {
+ coattr(csp->coshell,argv[1]);
+ return((void*)csp);
+ }
+ coclose(csp->coshell);
+ return(0);
+ }
+ csp = csp->next;
+ }
+ if(!open)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: unknown namespace",name);
+ environ[0][2]=0;
+ csp = newof(0,struct cosh,1,strlen(name)+1);
+ if(!(csp->coshell = coopen(NULL,CO_SHELL|CO_SILENT,argv[1])))
+ {
+ free((void*)csp);
+ errormsg(SH_DICT,ERROR_exit(1),"%s: unable to create namespace",name);
+ }
+ csp->coshell->data = (void*)csp;
+ csp->name = (char*)(csp+1);
+ strcpy(csp->name,name);
+ for(id=0; coused&(1<<id); id++);
+ coused |= (1<<id);
+ csp->id = id;
+ csp->next = job.colist;
+ job.colist = csp;
+ return((void*)csp);
+}
+
+int sh_coaddfile(Shell_t *shp, char *name)
+{
+ Namval_t *np = dtmatch(shp->inpool,name);
+ if(!np)
+ {
+ np = (Namval_t*)stakalloc(sizeof(Dtlink_t)+sizeof(char*));
+ np->nvname = name;
+ (Namval_t*)dtinsert(shp->inpool,np);
+ shp->poolfiles++;
+ return(1);
+ }
+ return(0);
+}
+
+static int sh_coexec(Shell_t *shp,const Shnode_t *t, int filt)
+{
+ struct cosh *csp = ((struct cosh*)shp->coshell);
+ Cojob_t *cjp;
+ char *str,*trap,host[PATH_MAX];
+ int lineno,sig,trace = sh_isoption(SH_XTRACE);
+ int verbose = sh_isoption(SH_VERBOSE);
+ sh_offoption(SH_XTRACE);
+ sh_offoption(SH_VERBOSE);
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ sfswap(shp->strbuf2,sfstdout);
+ sh_trap("typeset -p\nprint cd \"$PWD\"\nprint .sh.dollar=$$\nprint umask $(umask)",0);
+ for(sig=shp->st.trapmax;--sig>0;)
+ {
+ if((trap=shp->st.trapcom[sig]) && *trap==0)
+ sfprintf(sfstdout,"trap '' %d\n",sig);
+ }
+ if(t->tre.tretyp==TFIL)
+ lineno = ((struct forknod*)t->lst.lstlef)->forkline;
+ else
+ lineno = t->fork.forkline;
+ if(filt)
+ {
+ if(gethostname(host,sizeof(host)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ if(shp->inpipe[2]>=20000)
+ sfprintf(sfstdout,"command exec < /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->inpipe[2]);
+ sfprintf(sfstdout,"command exec > /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->outpipe[2]);
+ if(filt==3)
+ t = t->fork.forktre;
+ }
+ else
+ t = t->fork.forktre;
+ nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
+ if(1)
+ {
+ Dt_t *top = shp->var_tree;
+ sh_scope(shp,(struct argnod*)0,0);
+ shp->inpool = dtopen(&_Nvdisc,Dtset);
+ sh_exec(t,filt==1||filt==2?SH_NOFORK:0);
+ if(shp->poolfiles)
+ {
+ Namval_t *np;
+ sfprintf(sfstdout,"[[ ${.sh} == *pool* ]] && .sh.pool.files=(\n");
+ for(np=(Namval_t*)dtfirst(shp->inpool);np;np=(Namval_t*)dtnext(shp->inpool,np))
+ {
+ sfprintf(sfstdout,"\t%s\n",sh_fmtq(np->nvname));
+ }
+ sfputr(sfstdout,")",'\n');
+ ;
+ }
+ dtclose(shp->inpool);
+ shp->inpool = 0;
+ shp->poolfiles = 0;
+ sh_unscope(shp);
+ shp->var_tree = top;
+ }
+ sfprintf(sfstdout,"typeset -f .sh.pool.init && .sh.pool.init\n");
+ sfprintf(sfstdout,"LINENO=%d\n",lineno);
+ if(trace)
+ sh_onoption(SH_XTRACE);
+ if(verbose)
+ sh_onoption(SH_VERBOSE);
+ sh_trap("set +o",0);
+ sh_deparse(sfstdout,t,filt==1||filt==2?FALTPIPE:0);
+ sfputc(sfstdout,0);
+ sfswap(shp->strbuf2,sfstdout);
+ str = sfstruse(shp->strbuf2);
+ if(cjp=coexec(csp->coshell,str,0,NULL,NULL,NULL))
+ {
+ csp->cojob = cjp;
+ cjp->local = shp->coshell;
+ if(filt)
+ {
+ if(filt>1)
+ sh_coaccept(shp,shp->inpipe,1);
+ sh_coaccept(shp,shp->outpipe,0);
+ if(filt > 2)
+ {
+ shp->coutpipe = shp->inpipe[1];
+ shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
+ }
+ }
+ return(sh_copid(csp));
+ }
+ return(-1);
+}
+#endif /*SHOPT_COSHELL*/
+
+int sh_exec(register const Shnode_t *t, int flags)
+{
+ register Shell_t *shp = sh_getinterp();
+ Stk_t *stkp = shp->stk;
+ sh_sigcheck(shp);
+ if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC))
+ {
+ register int type = flags;
+ register char *com0 = 0;
+ int errorflg = (type&sh_state(SH_ERREXIT))|OPTIMIZE;
+ int execflg = (type&sh_state(SH_NOFORK));
+ int execflg2 = (type&sh_state(SH_FORKED));
+ int mainloop = (type&sh_state(SH_INTERACTIVE));
+#if SHOPT_AMP || SHOPT_SPAWN
+ int ntflag = (type&sh_state(SH_NTFORK));
+#else
+ int ntflag = 0;
+#endif
+ int topfd = shp->topfd;
+ char *sav=stkptr(stkp,0);
+ char *cp=0, **com=0, *comn;
+ int argn;
+ int skipexitset = 0;
+ int was_interactive = 0;
+ int was_errexit = sh_isstate(SH_ERREXIT);
+ int was_monitor = sh_isstate(SH_MONITOR);
+ int echeck = 0;
+ if(flags&sh_state(SH_INTERACTIVE))
+ {
+ if(pipejob==2)
+ job_unlock();
+ pipejob = 0;
+ job.curpgid = 0;
+ job.curjobid = 0;
+ flags &= ~sh_state(SH_INTERACTIVE);
+ }
+ sh_offstate(SH_ERREXIT);
+ sh_offstate(SH_DEFPATH);
+ if(was_errexit&flags)
+ sh_onstate(SH_ERREXIT);
+ if(was_monitor&flags)
+ sh_onstate(SH_MONITOR);
+ type = t->tre.tretyp;
+ if(!shp->intrap)
+ shp->oldexit=shp->exitval;
+ shp->exitval=0;
+ shp->lastsig = 0;
+ shp->lastpath = 0;
+ switch(type&COMMSK)
+ {
+ case TCOM:
+ {
+ register struct argnod *argp;
+ char *trap;
+ Namval_t *np, *nq, *last_table;
+ struct ionod *io;
+ int command=0, flgs=NV_ASSIGN;
+ shp->bltindata.invariant = type>>(COMBITS+2);
+ type &= (COMMSK|COMSCAN);
+ sh_stats(STAT_SCMDS);
+ error_info.line = t->com.comline-shp->st.firstline;
+ com = sh_argbuild(shp,&argn,&(t->com),OPTIMIZE);
+ echeck = 1;
+ if(t->tre.tretyp&COMSCAN)
+ {
+ argp = t->com.comarg;
+ if(argp && *com && !(argp->argflag&ARG_RAW))
+ sh_sigcheck(shp);
+ }
+ np = (Namval_t*)(t->com.comnamp);
+ nq = (Namval_t*)(t->com.comnamq);
+ com0 = com[0];
+ shp->xargexit = 0;
+ while(np==SYSCOMMAND)
+ {
+ register int n = b_command(0,com,&shp->bltindata);
+ if(n==0)
+ break;
+ command += n;
+ np = 0;
+ if(!(com0= *(com+=n)))
+ break;
+ np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
+ }
+ if(shp->xargexit)
+ {
+ shp->xargmin -= command;
+ shp->xargmax -= command;
+ }
+ else
+ shp->xargmin = 0;
+ argn -= command;
+#if SHOPT_COSHELL
+ if(argn && shp->inpool)
+ {
+ if(io=t->tre.treio)
+ sh_redirect(shp,io,0);
+ if(!np || !is_abuiltin(np) || *np->nvname=='/' || np==SYSCD)
+ {
+ char **argv, *cp;
+ for(argv=com+1; cp= *argv; argv++)
+ {
+ if(cp && *cp && *cp!='-')
+ sh_coaddfile(shp,*argv);
+ }
+ break;
+ }
+ if(np->nvalue.bfp!=SYSTYPESET->nvalue.bfp)
+ break;
+ }
+ if(t->tre.tretyp&FAMP)
+ {
+ shp->coshell = sh_coinit(shp,com);
+ com0 = 0;
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ if(np && is_abuiltin(np))
+ {
+ if(!command)
+ {
+ Namval_t *mp;
+#if SHOPT_NAMESPACE
+ if(shp->namespace && (mp=sh_fsearch(shp,np->nvname,0)))
+ np = mp;
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = dtsearch(shp->fun_tree,np);
+ }
+#if SHOPT_PFSH
+ if(sh_isoption(SH_PFSH) && nv_isattr(np,NV_BLTINOPT) && !nv_isattr(np,NV_BLTPFSH))
+ {
+ if(path_xattr(shp,np->nvname,(char*)0))
+ {
+ dtdelete(shp->bltin_tree,np);
+ np = 0;
+ }
+ else
+ nv_onattr(np,NV_BLTPFSH);
+
+ }
+#endif /* SHOPT_PFSH */
+ }
+ if(com0)
+ {
+ if(!np && !strchr(com0,'/'))
+ {
+ Dt_t *root = command?shp->bltin_tree:shp->fun_tree;
+ np = nv_bfsearch(com0, root, &nq, &cp);
+#if SHOPT_NAMESPACE
+ if(shp->namespace && !nq && !cp)
+ np = sh_fsearch(shp,com0,0);
+#endif /* SHOPT_NAMESPACE */
+ }
+ comn = com[argn-1];
+ }
+ io = t->tre.treio;
+ if(shp->envlist = argp = t->com.comset)
+ {
+ if(argn==0 || (np && nv_isattr(np,(BLT_DCL|BLT_SPC))))
+ {
+ Namval_t *tp=0;
+ if(argn)
+ {
+ if(checkopt(com,'A'))
+ flgs |= NV_ARRAY;
+ else if(checkopt(com,'a'))
+ flgs |= NV_IARRAY;
+ }
+#if SHOPT_BASH
+ if(np==SYSLOCAL)
+ {
+ if(!nv_getval(SH_FUNNAMENOD))
+ errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
+ if(!shp->st.var_local)
+ {
+ sh_scope(shp,(struct argnod*)0,0);
+ shp->st.var_local = shp->var_tree;
+ }
+
+ }
+#endif /* SHOPT_BASH */
+ if(np==SYSTYPESET || (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp))
+ {
+ if(np!=SYSTYPESET)
+ {
+ shp->typeinit = np;
+ tp = nv_type(np);
+ }
+ if(checkopt(com,'C'))
+ flgs |= NV_COMVAR;
+ if(checkopt(com,'S'))
+ flgs |= NV_STATIC;
+ if(checkopt(com,'m'))
+ flgs |= NV_MOVE;
+ if(checkopt(com,'n'))
+ flgs |= NV_NOREF;
+ else if(!shp->typeinit && (checkopt(com,'L') || checkopt(com,'R') || checkopt(com,'Z')))
+ flgs |= NV_UNJUST;
+#if SHOPT_TYPEDEF
+ else if(argn>=3 && checkopt(com,'T'))
+ {
+# if SHOPT_NAMESPACE
+ if(shp->namespace)
+ {
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ sfprintf(shp->strbuf2,"%s%s%c",NV_CLASS,nv_name(shp->namespace),0);
+ shp->prefix = strdup(sfstruse(shp->strbuf2));
+ nv_open(shp->prefix,shp->var_base,NV_VARNAME);
+ }
+ else
+# endif /* SHOPT_NAMESPACE */
+ shp->prefix = NV_CLASS;
+ flgs |= NV_TYPE;
+
+ }
+#endif /* SHOPT_TYPEDEF */
+ if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
+ flgs |= NV_NOSCOPE;
+ }
+ else if(np==SYSEXPORT)
+ flgs |= NV_EXPORT;
+ if(flgs&(NV_EXPORT|NV_NOREF))
+ flgs |= NV_IDENT;
+ else
+ flgs |= NV_VARNAME;
+#if 0
+ if(OPTIMIZE)
+ flgs |= NV_TAGGED;
+#endif
+ nv_setlist(argp,flgs,tp);
+ if(np==shp->typeinit)
+ shp->typeinit = 0;
+ shp->envlist = argp;
+ argp = NULL;
+ }
+ }
+ last_table = shp->last_table;
+ shp->last_table = 0;
+ if((io||argn))
+ {
+ Shbltin_t *bp=0;
+ static char *argv[1];
+ int tflags = 1;
+ if(np && nv_isattr(np,BLT_DCL))
+ tflags |= 2;
+ if(argn==0)
+ {
+ /* fake 'true' built-in */
+ np = SYSTRUE;
+ *argv = nv_name(np);
+ com = argv;
+ }
+ /* set +x doesn't echo */
+ else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME))
+ {
+ int ison = sh_isoption(SH_XTRACE);
+ if(!ison)
+ sh_onoption(SH_XTRACE);
+ sh_trace(shp,com-command,tflags);
+ if(io)
+ sh_redirect(shp,io,SH_SHOWME);
+ if(!ison)
+ sh_offoption(SH_XTRACE);
+ break;
+ }
+ else if((np!=SYSSET) && sh_isoption(SH_XTRACE))
+ sh_trace(shp,com-command,tflags);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ {
+ int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
+ if(n==255 && shp->fn_depth+shp->dot_depth)
+ {
+ np = SYSRETURN;
+ argn = 1;
+ com[0] = np->nvname;
+ com[1] = 0;
+ io = 0;
+ argp = 0;
+ }
+ else if(n==2)
+ break;
+ }
+ if(io)
+ sfsync(shp->outpool);
+ shp->lastpath = 0;
+ if(!np && !strchr(com0,'/'))
+ {
+ if(path_search(shp,com0,NIL(Pathcomp_t**),1))
+ {
+ error_info.line = t->com.comline-shp->st.firstline;
+#if SHOPT_NAMESPACE
+ if(!shp->namespace || !(np=sh_fsearch(shp,com0,0)))
+#endif /* SHOPT_NAMESPACE */
+ np=nv_search(com0,shp->fun_tree,0);
+ if(!np || !np->nvalue.ip)
+ {
+ Namval_t *mp=nv_search(com0,shp->bltin_tree,0);
+ if(mp)
+ np = mp;
+ }
+ }
+ else
+ {
+ if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
+ np=nv_search(nv_getval(np),shp->bltin_tree,0);
+ else
+ np = 0;
+ }
+ }
+ if(np && pipejob==2)
+ {
+ job_unlock();
+ pipejob = 1;
+ }
+ /* check for builtins */
+ if(np && is_abuiltin(np))
+ {
+ volatile int scope=0, share=0;
+ volatile void *save_ptr;
+ volatile void *save_data;
+ int jmpval, save_prompt;
+ int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ unsigned long was_vi=0, was_emacs=0, was_gmacs=0;
+ struct stat statb;
+ bp = &shp->bltindata;
+ save_ptr = bp->ptr;
+ save_data = bp->data;
+ memset(&statb, 0, sizeof(struct stat));
+ if(strchr(nv_name(np),'/'))
+ {
+ /*
+ * disable editors for built-in
+ * versions of commands on PATH
+ */
+ was_vi = sh_isoption(SH_VI);
+ was_emacs = sh_isoption(SH_EMACS);
+ was_gmacs = sh_isoption(SH_GMACS);
+ sh_offoption(SH_VI);
+ sh_offoption(SH_EMACS);
+ sh_offoption(SH_GMACS);
+ }
+ if(execflg)
+ sh_onstate(SH_NOFORK);
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ jmpval = sigsetjmp(buffp->buff,1);
+ if(jmpval == 0)
+ {
+ if(!(nv_isattr(np,BLT_ENV)))
+ error_info.flags |= ERROR_SILENT;
+ errorpush(&buffp->err,0);
+ if(io)
+ {
+ struct openlist *item;
+ if(np==SYSLOGIN)
+ type=1;
+ else if(np==SYSEXEC)
+ type=1+!com[1];
+ else
+ type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
+ shp->redir0 = 1;
+ sh_redirect(shp,io,type);
+ for(item=buffp->olist;item;item=item->next)
+ item->strm=0;
+ }
+ if(!(nv_isattr(np,BLT_ENV)))
+ {
+ if(bp->nosfio)
+ {
+ if(!shp->pwd)
+ path_pwd(shp,0);
+ if(shp->pwd)
+ stat(".",&statb);
+ }
+ sfsync(NULL);
+ share = sfset(sfstdin,SF_SHARE,0);
+ sh_onstate(SH_STOPOK);
+ sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
+ sfset(sfstderr,SF_LINE,1);
+ save_prompt = shp->nextprompt;
+ shp->nextprompt = 0;
+ }
+ if(argp)
+ {
+ scope++;
+ sh_scope(shp,argp,0);
+ }
+ opt_info.index = opt_info.offset = 0;
+ opt_info.disc = 0;
+ error_info.id = *com;
+ if(argn)
+ shp->exitval = 0;
+ shp->bltinfun = (Shbltin_f)funptr(np);
+ bp->bnode = np;
+ bp->vnode = nq;
+ bp->ptr = nv_context(np);
+ bp->data = t->com.comstate;
+ bp->sigset = 0;
+ bp->notify = 0;
+ bp->flags = (OPTIMIZE!=0);
+ if(shp->subshell && nv_isattr(np,BLT_NOSFIO))
+ sh_subtmpfile(shp);
+ if(execflg && !shp->subshell &&
+ !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
+ {
+ /* do close-on-exec */
+ int fd;
+ for(fd=0; fd < shp->gd->lim.open_max; fd++)
+ if((shp->fdstatus[fd]&IOCLEX)&&fd!=shp->infd)
+ sh_close(fd);
+ }
+ if(argn)
+ shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp);
+ if(error_info.flags&ERROR_INTERACTIVE)
+ tty_check(ERRIO);
+ ((Shnode_t*)t)->com.comstate = shp->bltindata.data;
+ bp->data = (void*)save_data;
+ if(sh.exitval && errno==EINTR && shp->lastsig)
+ sh.exitval = SH_EXITSIG|shp->lastsig;
+ else if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG)
+ shp->exitval &= SH_EXITMASK;
+ }
+ else
+ {
+ struct openlist *item;
+ for(item=buffp->olist;item;item=item->next)
+ {
+ if(item->strm)
+ {
+ sfclrlock(item->strm);
+ if(shp->gd->hist_ptr && item->strm == shp->gd->hist_ptr->histfp)
+ hist_close(shp->gd->hist_ptr);
+ else
+ sfclose(item->strm);
+ }
+ }
+ if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY))
+ (*shp->bltinfun)(-2,com,(void*)bp);
+ /* failure on special built-ins fatal */
+ if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command))
+ jmpval=0;
+ }
+ if(bp)
+ {
+ bp->bnode = 0;
+ if( bp->ptr!= nv_context(np))
+ np->nvfun = (Namfun_t*)bp->ptr;
+ }
+ if(execflg && !was_nofork)
+ sh_offstate(SH_NOFORK);
+ if(!(nv_isattr(np,BLT_ENV)))
+ {
+ if(bp->nosfio && shp->pwd)
+ {
+ struct stat stata;
+ stat(".",&stata);
+ /* restore directory changed */
+ if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
+ chdir(shp->pwd);
+ }
+ sh_offstate(SH_STOPOK);
+ if(share&SF_SHARE)
+ sfset(sfstdin,SF_PUBLIC|SF_SHARE,1);
+ sfset(sfstderr,SF_LINE,0);
+ sfpool(sfstderr,shp->outpool,SF_WRITE);
+ sfpool(sfstdin,NIL(Sfio_t*),SF_WRITE);
+ shp->nextprompt = save_prompt;
+ }
+ sh_popcontext(shp,buffp);
+ errorpop(&buffp->err);
+ error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY);
+ shp->bltinfun = 0;
+ if(buffp->olist)
+ free_list(buffp->olist);
+ if(was_vi)
+ sh_onoption(SH_VI);
+ else if(was_emacs)
+ sh_onoption(SH_EMACS);
+ else if(was_gmacs)
+ sh_onoption(SH_GMACS);
+ if(scope)
+ sh_unscope(shp);
+ bp->ptr = (void*)save_ptr;
+ bp->data = (void*)save_data;
+ /* don't restore for subshell exec */
+ if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC))
+ sh_iorestore(shp,topfd,jmpval);
+
+ shp->redir0 = 0;
+ if(jmpval)
+ siglongjmp(*shp->jmplist,jmpval);
+#if 0
+ if(flgs&NV_STATIC)
+ ((Shnode_t*)t)->com.comset = 0;
+#endif
+ if(shp->exitval >=0)
+ goto setexit;
+ np = 0;
+ type=0;
+ }
+ /* check for functions */
+ if(!command && np && nv_isattr(np,NV_FUNCTION))
+ {
+ volatile int indx;
+ int jmpval=0;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+#if SHOPT_NAMESPACE
+ Namval_t node,*namespace=shp->namespace;
+#else
+ Namval_t node;
+#endif /* SHOPT_NAMESPACE */
+ struct Namref nr;
+ long mode;
+ register struct slnod *slp;
+ if(!np->nvalue.ip)
+ {
+ indx = path_search(shp,com0,NIL(Pathcomp_t**),0);
+ if(indx==1)
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ np = sh_fsearch(shp,com0,0);
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = nv_search(com0,shp->fun_tree,HASH_NOSCOPE);
+ }
+
+ if(!np->nvalue.ip)
+ {
+ if(indx==1)
+ {
+ errormsg(SH_DICT,ERROR_exit(0),e_defined,com0);
+ shp->exitval = ERROR_NOEXEC;
+ }
+ else
+ {
+ errormsg(SH_DICT,ERROR_exit(0),e_found,"function");
+ shp->exitval = ERROR_NOENT;
+ }
+ goto setexit;
+ }
+ }
+ /* increase refcnt for unset */
+ slp = (struct slnod*)np->nvenv;
+ sh_funstaks(slp->slchild,1);
+ staklink(slp->slptr);
+ if(nq)
+ {
+ Namval_t *mp=0;
+ if(nv_isattr(np,NV_STATICF) && (mp=nv_type(nq)))
+ nq = mp;
+ shp->last_table = last_table;
+ mode = set_instance(shp,nq,&node,&nr);
+ }
+ if(io)
+ {
+ indx = shp->topfd;
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ jmpval = sigsetjmp(buffp->buff,0);
+ }
+ if(jmpval == 0)
+ {
+ if(io)
+ indx = sh_redirect(shp,io,execflg);
+#if SHOPT_NAMESPACE
+ if(nq && nv_istable(nq))
+ shp->namespace = nq;
+#endif /* SHOPT_NAMESPACE */
+ sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG));
+ }
+#if SHOPT_NAMESPACE
+ shp->namespace = namespace;
+#endif /* SHOPT_NAMESPACE */
+ if(io)
+ {
+ if(buffp->olist)
+ free_list(buffp->olist);
+ sh_popcontext(shp,buffp);
+ sh_iorestore(shp,indx,jmpval);
+ }
+ if(nq)
+ unset_instance(nq,&node,&nr,mode);
+ sh_funstaks(slp->slchild,-1);
+ stakdelete(slp->slptr);
+ if(jmpval > SH_JMPFUN)
+ siglongjmp(*shp->jmplist,jmpval);
+ goto setexit;
+ }
+ }
+ else if(!io)
+ {
+ setexit:
+ exitset();
+ break;
+ }
+ }
+ case TFORK:
+ {
+ register pid_t parent;
+ int no_fork,jobid;
+ int pipes[3];
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->fork.forktre,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ if(shp->subshell)
+ {
+ sh_subtmpfile(shp);
+ if(!usepipe)
+ {
+ subpipe[0] = -1;
+ if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK) && sh_pipe(subpipe)>=0)
+ iousepipe(shp);
+ }
+ if((type&(FAMP|TFORK))==(FAMP|TFORK))
+ sh_subfork();
+ }
+ no_fork = !ntflag && !(type&(FAMP|FPOU)) &&
+ !(shp->st.trapcom[SIGINT] && *shp->st.trapcom[SIGINT]) &&
+ !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
+ ((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL &&
+ (execflg2 || (execflg &&
+ !shp->subshell && shp->fn_depth==0 &&
+ !(pipejob && sh_isoption(SH_PIPEFAIL))
+ ));
+ if(sh_isstate(SH_PROFILE) || shp->dot_depth)
+ {
+ /* disable foreground job monitor */
+ if(!(type&FAMP))
+ sh_offstate(SH_MONITOR);
+#if SHOPT_DEVFD
+ else if(!(type&FINT))
+ sh_offstate(SH_MONITOR);
+#endif /* SHOPT_DEVFD */
+ }
+ if(no_fork)
+ job.parent=parent=0;
+ else
+ {
+#ifdef SHOPT_BGX
+ int maxjob;
+ if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
+ {
+ while(job.numbjob >= maxjob)
+ {
+ job_lock();
+ job_reap(0);
+ job_unlock();
+ }
+ }
+#endif /* SHOPT_BGX */
+ nv_getval(RANDNOD);
+ restorefd = shp->topfd;
+ if(type&FCOOP)
+ {
+ pipes[2] = 0;
+#if SHOPT_COSHELL
+ if(shp->coshell)
+ {
+ if(shp->cpipe[0]<0 || shp->cpipe[1] < 0)
+ {
+ sh_copipe(shp,shp->outpipe=shp->cpipe,0);
+ shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
+ }
+ sh_copipe(shp,shp->inpipe=pipes,0);
+ parent = sh_coexec(shp,t,3);
+ shp->cpid = parent;
+ jobid = job_post(shp,parent,0);
+ goto skip;
+ }
+#endif /* SHOPT_COSHELL */
+ coproc_init(shp,pipes);
+ }
+#if SHOPT_COSHELL
+ if((type&(FAMP|FINT)) == (FAMP|FINT))
+ {
+ if(shp->coshell)
+ {
+ parent = sh_coexec(shp,t,0);
+ jobid = job_post(shp,parent,0);
+ goto skip;
+ }
+ }
+#endif /* SHOPT_COSHELL */
+#if SHOPT_AMP
+ if((type&(FAMP|FINT)) == (FAMP|FINT))
+ parent = sh_ntfork(shp,t,com,&jobid,ntflag);
+ else
+ parent = sh_fork(shp,type,&jobid);
+ if(parent<0)
+ {
+ if(shp->comsub==1 && subpipe[0]>=0)
+ iounpipe(shp);
+ break;
+ }
+#else
+#if SHOPT_SPAWN
+# ifdef _lib_fork
+ if(com)
+ parent = sh_ntfork(shp,t,com,&jobid,ntflag);
+ else
+ parent = sh_fork(shp,type,&jobid);
+# else
+ if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0)
+ break;
+# endif /* _lib_fork */
+ if(parent<0)
+ {
+ if(shp->comsub==1 && subpipe[0]>=0)
+ iounpipe(shp);
+ break;
+ }
+#else
+ parent = sh_fork(shp,type,&jobid);
+#endif /* SHOPT_SPAWN */
+#endif
+ }
+#if SHOPT_COSHELL
+ skip:
+#endif /* SHOPT_COSHELL */
+ if(job.parent=parent)
+ /* This is the parent branch of fork
+ * It may or may not wait for the child
+ */
+ {
+ if(pipejob==2)
+ {
+ pipejob = 1;
+ job_unlock();
+ }
+ if(type&FPCL)
+ sh_close(shp->inpipe[0]);
+ if(type&(FCOOP|FAMP))
+ shp->bckpid = parent;
+ else if(!(type&(FAMP|FPOU)))
+ {
+ if(!sh_isoption(SH_MONITOR))
+ {
+ if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF)))
+ sh_sigtrap(SIGINT);
+ shp->trapnote |= SH_SIGIGNORE;
+ }
+ if(shp->pipepid)
+ shp->pipepid = parent;
+ else
+ job_wait(parent);
+ if(shp->topfd > topfd)
+ sh_iorestore(shp,topfd,sh.exitval);
+ if(usepipe && tsetio && subdup)
+ iounpipe(shp);
+ if(!sh_isoption(SH_MONITOR))
+ {
+ shp->trapnote &= ~SH_SIGIGNORE;
+ if(shp->exitval == (SH_EXITSIG|SIGINT))
+ sh_fault(SIGINT);
+ }
+ }
+ if(type&FAMP)
+ {
+ if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE))
+ {
+ /* print job number */
+#ifdef JOBS
+# if SHOPT_COSHELL
+ sfprintf(sfstderr,"[%d]\t%s\n",jobid,sh_pid2str(shp,parent));
+# else
+ sfprintf(sfstderr,"[%d]\t%d\n",jobid,parent);
+# endif /* SHOPT_COSHELL */
+#else
+ sfprintf(sfstderr,"%d\n",parent);
+#endif /* JOBS */
+ }
+ }
+ break;
+ }
+ else
+ /*
+ * this is the FORKED branch (child) of execute
+ */
+ {
+ volatile int jmpval;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ struct ionod *iop;
+ int rewrite=0;
+ if(no_fork)
+ sh_sigreset(2);
+ sh_pushcontext(shp,buffp,SH_JMPEXIT);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval)
+ goto done;
+ if((type&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ /* default std input for & */
+ signal(SIGINT,SIG_IGN);
+ signal(SIGQUIT,SIG_IGN);
+ if(!shp->st.ioset)
+ {
+ if(sh_close(0)>=0)
+ sh_chkopen(e_devnull);
+ }
+ }
+ sh_offstate(SH_MONITOR);
+ /* pipe in or out */
+#ifdef _lib_nice
+ if((type&FAMP) && sh_isoption(SH_BGNICE))
+ nice(4);
+#endif /* _lib_nice */
+#if !SHOPT_DEVFD
+ if(shp->fifo && (type&(FPIN|FPOU)))
+ {
+ int fn,fd = (type&FPIN)?0:1;
+ void *fifo_timer=sh_timeradd(500,1,fifo_check,(void*)shp);
+ fn = sh_open(shp->fifo,fd?O_WRONLY:O_RDONLY);
+ timerdel(fifo_timer);
+ sh_iorenumber(shp,fn,fd);
+ sh_close(fn);
+ sh_delay(.001);
+ unlink(shp->fifo);
+ free(shp->fifo);
+ shp->fifo = 0;
+ type &= ~(FPIN|FPOU);
+ }
+#endif /* !SHOPT_DEVFD */
+ if(type&FPIN)
+ {
+#if SHOPT_COSHELL
+ if(shp->inpipe[2]>20000)
+ sh_coaccept(shp,shp->inpipe,0);
+#endif /* SHOPT_COSHELL */
+ sh_iorenumber(shp,shp->inpipe[0],0);
+ if(!(type&FPOU) || (type&FCOOP))
+ sh_close(shp->inpipe[1]);
+ }
+ if(type&FPOU)
+ {
+#if SHOPT_COSHELL
+ if(shp->outpipe[2]>20000)
+ sh_coaccept(shp,shp->outpipe,1);
+#endif /* SHOPT_COSHELL */
+ sh_iorenumber(shp,shp->outpipe[1],1);
+ sh_pclose(shp->outpipe);
+ }
+ if((type&COMMSK)!=TCOM)
+ error_info.line = t->fork.forkline-shp->st.firstline;
+ if(shp->topfd)
+ sh_iounsave(shp);
+ topfd = shp->topfd;
+ if(com0 && (iop=t->tre.treio))
+ {
+ for(;iop;iop=iop->ionxt)
+ {
+ if(iop->iofile&IOREWRITE)
+ rewrite = 1;
+ }
+ }
+ sh_redirect(shp,t->tre.treio,1);
+ if(rewrite)
+ {
+ job_lock();
+ while((parent = vfork()) < 0)
+ _sh_fork(shp,parent, 0, (int*)0);
+ if(parent)
+ {
+ job_post(shp,parent,0);
+ job_wait(parent);
+ sh_iorestore(shp,topfd,SH_JMPCMD);
+ sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0);
+
+ }
+ job_unlock();
+ }
+ if((type&COMMSK)!=TCOM)
+ {
+ /* don't clear job table for out
+ pipes so that jobs comand can
+ be used in a pipeline
+ */
+ if(!no_fork && !(type&FPOU))
+ job_clear();
+ sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED));
+ }
+ else if(com0)
+ {
+ sh_offoption(SH_ERREXIT);
+ sh_freeup(shp);
+ path_exec(shp,com0,com,t->com.comset);
+ }
+ done:
+ sh_popcontext(shp,buffp);
+ if(jmpval>SH_JMPEXIT)
+ siglongjmp(*shp->jmplist,jmpval);
+ sh_done(shp,0);
+ }
+ }
+
+ case TSETIO:
+ {
+ /*
+ * don't create a new process, just
+ * save and restore io-streams
+ */
+ pid_t pid;
+ int jmpval, waitall;
+ int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_redirect(shp,t->fork.forkio,0);
+ sh_exec(t->fork.forktre,0);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+ if(shp->subshell)
+ execflg = 0;
+ sh_pushcontext(shp,buffp,SH_JMPIO);
+ if(type&FPIN)
+ {
+ was_interactive = sh_isstate(SH_INTERACTIVE);
+ sh_offstate(SH_INTERACTIVE);
+ sh_iosave(shp,0,shp->topfd,(char*)0);
+ shp->pipepid = simple;
+ sh_iorenumber(shp,shp->inpipe[0],0);
+ /*
+ * if read end of pipe is a simple command
+ * treat as non-sharable to improve performance
+ */
+ if(simple)
+ sfset(sfstdin,SF_PUBLIC|SF_SHARE,0);
+ waitall = job.waitall;
+ job.waitall = 0;
+ pid = job.parent;
+ }
+ else
+ error_info.line = t->fork.forkline-shp->st.firstline;
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval==0)
+ {
+ if(shp->comsub==1)
+ tsetio = 1;
+ sh_redirect(shp,t->fork.forkio,execflg);
+ (t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
+ sh_exec(t->fork.forktre,flags&~simple);
+ }
+ else
+ sfsync(shp->outpool);
+ sh_popcontext(shp,buffp);
+ sh_iorestore(shp,buffp->topfd,jmpval);
+ if(buffp->olist)
+ free_list(buffp->olist);
+ if(type&FPIN)
+ {
+ job.waitall = waitall;
+ type = shp->exitval;
+ if(!(type&SH_EXITSIG))
+ {
+ /* wait for remainder of pipline */
+ if(shp->pipepid>1)
+ {
+ job_wait(shp->pipepid);
+ type = shp->exitval;
+ }
+ else
+ job_wait(waitall?pid:0);
+ if(type || !sh_isoption(SH_PIPEFAIL))
+ shp->exitval = type;
+ }
+ if(shp->comsub==1 && subpipe[0]>=0)
+ iounpipe(shp);
+ shp->pipepid = 0;
+ shp->st.ioset = 0;
+ if(simple && was_errexit)
+ {
+ echeck = 1;
+ sh_onstate(SH_ERREXIT);
+ }
+ }
+ if(jmpval>SH_JMPIO)
+ siglongjmp(*shp->jmplist,jmpval);
+ break;
+ }
+
+ case TPAR:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->par.partre,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ echeck = 1;
+ flags &= ~OPTIMIZE_FLAG;
+ if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK)))
+ {
+ char *savsig;
+ int nsig,jmpval;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ shp->st.otrapcom = 0;
+ if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
+ {
+ nsig += sizeof(char*);
+ memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
+ shp->st.otrapcom = (char**)savsig;
+ }
+ sh_sigreset(0);
+ sh_pushcontext(shp,buffp,SH_JMPEXIT);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval==0)
+ sh_exec(t->par.partre,flags);
+ sh_popcontext(shp,buffp);
+ if(jmpval > SH_JMPEXIT)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(shp->exitval > 256)
+ shp->exitval -= 128;
+ sh_done(shp,0);
+ }
+ else if(((type=t->par.partre->tre.tretyp)&FAMP) && ((type&COMMSK)==TFORK))
+ {
+ pid_t pid;
+ sfsync(NIL(Sfio_t*));
+ while((pid=fork())< 0)
+ _sh_fork(shp,pid,0,0);
+ if(pid==0)
+ {
+ sh_exec(t->par.partre,flags);
+ shp->st.trapcom[0]=0;
+ sh_done(shp,0);
+ }
+ }
+ else
+ sh_subshell(shp,t->par.partre,flags,0);
+ break;
+
+ case TFIL:
+ {
+ /*
+ * This code sets up a pipe.
+ * All elements of the pipe are started by the parent.
+ * The last element executes in current environment
+ */
+ int pvo[3]; /* old pipe for multi-stage */
+ int pvn[3]; /* current set up pipe */
+ int savepipe = pipejob;
+ int showme = t->tre.tretyp&FSHOWME;
+ int n,waitall,savewaitall=job.waitall;
+ int savejobid = job.curjobid;
+ int *exitval=0,*saveexitval = job.exitval;
+ pid_t savepgid = job.curpgid;
+#if SHOPT_COSHELL
+ int copipe=0;
+ Shnode_t *tt;
+#endif /* SHOPT_COSHELL */
+ job.exitval = 0;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ do
+ {
+ sh_exec(t->lst.lstlef, 0);
+ t = t->lst.lstrit;
+ if(flags && (t->tre.tretyp!=TFIL || !(t->lst.lstlef->tre.tretyp&FALTPIPE)))
+ goto coskip1;
+ }
+ while(t->tre.tretyp==TFIL);
+ sh_exec(t,0);
+ coskip1:
+ break;
+ }
+ pvo[2] = pvn[2] = 0;
+#endif /* SHOPT_COSHELL */
+ job.curjobid = 0;
+ if(shp->subshell)
+ {
+ sh_subtmpfile(shp);
+ if(!usepipe)
+ {
+ subpipe[0] = -1;
+ if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK) && sh_pipe(subpipe)>=0)
+ iousepipe(shp);
+ }
+ }
+ shp->inpipe = pvo;
+ shp->outpipe = pvn;
+ pvo[1] = -1;
+ if(sh_isoption(SH_PIPEFAIL))
+ {
+ const Shnode_t* tn=t;
+ job.waitall = 2;
+ job.curpgid = 0;
+ while((tn=tn->lst.lstrit) && tn->tre.tretyp==TFIL)
+ job.waitall++;
+ exitval = job.exitval = (int*)stakalloc(job.waitall*sizeof(int));
+ memset(exitval,0,job.waitall*sizeof(int));
+ }
+ else
+ job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
+ job_lock();
+ do
+ {
+ /* create the pipe */
+#if SHOPT_COSHELL
+ tt = t->lst.lstrit;
+ if(shp->coshell && !showme)
+ {
+ if(t->lst.lstlef->tre.tretyp&FALTPIPE)
+ {
+ sh_copipe(shp,pvn,0);
+ type = sh_coexec(shp,t,1+copipe);
+ pvn[1] = -1;
+ pipejob=1;
+ if(type>0)
+ {
+ job_post(shp,type,0);
+ type = 0;
+ }
+ copipe = 1;
+ pvo[0] = pvn[0];
+ while(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
+ tt = tt->lst.lstrit;
+ t = tt;
+ continue;
+ }
+ else if(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
+ {
+ sh_copipe(shp,pvn,0);
+ pvo[2] = pvn[2];
+ copipe = 0;
+ goto coskip2;
+ }
+ }
+#endif /* SHOPT_COSHELL */
+ sh_pipe(pvn);
+#if SHOPT_COSHELL
+ pvn[2] = 0;
+ coskip2:
+#endif /* SHOPT_COSHELL */
+ /* execute out part of pipe no wait */
+ (t->lst.lstlef)->tre.tretyp |= showme;
+ type = sh_exec(t->lst.lstlef, errorflg);
+ /* close out-part of pipe */
+ sh_close(pvn[1]);
+ pipejob=1;
+ /* save the pipe stream-ids */
+ pvo[0] = pvn[0];
+ /* pipeline all in one process group */
+ t = t->lst.lstrit;
+ }
+ /* repeat until end of pipeline */
+ while(!type && t->tre.tretyp==TFIL);
+ shp->inpipe = pvn;
+ shp->outpipe = 0;
+ pipejob = 2;
+ waitall = job.waitall;
+ job.waitall = 0;
+ if(type == 0)
+ {
+ /*
+ * execute last element of pipeline
+ * in the current process
+ */
+ ((Shnode_t*)t)->tre.tretyp |= showme;
+ sh_exec(t,flags);
+ }
+ else
+ /* execution failure, close pipe */
+ sh_pclose(pvn);
+ if(pipejob==2)
+ job_unlock();
+ pipejob = savepipe;
+ n = shp->exitval;
+ if(job.waitall = waitall)
+ {
+ if(sh_isstate(SH_MONITOR))
+ job_wait(0);
+ else
+ {
+ shp->intrap++;
+ job_wait(0);
+ shp->intrap--;
+ }
+ }
+ if(n==0 && exitval)
+ {
+ while(exitval <= --job.exitval)
+ {
+ if(*job.exitval)
+ {
+ n = *job.exitval;
+ break;
+ }
+ }
+ }
+ shp->exitval = n;
+#ifdef SIGTSTP
+ if(!pipejob && sh_isstate(SH_MONITOR))
+ tcsetpgrp(JOBTTY,shp->gd->pid);
+#endif /*SIGTSTP */
+ job.curpgid = savepgid;
+ job.exitval = saveexitval;
+ job.waitall = savewaitall;
+ job.curjobid = savejobid;
+ break;
+ }
+
+ case TLST:
+ {
+ /* a list of commands are executed here */
+ do
+ {
+ sh_exec(t->lst.lstlef,errorflg|OPTIMIZE);
+ t = t->lst.lstrit;
+ }
+ while(t->tre.tretyp == TLST);
+ sh_exec(t,flags);
+ break;
+ }
+
+ case TAND:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ andor:
+ sh_exec(t->lst.lstlef,0);
+ sh_exec(t->lst.lstrit,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ if(type&TTEST)
+ skipexitset++;
+ if(sh_exec(t->lst.lstlef,OPTIMIZE)==0)
+ sh_exec(t->lst.lstrit,flags);
+ break;
+
+ case TORF:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ goto andor;
+#endif /* SHOPT_COSHELL */
+ if(type&TTEST)
+ skipexitset++;
+ if(sh_exec(t->lst.lstlef,OPTIMIZE)!=0)
+ sh_exec(t->lst.lstrit,flags);
+ break;
+
+ case TFOR: /* for and select */
+ {
+ register char **args;
+ register int nargs;
+ register Namval_t *np;
+ int flag = errorflg|OPTIMIZE_FLAG;
+ struct dolnod *argsav=0;
+ struct comnod *tp;
+ char *cp, *trap, *nullptr = 0;
+ int nameref, refresh=1;
+ char *av[5];
+#if SHOPT_COSHELL
+ int poolfiles;
+#endif /* SHOPT_COSHELL */
+#if SHOPT_OPTIMIZE
+ int jmpval = ((struct checkpt*)shp->jmplist)->mode;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ void *optlist = shp->optlist;
+ shp->optlist = 0;
+ sh_tclear(t->for_.fortre);
+ sh_pushcontext(shp,buffp,jmpval);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval)
+ goto endfor;
+#endif /* SHOPT_OPTIMIZE */
+ error_info.line = t->for_.forline-shp->st.firstline;
+ if(!(tp=t->for_.forlst))
+ {
+ args=shp->st.dolv+1;
+ nargs = shp->st.dolc;
+ argsav=sh_arguse(shp);
+ }
+ else
+ {
+ args=sh_argbuild(shp,&argn,tp,0);
+ nargs = argn;
+ }
+ np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF);
+ nameref = nv_isref(np)!=0;
+ shp->st.loopcnt++;
+ cp = *args;
+ while(cp && shp->st.execbrk==0)
+ {
+ if(t->tre.tretyp&COMSCAN)
+ {
+ char *val;
+ int save_prompt;
+ /* reuse register */
+ if(refresh)
+ {
+ sh_menu(sfstderr,nargs,args);
+ refresh = 0;
+ }
+ save_prompt = shp->nextprompt;
+ shp->nextprompt = 3;
+ shp->timeout = 0;
+ shp->exitval=sh_readline(shp,&nullptr,0,1,1000*shp->st.tmout);
+ shp->nextprompt = save_prompt;
+ if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin))
+ {
+ shp->exitval = 1;
+ break;
+ }
+ if(!(val=nv_getval(sh_scoped(shp,REPLYNOD))))
+ continue;
+ else
+ {
+ if(*(cp=val) == 0)
+ {
+ refresh++;
+ goto check;
+ }
+ while(type = *cp++)
+ if(type < '0' && type > '9')
+ break;
+ if(type!=0)
+ type = nargs;
+ else
+ type = (int)strtol(val, (char**)0, 10)-1;
+ if(type<0 || type >= nargs)
+ cp = "";
+ else
+ cp = args[type];
+ }
+ }
+ if(nameref)
+ nv_offattr(np,NV_REF);
+ else if(nv_isattr(np, NV_ARRAY))
+ nv_putsub(np,NIL(char*),0L);
+ nv_putval(np,cp,0);
+ if(nameref)
+ nv_setref(np,(Dt_t*)0,NV_VARNAME);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ {
+ av[0] = (t->tre.tretyp&COMSCAN)?"select":"for";
+ av[1] = t->for_.fornam;
+ av[2] = "in";
+ av[3] = cp;
+ av[4] = 0;
+ sh_debug(shp,trap,(char*)0,(char*)0,av,0);
+ }
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ poolfiles = shp->poolfiles;
+ sh_exec(t->for_.fortre,0);
+ if(poolfiles==shp->poolfiles)
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ sh_exec(t->for_.fortre,flag);
+ flag &= ~OPTIMIZE_FLAG;
+ if(t->tre.tretyp&COMSCAN)
+ {
+ if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0)
+ refresh++;
+ }
+ else
+ cp = *++args;
+ check:
+ if(shp->st.breakcnt<0)
+ shp->st.execbrk = (++shp->st.breakcnt !=0);
+ }
+#if SHOPT_OPTIMIZE
+ endfor:
+ sh_popcontext(shp,buffp);
+ sh_tclear(t->for_.fortre);
+ sh_optclear(shp,optlist);
+ if(jmpval)
+ siglongjmp(*shp->jmplist,jmpval);
+#endif /*SHOPT_OPTIMIZE */
+ if(shp->st.breakcnt>0)
+ shp->st.execbrk = (--shp->st.breakcnt !=0);
+ shp->st.loopcnt--;
+ sh_argfree(shp,argsav,0);
+ nv_close(np);
+ break;
+ }
+
+ case TWH: /* while and until */
+ {
+ volatile int r=0;
+ int first = OPTIMIZE_FLAG;
+ Shnode_t *tt = t->wh.whtre;
+#if SHOPT_FILESCAN
+ Sfio_t *iop=0;
+ int savein,fd;
+#endif /*SHOPT_FILESCAN*/
+#if SHOPT_OPTIMIZE
+ int jmpval = ((struct checkpt*)shp->jmplist)->mode;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ void *optlist = shp->optlist;
+#endif /* SHOPT_OPTIMIZE */
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ int poolfiles;
+# if SHOPT_FILESCAN
+ if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
+ {
+ sh_redirect(shp,tt->com.comio,0);
+ break;
+ }
+# endif /* SHOPT_FILESCAN */
+ sh_exec(tt,0);
+ do
+ {
+ if((sh_exec(tt,0)==0)!=(type==TWH))
+ break;
+ poolfiles = shp->poolfiles;
+ sh_exec(t->wh.dotre,0);
+ if(t->wh.whinc)
+ sh_exec((Shnode_t*)t->wh.whinc,0);
+ }
+ while(poolfiles != shp->poolfiles);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+#if SHOPT_OPTIMIZE
+ shp->optlist = 0;
+ sh_tclear(t->wh.whtre);
+ sh_tclear(t->wh.dotre);
+ sh_pushcontext(shp,buffp,jmpval);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval)
+ goto endwhile;
+#endif /* SHOPT_OPTIMIZE */
+#if SHOPT_FILESCAN
+ if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
+ {
+ fd = sh_redirect(shp,tt->com.comio,3);
+ savein = dup(0);
+ if(fd==0)
+ fd = savein;
+ iop = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ);
+ close(0);
+ open(e_devnull,O_RDONLY);
+ shp->offsets[0] = -1;
+ shp->offsets[1] = 0;
+ if(tt->com.comset)
+ nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0);
+ }
+#endif /*SHOPT_FILESCAN */
+ shp->st.loopcnt++;
+ while(shp->st.execbrk==0)
+ {
+#if SHOPT_FILESCAN
+ if(iop)
+ {
+ if(!(shp->cur_line=sfgetr(iop,'\n',SF_STRING)))
+ break;
+ }
+ else
+#endif /*SHOPT_FILESCAN */
+ if((sh_exec(tt,first)==0)!=(type==TWH))
+ break;
+ r = sh_exec(t->wh.dotre,first|errorflg);
+ if(shp->st.breakcnt<0)
+ shp->st.execbrk = (++shp->st.breakcnt !=0);
+ /* This is for the arithmetic for */
+ if(shp->st.execbrk==0 && t->wh.whinc)
+ sh_exec((Shnode_t*)t->wh.whinc,first);
+ first = 0;
+ errorflg &= ~OPTIMIZE_FLAG;
+#if SHOPT_FILESCAN
+ shp->offsets[0] = -1;
+ shp->offsets[1] = 0;
+#endif /*SHOPT_FILESCAN */
+ }
+#if SHOPT_OPTIMIZE
+ endwhile:
+ sh_popcontext(shp,buffp);
+ sh_tclear(t->wh.whtre);
+ sh_tclear(t->wh.dotre);
+ sh_optclear(shp,optlist);
+ if(jmpval)
+ siglongjmp(*shp->jmplist,jmpval);
+#endif /*SHOPT_OPTIMIZE */
+ if(shp->st.breakcnt>0)
+ shp->st.execbrk = (--shp->st.breakcnt !=0);
+ shp->st.loopcnt--;
+ shp->exitval= r;
+#if SHOPT_FILESCAN
+ if(iop)
+ {
+ sfclose(iop);
+ close(0);
+ dup(savein);
+ shp->cur_line = 0;
+ }
+#endif /*SHOPT_FILESCAN */
+ break;
+ }
+ case TARITH: /* (( expression )) */
+ {
+ register char *trap;
+ char *arg[4];
+ error_info.line = t->ar.arline-shp->st.firstline;
+ arg[0] = "((";
+ if(!(t->ar.arexpr->argflag&ARG_RAW))
+ arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH);
+ else
+ arg[1] = t->ar.arexpr->argval;
+ arg[2] = "))";
+ arg[3] = 0;
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH);
+ if(sh_isoption(SH_XTRACE))
+ {
+ sh_trace(shp,NIL(char**),0);
+ sfprintf(sfstderr,"((%s))\n",arg[1]);
+ }
+ if(t->ar.arcomp)
+ shp->exitval = !arith_exec((Arith_t*)t->ar.arcomp);
+ else
+ shp->exitval = !sh_arith(shp,arg[1]);
+ break;
+ }
+
+ case TIF:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->if_.thtre,0);
+ if(t->if_.eltre)
+ sh_exec(t->if_.eltre, 0);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+ if(sh_exec(t->if_.iftre,OPTIMIZE)==0)
+ sh_exec(t->if_.thtre,flags);
+ else if(t->if_.eltre)
+ sh_exec(t->if_.eltre, flags);
+ else
+ shp->exitval=0; /* force zero exit for if-then-fi */
+ break;
+
+ case TSW:
+ {
+ Shnode_t *tt = (Shnode_t*)t;
+ char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE);
+ error_info.line = t->sw.swline-shp->st.firstline;
+ t= (Shnode_t*)(tt->sw.swlst);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ {
+ char *av[4];
+ av[0] = "case";
+ av[1] = r;
+ av[2] = "in";
+ av[3] = 0;
+ sh_debug(shp,trap, (char*)0, (char*)0, av, 0);
+ }
+ while(t)
+ {
+ register struct argnod *rex=(struct argnod*)t->reg.regptr;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->reg.regcom,0);
+ continue;
+ }
+#endif /*SHOPT_COSHELL */
+ while(rex)
+ {
+ register char *s;
+ if(rex->argflag&ARG_MAC)
+ {
+ s = sh_macpat(shp,rex,OPTIMIZE|ARG_EXP);
+ while(*s=='\\' && s[1]==0)
+ s+=2;
+ }
+ else
+ s = rex->argval;
+ type = (rex->argflag&ARG_RAW);
+ if((type && strcmp(r,s)==0) ||
+ (!type && (strmatch(r,s)
+ || trim_eq(r,s))))
+ {
+ do sh_exec(t->reg.regcom,(t->reg.regflag?(flags&sh_state(SH_ERREXIT)):flags));
+ while(t->reg.regflag &&
+ (t=(Shnode_t*)t->reg.regnxt));
+ t=0;
+ break;
+ }
+ else
+ rex=rex->argnxt.ap;
+ }
+ if(t)
+ t=(Shnode_t*)t->reg.regnxt;
+ }
+ break;
+ }
+
+ case TTIME:
+ {
+ /* time the command */
+ struct tms before,after;
+ const char *format = e_timeformat;
+ clock_t at, tm[3];
+#ifdef timeofday
+ struct timeval tb,ta;
+#else
+ clock_t bt;
+#endif /* timeofday */
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ if(t->par.partre)
+ sh_exec(t->par.partre,0);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+ if(type!=TTIME)
+ {
+ sh_exec(t->par.partre,OPTIMIZE);
+ shp->exitval = !shp->exitval;
+ break;
+ }
+ if(t->par.partre)
+ {
+ long timer_on;
+ if(shp->subshell && shp->comsub==1)
+ sh_subfork();
+ timer_on = sh_isstate(SH_TIMING);
+#ifdef timeofday
+ timeofday(&tb);
+ times(&before);
+#else
+ bt = times(&before);
+#endif /* timeofday */
+ job.waitall = 1;
+ sh_onstate(SH_TIMING);
+ sh_exec(t->par.partre,OPTIMIZE);
+ if(!timer_on)
+ sh_offstate(SH_TIMING);
+ job.waitall = 0;
+ }
+ else
+ {
+#ifndef timeofday
+ bt = 0;
+#endif /* timeofday */
+ before.tms_utime = before.tms_cutime = 0;
+ before.tms_stime = before.tms_cstime = 0;
+ }
+#ifdef timeofday
+ times(&after);
+ timeofday(&ta);
+ at = shp->gd->lim.clk_tck*(ta.tv_sec-tb.tv_sec);
+ at += ((shp->gd->lim.clk_tck*(((1000000L/2)/shp->gd->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L);
+#else
+ at = times(&after) - bt;
+#endif /* timeofday */
+ tm[0] = at;
+ if(t->par.partre)
+ {
+ Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD);
+ if(np)
+ {
+ format = nv_getval(np);
+ nv_close(np);
+ }
+ if(!format)
+ format = e_timeformat;
+ }
+ else
+ format = strchr(format+1,'\n')+1;
+ tm[1] = after.tms_utime - before.tms_utime;
+ tm[1] += after.tms_cutime - before.tms_cutime;
+ tm[2] = after.tms_stime - before.tms_stime;
+ tm[2] += after.tms_cstime - before.tms_cstime;
+ if(format && *format)
+ p_time(shp,sfstderr,sh_translate(format),tm);
+ break;
+ }
+ case TFUN:
+ {
+ register Namval_t *np=0;
+ register struct slnod *slp;
+ register char *fname = ((struct functnod*)t)->functnam;
+ register char *cp = strrchr(fname,'.');
+ register Namval_t *npv=0,*mp;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->funct.functtre,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+#if SHOPT_NAMESPACE
+ if(t->tre.tretyp==TNSPACE)
+ {
+ Dt_t *root,*oldroot, *bot=0;
+ Namval_t *oldnspace = shp->namespace;
+ int offset = stktell(stkp);
+ long optindex = shp->st.optindex;
+ int flags=NV_NOASSIGN|NV_NOARRAY|NV_VARNAME;
+ if(cp)
+ errormsg(SH_DICT,ERROR_exit(1),e_ident,fname);
+ if(!shp->namespace)
+ sfputc(stkp,'.');
+ else
+ flags |= NV_NOSCOPE;
+ sfputr(stkp,fname,0);
+ np = nv_open(stkptr(stkp,offset),shp->var_tree,flags);
+ offset = stktell(stkp);
+ shp->namespace = np;
+ if(nv_istable(np))
+ root = nv_dict(np);
+ else
+ {
+ root = dtopen(&_Nvdisc,Dtoset);
+ nv_mount(np, (char*)0, root);
+ np->nvalue.cp = Empty;
+ shp->st.optindex = 1;
+ }
+ if(oldnspace && dtvnext(dtvnext(shp->var_tree)))
+ bot = dtview(shp->var_tree,0);
+ else if(dtvnext(shp->var_tree))
+ bot = dtview(shp->var_tree,0);
+ oldroot = shp->var_tree;
+ dtview(root,shp->var_base);
+ shp->var_tree = root;
+ if(bot)
+ dtview(shp->var_tree,bot);
+ sh_exec(t->for_.fortre,flags|sh_state(SH_ERREXIT));
+ if(dtvnext(shp->var_tree))
+ bot = dtview(shp->var_tree,0);
+ shp->var_tree = oldroot;
+ if(bot)
+ dtview(shp->var_tree,bot);
+ shp->namespace = oldnspace;
+ shp->st.optindex = optindex;
+ break;
+ }
+#endif /* SHOPT_NAMESPACE */
+ /* look for discipline functions */
+ error_info.line = t->funct.functline-shp->st.firstline;
+ /* Function names cannot be special builtin */
+ if(cp || shp->prefix)
+ {
+ int offset = stktell(stkp);
+ if(shp->prefix)
+ {
+ cp = shp->prefix;
+ shp->prefix = 0;
+ npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
+ shp->prefix = cp;
+ cp = fname;
+ }
+ else
+ {
+ sfwrite(stkp,fname,cp++-fname);
+ sfputc(stkp,0);
+ npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
+ }
+ offset = stktell(stkp);
+ sfprintf(stkp,"%s.%s%c",nv_name(npv),cp,0);
+ fname = stkptr(stkp,offset);
+ }
+ else if((mp=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(mp,BLT_SPC))
+ errormsg(SH_DICT,ERROR_exit(1),e_badfun,fname);
+#if SHOPT_NAMESPACE
+ if(shp->namespace && !shp->prefix && *fname!='.')
+ np = sh_fsearch(shp,fname,NV_ADD|HASH_NOSCOPE);
+ if(!np)
+#endif /* SHOPT_NAMESPACE */
+ np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
+ if(npv)
+ {
+ if(!shp->mktype)
+ cp = nv_setdisc(npv,cp,np,(Namfun_t*)npv);
+ if(!cp)
+ errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname);
+ }
+ if(np->nvalue.rp)
+ {
+ struct Ufunction *rp = np->nvalue.rp;
+ slp = (struct slnod*)np->nvenv;
+ sh_funstaks(slp->slchild,-1);
+ stakdelete(slp->slptr);
+ if(shp->funload)
+ {
+ free((void*)np->nvalue.rp);
+ np->nvalue.rp = 0;
+ }
+ if(rp->sdict)
+ {
+ Namval_t *mp, *nq;
+ shp->last_root = rp->sdict;
+ for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
+ {
+ nq = dtnext(rp->sdict,mp);
+ _nv_unset(mp,NV_RDONLY);
+ nv_delete(mp,rp->sdict,0);
+ }
+ dtclose(rp->sdict);
+ rp->sdict = 0;
+ }
+ }
+ if(!np->nvalue.rp)
+ {
+ np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
+ memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
+ }
+ if(t->funct.functstak)
+ {
+ static Dtdisc_t _Rpdisc =
+ {
+ offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction)
+ };
+ struct functnod *fp;
+ struct comnod *ac = t->funct.functargs;
+ slp = t->funct.functstak;
+ sh_funstaks(slp->slchild,1);
+ staklink(slp->slptr);
+ np->nvenv = (char*)slp;
+ nv_funtree(np) = (int*)(t->funct.functtre);
+ np->nvalue.rp->hoffset = t->funct.functloc;
+ np->nvalue.rp->lineno = t->funct.functline;
+ np->nvalue.rp->nspace = shp->namespace;
+ np->nvalue.rp->fname = 0;
+ np->nvalue.rp->argv = ac?((struct dolnod*)ac->comarg)->dolval+1:0;
+ np->nvalue.rp->argc = ac?((struct dolnod*)ac->comarg)->dolnum:0;
+ np->nvalue.rp->fdict = shp->fun_tree;
+ fp = (struct functnod*)(slp+1);
+ if(fp->functtyp==(TFUN|FAMP))
+ np->nvalue.rp->fname = fp->functnam;
+ nv_setsize(np,fp->functline);
+ nv_offattr(np,NV_FPOSIX);
+ if(shp->funload)
+ {
+ struct Ufunction *rp = np->nvalue.rp;
+ rp->np = np;
+ if(!shp->fpathdict)
+ shp->fpathdict = dtopen(&_Rpdisc,Dtobag);
+ if(shp->fpathdict)
+ dtinsert(shp->fpathdict,rp);
+ }
+ }
+ else
+ _nv_unset(np,0);
+ if(type&FPOSIX)
+ nv_onattr(np,NV_FUNCTION|NV_FPOSIX);
+ else
+ nv_onattr(np,NV_FUNCTION);
+ if(type&FPIN)
+ nv_onattr(np,NV_FTMP);
+ if(type&FOPTGET)
+ nv_onattr(np,NV_OPTGET);
+ break;
+ }
+
+ /* new test compound command */
+ case TTST:
+ {
+ register int n;
+ register char *left;
+ int negate = (type&TNEGATE)!=0;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ break;
+#endif /* SHOPT_COSHELL */
+ if(type&TTEST)
+ skipexitset++;
+ error_info.line = t->tst.tstline-shp->st.firstline;
+ echeck = 1;
+ if((type&TPAREN)==TPAREN)
+ {
+ sh_exec(t->lst.lstlef,OPTIMIZE);
+ n = !shp->exitval;
+ }
+ else
+ {
+ register int traceon=0;
+ register char *right;
+ register char *trap;
+ char *argv[6];
+ n = type>>TSHIFT;
+ left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE);
+ if(type&TBINARY)
+ right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ argv[0] = (type&TNEGATE)?((char*)e_tstbegin):"[[";
+ if(sh_isoption(SH_XTRACE))
+ {
+ traceon = sh_trace(shp,NIL(char**),0);
+ sfwrite(sfstderr,e_tstbegin,(type&TNEGATE?5:3));
+ }
+ if(type&TUNARY)
+ {
+ if(traceon)
+ sfprintf(sfstderr,"-%c %s",n,sh_fmtq(left));
+ if(trap)
+ {
+ char unop[3];
+ unop[0] = '-';
+ unop[1] = n;
+ unop[2] = 0;
+ argv[1] = unop;
+ argv[2] = left;
+ argv[3] = "]]";
+ argv[4] = 0;
+ sh_debug(shp,trap,(char*)0,(char*)0,argv, 0);
+ }
+ n = test_unop(shp,n,left);
+ }
+ else if(type&TBINARY)
+ {
+ char *op;
+ int pattern = 0;
+ if(trap || traceon)
+ op = (char*)(shtab_testops+(n&037)-1)->sh_name;
+ type >>= TSHIFT;
+ if(type==TEST_PEQ || type==TEST_PNE)
+ pattern=ARG_EXP;
+ if(trap)
+ {
+ argv[1] = left;
+ argv[2] = op;
+ argv[3] = right;
+ argv[4] = "]]";
+ argv[5] = 0;
+ sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern);
+ }
+ n = test_binop(shp,n,left,right);
+ if(traceon)
+ {
+ sfprintf(sfstderr,"%s %s ",sh_fmtq(left),op);
+ if(pattern)
+ out_pattern(sfstderr,right,-1);
+ else
+ sfputr(sfstderr,sh_fmtq(right),-1);
+ }
+ }
+ if(traceon)
+ sfwrite(sfstderr,e_tstend,4);
+ }
+ shp->exitval = ((!n)^negate);
+ if(!skipexitset)
+ exitset();
+ break;
+ }
+ }
+ if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
+ t && echeck)
+ sh_chktrap(shp);
+ /* set $_ */
+ if(mainloop && com0)
+ {
+ /* store last argument here if it fits */
+ static char lastarg[32];
+ if(sh_isstate(SH_FORKED))
+ sh_done(shp,0);
+ if(shp->lastarg!= lastarg && shp->lastarg)
+ free(shp->lastarg);
+ if(strlen(comn) < sizeof(lastarg))
+ {
+ nv_onattr(L_ARGNOD,NV_NOFREE);
+ shp->lastarg = strcpy(lastarg,comn);
+ }
+ else
+ {
+ nv_offattr(L_ARGNOD,NV_NOFREE);
+ shp->lastarg = strdup(comn);
+ }
+ }
+ if(!skipexitset)
+ exitset();
+#if SHOPT_COSHELL
+ if(!shp->inpool && !(OPTIMIZE))
+#else
+ if(!(OPTIMIZE))
+#endif /* SHOPT_COSHELL */
+ {
+ if(sav != stkptr(stkp,0))
+ stkset(stkp,sav,0);
+ else if(stktell(stkp))
+ stkseek(stkp,0);
+ }
+ if(shp->trapnote&SH_SIGSET)
+ sh_exit(SH_EXITSIG|shp->lastsig);
+ if(was_interactive)
+ sh_onstate(SH_INTERACTIVE);
+ if(was_monitor && sh_isoption(SH_MONITOR))
+ sh_onstate(SH_MONITOR);
+ if(was_errexit)
+ sh_onstate(SH_ERREXIT);
+ }
+ return(shp->exitval);
+}
+
+int sh_run(int argn, char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ register struct dolnod *dp;
+ register struct comnod *t = (struct comnod*)stakalloc(sizeof(struct comnod));
+ int savtop = staktell();
+ char *savptr = stakfreeze(0);
+ Opt_t *op, *np = optctx(0, 0);
+ Shbltin_t bltindata;
+ bltindata = shp->bltindata;
+ op = optctx(np, 0);
+ memset(t, 0, sizeof(struct comnod));
+ dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
+ dp->dolnum = argn;
+ dp->dolbot = ARG_SPARE;
+ memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*));
+ t->comarg = (struct argnod*)dp;
+ if(!strchr(argv[0],'/'))
+ t->comnamp = (void*)nv_bfsearch(argv[0],shp->fun_tree,(Namval_t**)&t->comnamq,(char**)0);
+ argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT));
+ optctx(op,np);
+ shp->bltindata = bltindata;
+ if(savptr!=stakptr(0))
+ stakset(savptr,savtop);
+ else
+ stakseek(savtop);
+ return(argn);
+}
+
+/*
+ * test for equality with second argument trimmed
+ * returns 1 if r == trim(s) otherwise 0
+ */
+
+static int trim_eq(register const char *r,register const char *s)
+{
+ register char c;
+ while(c = *s++)
+ {
+ if(c=='\\')
+ c = *s++;
+ if(c && c != *r++)
+ return(0);
+ }
+ return(*r==0);
+}
+
+/*
+ * print out the command line if set -x is on
+ */
+
+int sh_trace(Shell_t *shp,register char *argv[], register int nl)
+{
+ register char *cp;
+ register int bracket = 0;
+ int decl = (nl&2);
+ nl &= ~2;
+ if(sh_isoption(SH_XTRACE))
+ {
+ /* make this trace atomic */
+ sfset(sfstderr,SF_SHARE|SF_PUBLIC,0);
+ if(!(cp=nv_getval(sh_scoped(shp,PS4NOD))))
+ cp = "+ ";
+ else
+ {
+ sh_offoption(SH_XTRACE);
+ cp = sh_mactry(shp,cp);
+ sh_onoption(SH_XTRACE);
+ }
+ if(*cp)
+ sfputr(sfstderr,cp,-1);
+ if(argv)
+ {
+ char *argv0 = *argv;
+ nl = (nl?'\n':-1);
+ /* don't quote [ and [[ */
+ if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='['))
+ {
+ sfputr(sfstderr,cp,*++argv?' ':nl);
+ bracket = 1;
+ }
+ while(cp = *argv++)
+ {
+ if(bracket==0 || *argv || *cp!=']')
+ cp = sh_fmtq(cp);
+ if(decl && shp->prefix && cp!=argv0 && *cp!='-')
+ {
+ if(*cp=='.' && cp[1]==0)
+ cp = shp->prefix;
+ else
+ sfputr(sfstderr,shp->prefix,'.');
+ }
+ sfputr(sfstderr,cp,*argv?' ':nl);
+ }
+ sfset(sfstderr,SF_SHARE|SF_PUBLIC,1);
+ }
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ * This routine creates a subshell by calling fork() or vfork()
+ * If ((flags&COMASK)==TCOM), then vfork() is permitted
+ * If fork fails, the shell sleeps for exponentially longer periods
+ * and tries again until a limit is reached.
+ * SH_FORKLIM is the max period between forks - power of 2 usually.
+ * Currently shell tries after 2,4,8,16, and 32 seconds and then quits
+ * Failures cause the routine to error exit.
+ * Parent links to here-documents are removed by the child
+ * Traps are reset by the child
+ * The process-id of the child is returned to the parent, 0 to the child.
+ */
+
+static void timed_out(void *handle)
+{
+ NOT_USED(handle);
+ timeout = 0;
+}
+
+
+/*
+ * called by parent and child after fork by sh_fork()
+ */
+pid_t _sh_fork(Shell_t *shp,register pid_t parent,int flags,int *jobid)
+{
+ static long forkcnt = 1000L;
+ pid_t curpgid = job.curpgid;
+ pid_t postid = (flags&FAMP)?0:curpgid;
+ int sig,nochild;
+ if(parent<0)
+ {
+ sh_sigcheck(shp);
+ if((forkcnt *= 2) > 1000L*SH_FORKLIM)
+ {
+ forkcnt=1000L;
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_nofork);
+ }
+ timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*));
+ nochild = job_wait((pid_t)1);
+ if(timeout)
+ {
+ if(nochild)
+ pause();
+ else if(forkcnt>1000L)
+ forkcnt /= 2;
+ timerdel(timeout);
+ timeout = 0;
+ }
+ return(-1);
+ }
+ forkcnt = 1000L;
+ if(parent)
+ {
+ int myjob,waitall=job.waitall;
+ shp->gd->nforks++;
+ if(job.toclear)
+ job_clear();
+ job.waitall = waitall;
+#ifdef JOBS
+ /* first process defines process group */
+ if(sh_isstate(SH_MONITOR))
+ {
+ /*
+ * errno==EPERM means that an earlier processes
+ * completed. Make parent the job group id.
+ */
+ if(postid==0)
+ job.curpgid = parent;
+ if(job.jobcontrol || (flags&FAMP))
+ {
+ if(setpgid(parent,job.curpgid)<0 && errno==EPERM)
+ setpgid(parent,parent);
+ }
+ }
+#endif /* JOBS */
+ if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0)
+ job.curpgid = parent;
+ if(flags&FCOOP)
+ shp->cpid = parent;
+ if(!postid && job.curjobid && (flags&FPOU))
+ postid = job.curpgid;
+#ifdef SHOPT_BGX
+ if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
+ postid = 1;
+ myjob = job_post(shp,parent,postid);
+ if(postid==1)
+ postid = 0;
+#else
+ myjob = job_post(shp,parent,postid);
+#endif /* SHOPT_BGX */
+ if(job.waitall && (flags&FPOU))
+ {
+ if(!job.curjobid)
+ job.curjobid = myjob;
+ if(job.exitval)
+ job.exitval++;
+ }
+ if(flags&FAMP)
+ job.curpgid = curpgid;
+ if(jobid)
+ *jobid = myjob;
+ if(shp->comsub==1 && subpipe[0]>=0)
+ {
+ if(!tsetio || !subdup)
+ {
+ if(shp->topfd > restorefd)
+ sh_iorestore(shp,restorefd,sh.exitval);
+ iounpipe(shp);
+ }
+ }
+ return(parent);
+ }
+#if !_std_malloc
+ vmtrace(-1);
+#endif
+ shp->outpipepid = ((flags&FPOU)?getpid():0);
+ /* This is the child process */
+ if(shp->trapnote&SH_SIGTERM)
+ sh_exit(SH_EXITSIG|SIGTERM);
+ shp->gd->nforks=0;
+ timerdel(NIL(void*));
+#ifdef JOBS
+ if(!job.jobcontrol && !(flags&FAMP))
+ sh_offstate(SH_MONITOR);
+ if(sh_isstate(SH_MONITOR))
+ {
+ parent = getpid();
+ if(postid==0)
+ job.curpgid = parent;
+ while(setpgid(0,job.curpgid)<0 && job.curpgid!=parent)
+ job.curpgid = parent;
+# ifdef SIGTSTP
+ if(job.curpgid==parent && !(flags&FAMP))
+ tcsetpgrp(job.fd,job.curpgid);
+# endif /* SIGTSTP */
+ }
+# ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_DFL);
+ signal(SIGTTOU,SIG_DFL);
+ signal(SIGTSTP,SIG_DFL);
+ }
+# endif /* SIGTSTP */
+ job.jobcontrol = 0;
+#endif /* JOBS */
+ job.toclear = 1;
+ shp->login_sh = 0;
+ sh_offoption(SH_LOGIN_SHELL);
+ sh_onstate(SH_FORKED);
+ sh_onstate(SH_NOLOG);
+ if (shp->fn_reset)
+ shp->fn_depth = shp->fn_reset = 0;
+#if SHOPT_ACCT
+ sh_accsusp();
+#endif /* SHOPT_ACCT */
+ /* Reset remaining signals to parent */
+ /* except for those `lost' by trap */
+ if(!(flags&FSHOWME))
+ sh_sigreset(2);
+ shp->subshell = 0;
+ shp->comsub = 0;
+ shp->spid = 0;
+ if((flags&FAMP) && shp->coutpipe>1)
+ sh_close(shp->coutpipe);
+ sig = shp->savesig;
+ shp->savesig = 0;
+ if(sig>0)
+ sh_fault(sig);
+ sh_sigcheck(shp);
+ usepipe=0;
+ return(0);
+}
+
+pid_t sh_fork(Shell_t *shp,int flags, int *jobid)
+{
+ register pid_t parent;
+ register int sig;
+ if(!shp->pathlist)
+ path_get(shp,"");
+ sfsync(NIL(Sfio_t*));
+ shp->trapnote &= ~SH_SIGTERM;
+ job_fork(-1);
+ shp->savesig = -1;
+ while(_sh_fork(shp,parent=fork(),flags,jobid) < 0);
+ sh_stats(STAT_FORKS);
+ if(!shp->subshell)
+ {
+ sig = shp->savesig;
+ shp->savesig = 0;
+ if(sig>0)
+ sh_fault(sig);
+ }
+ job_fork(parent);
+ return(parent);
+}
+
+struct Tdata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ void *extra[2];
+};
+
+/*
+ * add exports from previous scope to the new scope
+ */
+static void local_exports(register Namval_t *np, void *data)
+{
+ Shell_t *shp = ((struct Tdata*)data)->sh;
+ register Namval_t *mp;
+ register char *cp;
+ if(nv_isarray(np))
+ nv_putsub(np,NIL(char*),0);
+ if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), shp->var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp))
+ nv_putval(mp, cp, 0);
+}
+
+/*
+ * This routine executes .sh.math functions from within ((...)))
+*/
+Sfdouble_t sh_mathfun(Shell_t *shp,void *fp, int nargs, Sfdouble_t *arg)
+{
+ Sfdouble_t d;
+ Namval_t node,*mp,*np, *nref[9], **nr=nref;
+ char *argv[2];
+ struct funenv funenv;
+ int i;
+ np = (Namval_t*)fp;
+ funenv.node = np;
+ funenv.nref = nref;
+ funenv.env = 0;
+ memcpy(&node,SH_VALNOD,sizeof(node));
+ SH_VALNOD->nvfun = 0;
+ SH_VALNOD->nvenv = 0;
+ SH_VALNOD->nvflag = NV_LDOUBLE|NV_NOFREE;
+ SH_VALNOD->nvalue.ldp = 0;
+ for(i=0; i < nargs; i++)
+ {
+ *nr++ = mp = nv_namptr(shp->mathnodes,i);
+ mp->nvalue.ldp = arg++;
+ }
+ *nr = 0;
+ SH_VALNOD->nvalue.ldp = &d;
+ argv[0] = np->nvname;
+ argv[1] = 0;
+ sh_funscope(1,argv,0,&funenv,0);
+ while(mp= *nr++)
+ mp->nvalue.ldp = 0;
+ SH_VALNOD->nvfun = node.nvfun;
+ SH_VALNOD->nvflag = node.nvflag;
+ SH_VALNOD->nvenv = node.nvenv;
+ SH_VALNOD->nvalue.ldp = node.nvalue.ldp;
+ return(d);
+}
+
+/*
+ * This routine is used to execute the given function <fun> in a new scope
+ * If <fun> is NULL, then arg points to a structure containing a pointer
+ * to a function that will be executed in the current environment.
+ */
+int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
+{
+ register char *trap;
+ register int nsig;
+ register Shell_t *shp = sh_getinterp();
+ struct dolnod *argsav=0,*saveargfor;
+ struct sh_scoped savst, *prevscope = shp->st.self;
+ struct argnod *envlist=0;
+ int jmpval;
+ volatile int r = 0;
+ int n;
+ char *savstak;
+ struct funenv *fp = 0;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ Namval_t *nspace = shp->namespace;
+ Dt_t *last_root = shp->last_root;
+ Shopt_t options;
+#if SHOPT_NAMESPACE
+ Namval_t *np;
+#endif /* SHOPT_NAMESPACE */
+ options = shp->options;
+ if(shp->fn_depth==0)
+ shp->glob_options = shp->options;
+ else
+ shp->options = shp->glob_options;
+#if 0
+ shp->st.lineno = error_info.line;
+#endif
+ *prevscope = shp->st;
+ sh_offoption(SH_ERREXIT);
+ shp->st.prevst = prevscope;
+ shp->st.self = &savst;
+ shp->topscope = (Shscope_t*)shp->st.self;
+ shp->st.opterror = shp->st.optchar = 0;
+ shp->st.optindex = 1;
+ shp->st.loopcnt = 0;
+ if(!fun)
+ {
+ fp = (struct funenv*)arg;
+ shp->st.real_fun = (fp->node)->nvalue.rp;
+ envlist = fp->env;
+ }
+ prevscope->save_tree = shp->var_tree;
+ n = dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0);
+#if SHOPT_NAMESPACE
+ if(n && fp && (np=(fp->node)->nvalue.rp->nspace) && np!=shp->namespace)
+ shp->namespace = np;
+#endif /* SHOPT_NAMESPACE */
+ sh_scope(shp,envlist,1);
+ if(n)
+ {
+ struct Tdata tdata;
+ memset(&tdata,0,sizeof(tdata));
+ tdata.sh = shp;
+ /* eliminate parent scope */
+ nv_scan(prevscope->save_tree, local_exports,&tdata, NV_EXPORT, NV_EXPORT|NV_NOSCOPE);
+ }
+ shp->st.save_tree = shp->var_tree;
+ if(!fun)
+ {
+ if(nv_isattr(fp->node,NV_TAGGED))
+ sh_onoption(SH_XTRACE);
+ else
+ sh_offoption(SH_XTRACE);
+ }
+ shp->st.cmdname = argv[0];
+ /* save trap table */
+ if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
+ {
+ nsig += sizeof(char*);
+ memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig);
+ }
+ sh_sigreset(0);
+ argsav = sh_argnew(shp,argv,&saveargfor);
+ sh_pushcontext(shp,buffp,SH_JMPFUN);
+ errorpush(&buffp->err,0);
+ error_info.id = argv[0];
+ shp->st.var_local = shp->var_tree;
+ if(!fun)
+ {
+ shp->st.filename = fp->node->nvalue.rp->fname;
+ shp->st.funname = nv_name(fp->node);
+ shp->last_root = nv_dict(DOTSHNOD);
+ nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
+ nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
+ }
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval == 0)
+ {
+ if(shp->fn_depth++ > MAXDEPTH)
+ {
+ shp->toomany = 1;
+ siglongjmp(*shp->jmplist,SH_JMPERRFN);
+ }
+ else if(fun)
+ r= (*fun)(arg);
+ else
+ {
+ char **arg = shp->st.real_fun->argv;
+ Namval_t *np, *nq, **nref;
+ if(nref=fp->nref)
+ {
+ shp->last_root = 0;
+ for(r=0; arg[r]; r++)
+ {
+ np = nv_search(arg[r],shp->var_tree,HASH_NOSCOPE|NV_ADD);
+ if(np && (nq=*nref++))
+ {
+ np->nvalue.nrp = newof(0,struct Namref,1,0);
+ np->nvalue.nrp->np = nq;
+ nv_onattr(np,NV_REF|NV_NOFREE);
+ }
+ }
+ }
+ sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT);
+ r = shp->exitval;
+ }
+ }
+ if(--shp->fn_depth==1 && jmpval==SH_JMPERRFN)
+ errormsg(SH_DICT,ERROR_exit(1),e_toodeep,argv[0]);
+ sh_popcontext(shp,buffp);
+ if (shp->st.self != &savst)
+ shp->var_tree = (Dt_t*)savst.save_tree;
+ sh_unscope(shp);
+ shp->namespace = nspace;
+ shp->var_tree = (Dt_t*)prevscope->save_tree;
+ if(shp->topscope != (Shscope_t*)shp->st.self)
+ sh_setscope(shp->topscope);
+ sh_argreset(shp,argsav,saveargfor);
+ trap = shp->st.trapcom[0];
+ shp->st.trapcom[0] = 0;
+ sh_sigreset(1);
+ if (shp->st.self != &savst)
+ *shp->st.self = shp->st;
+ shp->st = *prevscope;
+ shp->topscope = (Shscope_t*)prevscope;
+ nv_getval(sh_scoped(shp,IFSNOD));
+ if(nsig)
+ memcpy((char*)&shp->st.trapcom[0],savstak,nsig);
+ shp->trapnote=0;
+ if(nsig)
+ stakset(savstak,0);
+ shp->options = options;
+ shp->last_root = last_root;
+ if(jmpval == SH_JMPSUB)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(trap)
+ {
+ sh_trap(trap,0);
+ free(trap);
+ }
+ if(jmpval)
+ r=shp->exitval;
+ if(r>SH_EXITSIG && ((r&SH_EXITMASK)==SIGINT || ((r&SH_EXITMASK)==SIGQUIT)))
+ sh_fault(r&SH_EXITMASK);
+ if(jmpval > SH_JMPFUN)
+ {
+ sh_chktrap(shp);
+ siglongjmp(*shp->jmplist,jmpval);
+ }
+ return(r);
+}
+
+static void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg)
+{
+ struct funenv fun;
+ char *fname = nv_getval(SH_FUNNAMENOD);
+ struct Level *lp =(struct Level*)(SH_LEVELNOD->nvfun);
+ int level, pipepid=shp->pipepid, comsub=shp->comsub;
+ shp->comsub = 0;
+ shp->pipepid = 0;
+ sh_stats(STAT_FUNCT);
+ if(!lp->hdr.disc)
+ lp = init_level(shp,0);
+ if((struct sh_scoped*)shp->topscope != shp->st.self)
+ sh_setscope(shp->topscope);
+ level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1;
+ SH_LEVELNOD->nvalue.s = lp->maxlevel;
+ shp->st.lineno = error_info.line;
+ if(nv_isattr(np,NV_FPOSIX))
+ {
+ char *save;
+ int loopcnt = shp->st.loopcnt;
+ shp->posix_fun = np;
+ save = argv[-1];
+ argv[-1] = 0;
+ shp->st.funname = nv_name(np);
+ shp->last_root = nv_dict(DOTSHNOD);
+ nv_putval(SH_FUNNAMENOD, nv_name(np),NV_NOFREE);
+ opt_info.index = opt_info.offset = 0;
+ error_info.errors = 0;
+ shp->st.loopcnt = 0;
+ b_dot_cmd(argn+1,argv-1,&shp->bltindata);
+ shp->st.loopcnt = loopcnt;
+ argv[-1] = save;
+ }
+ else
+ {
+ fun.env = envlist;
+ fun.node = np;
+ fun.nref = 0;
+ sh_funscope(argn,argv,0,&fun,execflg);
+ }
+ if(level-- != nv_getnum(SH_LEVELNOD))
+ {
+ Shscope_t *sp = sh_getscope(0,SEEK_END);
+ sh_setscope(sp);
+ }
+ lp->maxlevel = level;
+ SH_LEVELNOD->nvalue.s = lp->maxlevel;
+ shp->last_root = nv_dict(DOTSHNOD);
+ shp->comsub = comsub;
+#if 0
+ nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
+#else
+ nv_putval(SH_FUNNAMENOD,fname,NV_NOFREE);
+#endif
+ nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
+ shp->pipepid = pipepid;
+}
+
+/*
+ * external interface to execute a function without arguments
+ * <np> is the function node
+ * If <nq> is not-null, then sh.name and sh.subscript will be set
+ */
+int sh_fun(Namval_t *np, Namval_t *nq, char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ register int offset;
+ register char *base;
+ Namval_t node;
+ struct Namref nr;
+ long mode;
+ char *prefix = shp->prefix;
+ int n=0;
+ char *av[3];
+ Fcin_t save;
+ fcsave(&save);
+ if((offset=staktell())>0)
+ base=stakfreeze(0);
+ shp->prefix = 0;
+ if(!argv)
+ {
+ argv = av+1;
+ argv[1]=0;
+ }
+ argv[0] = nv_name(np);
+ while(argv[n])
+ n++;
+ if(nq)
+ mode = set_instance(shp,nq,&node, &nr);
+ if(is_abuiltin(np))
+ {
+ int jmpval;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ Shbltin_t *bp = &shp->bltindata;
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ jmpval = sigsetjmp(buffp->buff,1);
+ if(jmpval == 0)
+ {
+ bp->bnode = np;
+ bp->ptr = nv_context(np);
+ errorpush(&buffp->err,0);
+ error_info.id = argv[0];
+ opt_info.index = opt_info.offset = 0;
+ opt_info.disc = 0;
+ shp->exitval = 0;
+ shp->exitval = ((Shbltin_f)funptr(np))(n,argv,bp);
+ }
+ sh_popcontext(shp,buffp);
+ if(jmpval>SH_JMPCMD)
+ siglongjmp(*shp->jmplist,jmpval);
+ }
+ else
+ sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT));
+ if(nq)
+ unset_instance(nq, &node, &nr, mode);
+ fcrestore(&save);
+ if(offset>0)
+ stakset(base,offset);
+ shp->prefix = prefix;
+ return(shp->exitval);
+}
+
+/*
+ * This dummy routine is called by built-ins that do recursion
+ * on the file system (chmod, chgrp, chown). It causes
+ * the shell to invoke the non-builtin version in this case
+ */
+int cmdrecurse(int argc, char* argv[], int ac, char* av[])
+{
+ NOT_USED(argc);
+ NOT_USED(argv[0]);
+ NOT_USED(ac);
+ NOT_USED(av[0]);
+ return(SH_RUNPROG);
+}
+
+/*
+ * set up pipe for cooperating process
+ */
+static void coproc_init(Shell_t *shp, int pipes[])
+{
+ int outfd;
+ if(shp->coutpipe>=0 && shp->cpid)
+ errormsg(SH_DICT,ERROR_exit(1),e_pexists);
+ shp->cpid = 0;
+ if(shp->cpipe[0]<=0 || shp->cpipe[1]<=0)
+ {
+ /* first co-process */
+ sh_pclose(shp->cpipe);
+ sh_pipe(shp->cpipe);
+ if((outfd=shp->cpipe[1]) < 10)
+ {
+ int fd=fcntl(shp->cpipe[1],F_DUPFD,10);
+ if(fd>=10)
+ {
+ shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
+ close(outfd);
+ shp->fdstatus[outfd] = IOCLOSE;
+ shp->cpipe[1] = fd;
+ }
+ }
+ if(fcntl(*shp->cpipe,F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->cpipe[0]] |= IOCLEX;
+ shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
+
+ if(fcntl(shp->cpipe[1],F_SETFD,FD_CLOEXEC) >=0)
+ shp->fdstatus[shp->cpipe[1]] |= IOCLEX;
+ }
+ shp->outpipe = shp->cpipe;
+ sh_pipe(shp->inpipe=pipes);
+ shp->coutpipe = shp->inpipe[1];
+ shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
+ if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
+}
+
+#if SHOPT_SPAWN
+
+
+#if SHOPT_AMP || !defined(_lib_fork)
+
+/*
+ * create a shell script consisting of t->fork.forktre and execute it
+ */
+static int run_subshell(Shell_t *shp,const Shnode_t *t,pid_t grp)
+{
+ static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)";
+ register int i, fd, trace = sh_isoption(SH_XTRACE);
+ int pin,pout;
+ pid_t pid;
+ char *arglist[3], *envlist[2], devfd[12], *cp;
+ Sfio_t *sp = sftmp(0);
+ envlist[0] = "_=" SH_ID;
+ envlist[1] = 0;
+ arglist[0] = error_info.id?error_info.id:shp->shname;
+ if(*arglist[0]=='-')
+ arglist[0]++;
+ arglist[1] = devfd;
+ strncpy(devfd,e_devfdNN,sizeof(devfd));
+ arglist[2] = 0;
+ sfstack(sfstdout,sp);
+ if(trace)
+ sh_offoption(SH_XTRACE);
+ sfwrite(sfstdout,"typeset -A -- ",14);
+ sh_trap(prolog,0);
+ nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
+ if(shp->st.dolc>0)
+ {
+ /* pass the positional parameters */
+ char **argv = shp->st.dolv+1;
+ sfwrite(sfstdout,"set --",6);
+ while(*argv)
+ sfprintf(sfstdout," %s",sh_fmtq(*argv++));
+ sfputc(sfstdout,'\n');
+ }
+ pin = (shp->inpipe?shp->inpipe[1]:0);
+ pout = (shp->outpipe?shp->outpipe[0]:0);
+ for(i=3; i < 10; i++)
+ {
+ if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
+ {
+ sfprintf(sfstdout,"exec %d<&%d\n",i,i);
+ fcntl(i,F_SETFD,0);
+ }
+ }
+ sfprintf(sfstdout,"LINENO=%d\n",t->fork.forkline);
+ if(trace)
+ {
+ sfwrite(sfstdout,"set -x\n",7);
+ sh_onoption(SH_XTRACE);
+ }
+ sfstack(sfstdout,NIL(Sfio_t*));
+ sh_deparse(sp,t->fork.forktre,0);
+ sfseek(sp,(Sfoff_t)0,SEEK_SET);
+ fd = sh_dup(sffileno(sp));
+ cp = devfd+8;
+ if(fd>9)
+ *cp++ = '0' + (fd/10);
+ *cp++ = '0' + fd%10;
+ *cp = 0;
+ sfclose(sp);
+ sfsync(NIL(Sfio_t*));
+ if(!shp->gd->shpath)
+ shp->gd->shpath = pathshell();
+ pid = spawnveg(shp->shpath,arglist,envlist,grp);
+ close(fd);
+ for(i=3; i < 10; i++)
+ {
+ if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
+ fcntl(i,F_SETFD,FD_CLOEXEC);
+ }
+ if(pid <=0)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]);
+ return(pid);
+}
+#endif /* !_lib_fork */
+
+static void sigreset(Shell_t *shp,int mode)
+{
+ register char *trap;
+ register int sig=shp->st.trapmax;
+ while(sig-- > 0)
+ {
+ if(sig==SIGCHLD)
+ continue;
+ if((trap=shp->st.trapcom[sig]) && *trap==0)
+ signal(sig,mode?sh_fault:SIG_IGN);
+ }
+}
+
+/*
+ * A combined fork/exec for systems with slow or non-existent fork()
+ */
+static pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag)
+{
+ static pid_t spawnpid;
+ static int savetype;
+ static int savejobid;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ int otype=0, jmpval,jobfork=0;
+ volatile int jobwasset=0, scope=0, sigwasset=0;
+ char **arge, *path;
+ volatile pid_t grp = 0;
+ Pathcomp_t *pp;
+ if(flag)
+ {
+ otype = savetype;
+ savetype=0;
+ }
+# if SHOPT_AMP || !defined(_lib_fork)
+ if(!argv)
+ {
+ register Shnode_t *tchild = t->fork.forktre;
+ int optimize=0;
+ otype = t->tre.tretyp;
+ savetype = otype;
+ spawnpid = 0;
+# ifndef _lib_fork
+ if((tchild->tre.tretyp&COMMSK)==TCOM)
+ {
+ Namval_t *np = (Namval_t*)(tchild->com.comnamp);
+ if(np)
+ {
+ path = nv_name(np);
+ if(!nv_isattr(np,BLT_ENV))
+ np=0;
+ else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0)
+ np=0;
+ }
+ else if(!tchild->com.comarg)
+ optimize=1;
+ else if(tchild->com.comtyp&COMSCAN)
+ {
+ if(tchild->com.comarg->argflag&ARG_RAW)
+ path = tchild->com.comarg->argval;
+ else
+ path = 0;
+ }
+ else
+ path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE];
+ if(!np && path && !nv_search(path,shp->fun_tree,0))
+ optimize=1;
+ }
+# endif
+ sh_pushcontext(shp,buffp,SH_JMPIO);
+ jmpval = sigsetjmp(buffp->buff,0);
+ {
+ if((otype&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ signal(SIGQUIT,SIG_IGN);
+ signal(SIGINT,SIG_IGN);
+ if(!shp->st.ioset)
+ {
+ sh_iosave(shp,0,buffp->topfd,(char*)0);
+ sh_iorenumber(shp,sh_chkopen(e_devnull),0);
+ }
+ }
+ if(otype&FPIN)
+ {
+ int fd = shp->inpipe[1];
+ sh_iosave(shp,0,buffp->topfd,(char*)0);
+ sh_iorenumber(shp,shp->inpipe[0],0);
+ if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ if(otype&FPOU)
+ {
+#if SHOPT_COSHELL
+ if(shp->outpipe[2] > 20000)
+ sh_coaccept(shp,shp->outpipe,1);
+#endif /* SHOPT_COSHELL */
+ sh_iosave(shp,1,buffp->topfd,(char*)0);
+ sh_iorenumber(shp,sh_dup(shp->outpipe[1]),1);
+ if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
+ }
+
+ if(t->fork.forkio)
+ sh_redirect(shp,t->fork.forkio,0);
+ if(optimize==0)
+ {
+#ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_DFL);
+ signal(SIGTTOU,SIG_DFL);
+ }
+#endif /* SIGTSTP */
+#ifdef JOBS
+ if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
+ {
+ if((otype&FAMP) || job.curpgid==0)
+ grp = 1;
+ else
+ grp = job.curpgid;
+ }
+#endif /* JOBS */
+ spawnpid = run_subshell(shp,t,grp);
+ }
+ else
+ {
+ sh_exec(tchild,SH_NTFORK);
+ if(jobid)
+ *jobid = savejobid;
+ }
+ }
+ sh_popcontext(shp,buffp);
+ if((otype&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ signal(SIGQUIT,sh_fault);
+ signal(SIGINT,sh_fault);
+ }
+ if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->inpipe[1]] &= ~IOCLEX;
+ if(t->fork.forkio || otype)
+ sh_iorestore(shp,buffp->topfd,jmpval);
+ if(optimize==0)
+ {
+#ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_IGN);
+ signal(SIGTTOU,SIG_IGN);
+ }
+#endif /* SIGTSTP */
+ if(spawnpid>0)
+ _sh_fork(shp,spawnpid,otype,jobid);
+ if(grp>0 && !(otype&FAMP))
+ {
+ while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
+ job.curpgid = spawnpid;
+ }
+ }
+ savetype=0;
+ if(jmpval>SH_JMPIO)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(spawnpid<0 && (otype&FCOOP))
+ {
+ sh_close(shp->coutpipe);
+ sh_close(shp->cpipe[1]);
+ shp->cpipe[1] = -1;
+ shp->coutpipe = -1;
+ }
+ shp->exitval = 0;
+ return(spawnpid);
+ }
+# endif /* !_lib_fork */
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ errorpush(&buffp->err,ERROR_SILENT);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval == 0)
+ {
+ if((otype&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ signal(SIGQUIT,SIG_IGN);
+ signal(SIGINT,SIG_IGN);
+ }
+ spawnpid = -1;
+ if(t->com.comio)
+ sh_redirect(shp,t->com.comio,0);
+ error_info.id = *argv;
+ if(t->com.comset)
+ {
+ scope++;
+ sh_scope(shp,t->com.comset,0);
+ }
+ if(!strchr(path=argv[0],'/'))
+ {
+ Namval_t *np;
+ if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
+ path = nv_getval(np);
+ else if(path_absolute(shp,path,NIL(Pathcomp_t*)))
+ {
+ path = stkptr(shp->stk,PATH_OFFSET);
+ stkfreeze(shp->stk,0);
+ }
+ else
+ {
+ pp=path_get(shp,path);
+ while(pp)
+ {
+ if(pp->len==1 && *pp->name=='.')
+ break;
+ pp = pp->next;
+ }
+ if(!pp)
+ path = 0;
+ }
+ }
+ else if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,path);
+ if(!path)
+ {
+ spawnpid = -1;
+ goto fail;
+ }
+ arge = sh_envgen();
+ shp->exitval = 0;
+#ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_DFL);
+ signal(SIGTTOU,SIG_DFL);
+ jobwasset++;
+ }
+#endif /* SIGTSTP */
+#ifdef JOBS
+ if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
+ {
+ if((otype&FAMP) || job.curpgid==0)
+ grp = 1;
+ else
+ grp = job.curpgid;
+ }
+#endif /* JOBS */
+
+ sfsync(NIL(Sfio_t*));
+ sigreset(shp,0); /* set signals to ignore */
+ sigwasset++;
+ /* find first path that has a library component */
+ for(pp=path_get(shp,argv[0]); pp && !pp->lib ; pp=pp->next);
+ job_fork(-1);
+ jobfork = 1;
+ spawnpid = path_spawn(shp,path,argv,arge,pp,(grp<<1)|1);
+ if(spawnpid < 0 && errno==ENOEXEC)
+ {
+ char *devfd;
+ int fd = open(path,O_RDONLY);
+ argv[-1] = argv[0];
+ argv[0] = path;
+ if(fd>=0)
+ {
+ struct stat statb;
+ sfprintf(shp->strbuf,"/dev/fd/%d",fd);
+ if(stat(devfd=sfstruse(shp->strbuf),&statb)>=0)
+ argv[0] = devfd;
+ }
+ if(!shp->gd->shpath)
+ shp->gd->shpath = pathshell();
+ spawnpid = path_spawn(shp,shp->gd->shpath,&argv[-1],arge,pp,(grp<<1)|1);
+ if(fd>=0)
+ close(fd);
+ argv[0] = argv[-1];
+ }
+ fail:
+ if(jobfork && spawnpid<0)
+ job_fork(0);
+ if(spawnpid < 0) switch(errno=shp->path_err)
+ {
+ case ENOENT:
+ errormsg(SH_DICT,ERROR_system(ERROR_NOENT),e_found+4);
+ default:
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
+ }
+ }
+ else
+ exitset();
+ sh_popcontext(shp,buffp);
+ if(buffp->olist)
+ free_list(buffp->olist);
+#ifdef SIGTSTP
+ if(jobwasset)
+ {
+ signal(SIGTTIN,SIG_IGN);
+ signal(SIGTTOU,SIG_IGN);
+ }
+#endif /* SIGTSTP */
+ if(sigwasset)
+ sigreset(shp,1); /* restore ignored signals */
+ if(scope)
+ {
+ sh_unscope(shp);
+ if(jmpval==SH_JMPSCRIPT)
+ nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
+ }
+ if(t->com.comio && (jmpval || spawnpid<=0))
+ sh_iorestore(shp,buffp->topfd,jmpval);
+ if(jmpval>SH_JMPCMD)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(spawnpid>0)
+ {
+ _sh_fork(shp,spawnpid,otype,jobid);
+ job_fork(spawnpid);
+#ifdef JOBS
+ if(grp==1)
+ job.curpgid = spawnpid;
+# ifdef SIGTSTP
+ if(grp>0 && !(otype&FAMP))
+ {
+ while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
+ job.curpgid = spawnpid;
+ }
+# endif /* SIGTSTP */
+#endif /* JOBS */
+ savejobid = *jobid;
+ if(otype)
+ return(0);
+ }
+ return(spawnpid);
+}
+
+# ifdef _was_lib_fork
+# define _lib_fork 1
+# endif
+# ifndef _lib_fork
+ pid_t fork(void)
+ {
+ errormsg(SH_DICT,ERROR_exit(3),e_notimp,"fork");
+ return(-1);
+ }
+# endif /* _lib_fork */
+#endif /* SHOPT_SPAWN */
diff --git a/src/cmd/ksh93/shell.3 b/src/cmd/ksh93/shell.3
new file mode 100644
index 0000000..8a27482
--- /dev/null
+++ b/src/cmd/ksh93/shell.3
@@ -0,0 +1,414 @@
+.fp 5 CW
+.TH SHELL 3 "28 Feb 2003" AST
+.SH NAME
+\fBshell\fR \- a \f5ksh\fP library interface
+.SH SYNOPSIS
+.ta .8i 1.6i 2.4i 3.2i 4.0i 4.8i 5.6i
+.SS "HEADERS/LIBRARIES"
+.nf
+.ft 5
+#include <shell.h>
+libshell.a -lshell
+.ft R
+.fi
+.SS "DATA TYPES"
+.nf
+.ft 5
+Shell_t;
+Shopt_t;
+Shscope_t;
+Shbltin_t;
+Shbltin_f;
+Shinit_f;
+Shwait_f;
+.ft R
+.fi
+.SS "FUNCTIONS"
+.nf
+.ft 5
+int sh_main(int \fIargc\fP, char *\fIargv\fP[], Sh_init \fIfn\fP);
+Shell_t *sh_init(int \fIargc\fP, char *\fIargv\fP[]);
+Shell_t *sh_getinterp(void);
+
+Namval_t *sh_addbuiltin(const char *\fIname\fP,Sh_bltin_f \fIfn\fP,void *\fIarg\fP);
+
+unsigned int sh_isoption(int \fIoption\fP);
+unsigned int sh_onoption(int \fIoption\fP);
+unsigned int sh_offoption(int \fIoption\fP);
+
+void *sh_parse(Shell_t *\fIshp\fP, Sfio_t *\fIsp\fP, int \fIflags\fP);
+int sh_trap(const char *\fIstring\fP, int \fImode\fP);
+int sh_run(int \fIargc\fP, char *\fIargv\fP[]);
+int sh_eval(Sfio_t *\fIsp\fP,int \fImode\fP);
+int sh_fun(Namval_t *\fIfunnode\fP, Namval_t *\fIvarnode\fP, char *\fIargv\fP[]);
+int sh_funscope(int \fIargc\fP,char *\fIargv\fP[],int(*\fIfn\fP)(void*),void *\fIarg\fP,int \fIflags\fP);
+Shscope_t *sh_getscope(int \fIindex\fP,int \fIwhence\fP);
+Shscope_t *sh_setscope(Shscope_t *\fIscope\fP);
+
+int (*sh_fdnotify(int(*\fIfn\fP)(int,int)))(int,int);
+char *sh_fmtq(const char *\fIstring\fP);
+void *sh_waitnotify(Shwait_f \fIfn\fP);
+void sh_delay(double \fIsec\fP);
+Sfio_t *sh_iogetiop(int \fIfd\fP, int \fImode\fP);
+int sh_sigcheck(void);
+.ft R
+.fi
+.SH DESCRIPTION
+The \fIShell\fP library is a set of functions used for
+writing extensions to \f5ksh\fP or writing commands
+that embed shell command processing.
+The include file \f5<shell.h>\fP contains the type definitions,
+function prototypes and symbolic constants defined by
+this interface. It also defines replacement definitions for
+the standard library functions
+\f5access()\fP,
+\f5close()\fP,
+\f5dup()\fP,
+\f5exit()\fP,
+\f5fcntl()\fP,
+\f5lseek()\fP,
+\f5open()\fP,
+\f5pipe()\fP,
+\f5read()\fP,
+and
+\f5write()\fP
+that must be used
+with all code
+intended to be compiled as built-in commands.
+.P
+The \f5<shell.h>\fP header includes \f5<ast.h>\fP which
+in turn includes the standard include files, \f5<stddef.h>\fP,
+\f5<stdlib.h>\fP, \f5<stdarg.h>\fP, \f5<limits.h>\fP,
+\f5<stdio.h>\fP, \f5<string.h>\fP, \f5<unistd.h>\fP,
+\f5<sys/types.h>\fP, \f5<fcntl.h>\fP, and \f5<locale.h>\fP.
+The \f5<shell.h>\fP header also includes the headers
+\f5<cdt.h>\fP,
+\f5<cmd.h>\fP,
+\f5<sfio.h>\fP,
+\f5<nval.h>\fP,
+\f5<stk.h>\fP,
+and \f5<error.h>\fP
+so that in most cases, programs only require the single
+header \f5<shell.h>\fP.
+.PP
+Programs can use this library in one of the following ways:
+.PD 0
+.TP
+.B 1
+To write builtin commands and/or other code that will be loaded
+into the shell by loading dynamic libraries
+at run time using the \f5builtin\fP(1) command.
+In this case the shell will look for a function named \f5lib_init\fP
+in your library and, if found, will execute this function with
+two arguments. The first
+argument will be an \f5int\fP with value \f50\fP when the library is loaded.
+The second argument will contain a pointer to a structure of type
+\f5Shbltin_t\fP.
+In addition, for each argument named on the \f5builtin\fP
+command line, it will look for a function named \f5b_\fP\fIname\fP\f5()\fP
+in your library and will \fIname\fP as a built-in.
+.TP
+.B 2
+To build separate a separate command that uses the shell as a
+library at compile or run time.
+In this case the \f5sh_init()\fP function must be called to
+initialize this library before any other commands in this library
+are invoked.
+The arguments \fIargc\fP and \fIargv\fP are the number
+of arguments and the vector of arguments as supplied by the shell.
+It returns a pointer the \f5Shell_t\fP.
+.TP
+.B 3
+To build a new version of \f5ksh\fP with extended capabilities,
+for example \f5tksh\fP(1).
+In this case, the user writes a \f5main()\fP function that
+calls \f5sh_main()\fP with the \fIargc\fP and \fIargv\fP arguments
+from \f5main\fP and pointer to function, \fIfn\fP as a third
+argument.. The function \fIfn\fP will
+be invoked with argument \f50\fP after \f5ksh\fP has done initialization,
+but before \f5ksh\fP has processed any start up files or executed
+any commands. The function \fIfn\fP
+will be invoked with an argument of \f51\fP before \f5ksh\fP
+begins to execute a script that has been invoked by name
+since \f5ksh\fP cleans up memory and long jumps back to
+the beginning of the shell in this case.
+The function \fIfn\fP will be called with argument \f5-1\fP before
+the shell exits.
+.PD
+.PP
+The \f5Shell_t\fP structure contains the following fields:
+.nf
+.ft 5
+ Shopt_t \fIoptions\fP; \fR/* set -o options */\fP
+ Dt_t *\fIvar_tree\fP; \fR/* shell variable dictionary */\fP
+ Dt_t *\fIfun_tree\fP; \fR/* shell function dictionary */\fP
+ Dt_t *\fIalias_tree\fP; \fR/* shell alias dictionary */\fP
+ Dt_t *\fIbltin_tree\fP; \fR/* shell built-in dictionary */\fP
+ Shscope_t *\fItopscope\fP; \fR/* pointer to top-level scope */\fP
+ char *\fIinfile_name\fP; \fR/* path name of current input file*/\fP
+ int \fIinlineno\fP; \fR/* line number of current input file*/\fP
+ int \fIexitval\fP; \fR/* most recent exit value*/\fP
+.ft R
+.fi
+This structure is returned by \f5sh_init()\fP but can also be retrieved
+by a call to \f5sh_getinterp()\fP.
+.PP
+All built-in commands to the shell are invoked with
+three arguments. The first two arguments give the
+number of arguments and the argument list
+and uses the same conventions as the \f5main()\fP function
+of a program. The third argument is a pointer to a structure
+of type \f5Shbltin_t\fP. This structure contains \f5shp\fP which is a pointer
+to the shell interpreter, and \f5ptr\fP which is a pointer that
+can be associated with each built-in.
+The \f5sh_addbuiltin()\fP function is used to add, replace or delete
+built-in commands.
+It takes the name of the built-in, \fIname\fP, a pointer
+to the function that implements the built-in, \fIfn\fP, and
+a pointer that will be passed to the function in the \f5ptr\fP field when
+it is invoked.
+If, \fIfn\fP is non-\f5NULL\fP the built-in command
+is added or replaced. Otherwise, \f5sh_addbuiltin()\fP will
+return a pointer to the built-in if it exists or \f5NULL\fP otherwise.
+If \fIarg\fP is \f5(void*)1\fP the built-in will be deleted.
+The \fIname\fP argument can be in the format of a pathname.
+It cannot be the name of any of the special built-in commands.
+If \fIname\fP contains a \f5/\fP, the built-in is the basename of
+the pathname and the built-in will only be executed
+if the given pathname is encountered when performing
+a path search.
+When adding or replacing a built-in,
+\f5sh_addbuiltin()\fP function returns a pointer to
+the name-value pair corresponding to the built-in on success and \f5NULL\fP
+if it is unable to add or replace the built-in.
+When deleting a built-in, \f5NULL\fP is returned on success or
+if not found, and the name-value pair pointer is returned if the built-in
+cannot be deleted.
+.PP
+The functions \f5sh_onoption()\fP, \f5sh_offoption()\fP, \f5sh_isoption()\fP
+are used to set, unset, and test for shell options respectively.
+The \fIoption\fP argument can be any one of the following:
+.IP
+\f5SH_ALLEXPORT\fP:
+The \f5NV_EXPORT\fP attribute is given to each variable whose
+name is an identifier when a value is assigned.
+.IP
+\f5SH_BGNICE\fP:
+Each background process is run at a lower priority.
+.IP
+\f5SH_ERREXIT\fP:
+Causes a non-interactive shell to exit when a command,
+other than a conditional command, returns non-zero.
+.IP
+\f5SH_EMACS\fP:
+The emacs editing mode.
+.IP
+\f5SH_GMACS\fP:
+Same as the emacs editing mode except for the behavior of CONTROL-T.
+.IP
+\f5SH_HISTORY\fP:
+Indicates that the history file has been created and that
+commands can be logged.
+.IP
+\f5SH_IGNOREEOF\fP:
+Do not treat end-of-file as exit.
+.IP
+\f5SH_INTERACTIVE\fP:
+.IP
+Set for interactive shells.
+Do not set or unset this option.
+\f5SH_MARKDIRS\fP:
+A \fB/\fP is added to the end of each directory generated by pathname
+expansion.
+.IP
+\f5SH_MONITOR\fP:
+Indicates that the monitor option is enabled for job control.
+.IP
+\f5SH_NOCLOBBER\fP:
+The \fB>\fP redirection will fail if the file exists. Each file
+created with \fB>\fP will have the \f5O_EXCL\fP bit set as described
+in \f5<fcntl.h>\fP
+.IP
+\f5SH_NOGLOB\fP:
+Do not perform pathname expansion.
+.IP
+\f5SH_NOLOG\fP:
+Do not save function definitions in the history file.
+.IP
+\f5SH_NOTIFY\fP:
+Cause a message to be generated as soon as each background job completes.
+.IP
+\f5SH_NOUNSET\fP:
+Cause the shell to fail with an error of an unset variable is
+referenced.
+.IP
+\f5SH_PRIVILEGED\fP:
+.IP
+\f5SH_VERBOSE\fP:
+Cause each line to be echoed as it is read by the parser.
+.IP
+\f5SH_XTRACE\fP:
+Cause each command to be displayed after all expansions, but
+before execution.
+.IP
+\f5SH_VI\fP:
+The vi edit mode.
+.IP
+\f5SH_VIRAW\fP:
+Read character at a time rather than line at a time when
+in vi edit mode.
+.IP
+.PP
+The \f5sh_trap()\fP function can be used to compile and execute
+a string or file.
+A value of \f50\fP for \fImode\fP indicates that \fIname\fP
+refers to a string. A value of \f51\fP for \fImode\fP
+indicates that \fIname\fP is an \f5Sfio_t*\fP to an open stream.
+A value of \f52\fP for \fImode\fP indicates that \fIname\fP
+points to a parse tree that has been returned by \f5sh_parse()\fP.
+The complete file associated with the string or file
+is compiled and then executed so that aliases defined
+within the string or file will not take effect until
+the next command is executed.
+.PP
+The \f5sh_run()\fP function will run the command given by
+by the argument list \fIargv\fP containing \fIargc\fP elements.
+If \fIargv\fP\f5[0]\fP does not contain a \f5/\fP, it will
+be checked to see if it is a built-in or function before
+performing a path search.
+.PP
+The \f5sh_eval()\fP function executes a string or file
+stream \fIsp\fP.
+If \fImode\fP is non-zero and the history file has
+been created, the stream defined by \fIsp\fP
+will be appended to the history file as a command.
+.PP
+The \f5sh_parse()\fP function takes a pointer to the
+shell interpreter \fIshp\fP, a pointer to a string or file stream
+\fIsp\fP, and compilation flags, and returns a pointer
+to a parse tree of the compiled stream. This pointer can
+be used in subsequent calls to \f5sh_trap()\fP.
+The compilation flags can be zero or more of the following:
+.IP
+\f5SH_NL\fP:
+Treat new-lines as \fB;\fP.
+.IP
+\f5SH_EOF\fP:
+An end of file causes syntax error. By default it will
+be treated as a new-line.
+.PP
+\f5ksh\fP executes each function defined with the \f5function\fP
+reserved word in a separate scope. The \f5Shscope_t\fP type
+provides an interface to some of the information that
+is available on each scope. The structure contains
+the following public members:
+.nf
+ \f5Sh_scope_t *par_scope;\fP
+ \f5int argc;\fP
+ \f5char **argv;\fP
+ \f5char *cmdname;\fP
+ \f5Dt_t *var_tree;\fP
+.fi
+The \f5sh_getscope()\fP function can be used to the the
+scope information associated with existing scope.
+Scopes are numbered from \f50\fP for the global scope
+up to the current scope level. The \fIwhence\fP
+argument uses the symbolic constants associated with \f5lseek()\fP
+to indicate whether the \f5Iscope\fP argument is absolute,
+relative to the current scope, or relative to the topmost scope.
+The\f5sh_setscope()\fP function can be used to make a
+a known scope the current scope. It returns a pointer to the
+old current scope.
+.PP
+The \f5sh_funscope()\fP function can be used to run a function
+in a new scope. The arguments \fIargc\fP and \fIargv\fP
+are the number of arguments and the list of arguments
+respectively. If \fIfn\fP is non-\f5NULL\fP, then
+this function is invoked with \fIargc\fP, \fIargv\fP, and \fIarg\fP
+as arguments.
+.PP
+The \f5sh_fun()\fP function can be called within a
+discipline function or built-in extension to execute a
+discipline function script.
+The argument \fIfunnode\fP is a pointer to the shell function
+or built-in to execute.
+The argument \fIvarnode\fP is a pointer to the name
+value pair that has defined this discipline.
+The array \fIargv\fP is a \f5NULL\fP terminated list of
+arguments that are passed to the function.
+.PP
+By default, \f5ksh\fP only records but does not act
+on signals when running a built-in command.
+If a built-in takes a substantial amount of time
+to execute, then it should check for interrupts
+periodically by calling \f5sh_sigcheck()\fP.
+If a signal is pending, \f5sh_sigcheck()\fP will exit
+the function you are calling and return to the point
+where the most recent built-in was invoked, or where
+\f5sh_eval()\fP or \f5sh_trap()\fP was called.
+.PP
+The \f5sh_delay()\fP function is used to cause the
+shell to sleep for a period of time defined by \fIsec\fP.
+.PP
+The \f5sh_fmtq()\fP function can be used to convert a string
+into a string that is quoted so that it can be reinput
+to the shell. The quoted string returned by \f5sh_fmtq\fP
+may be returned on the current stack, so that it
+must be saved or copied.
+.PP
+The \f5sh_fdnotify()\fP function causes the function \fIfn\fP
+to be called whenever the shell duplicates or closes a file.
+It is provided for extensions that need to keep track of
+file descriptors that could be changed by shell commands.
+The function \fIfn\fP is called with two arguments.
+The first argument is the original file descriptor. The
+second argument is the new file descriptor for duplicating
+files, and \f5SH_FDCLOSE\fP when a file has been closed.
+The previously installed \f5sh_fdnotify()\fP function pointer
+is returned.
+.PP
+The \f5sh_waitnotify()\fP function causes the function \fIfn\fP
+to be called whenever the shell is waiting for input from
+a slow device or waiting for a process to complete.
+This function can process events and run shell commands
+until there is input, the timer is reached or a signal arises.
+It is called with three arguments. The first is the file
+descriptor from which the shell trying to read or \f5\-1\fP
+if the shell is waiting for a process to complete.
+The second is a timeout in milliseconds.
+A value of \f5\-1\fP for the timeout means that
+no timeout should be set.
+The third argument is 0 for input file descriptors
+and 1 for output file descriptor.
+The function needs to return a value \f5>0\fP if there
+is input on the file descriptor, and a value \f5<0\fP
+if the timeout is reached or a signal has occurred.
+A value of \f50\fP indicates
+that the function has returned without processing and that the shell
+should wait for input or process completion.
+The previous installed \f5sh_waitnotify()\fP function pointer is returned.
+.PP
+The \f5sh_iogetiop()\fP function returns a pointer to the
+Sfio stream corresponding to file descriptor number \fIfd\fP
+and the given mode \fImode\fP. The mode can be either
+\f5SF_READ\fP or \f5SF_WRITE\fP.
+The \fIfd\fP argument can the number of an open file descriptor or
+one of the following symbolic constants:
+.IP
+\f5SH_IOCOPROCESS\fP:
+The stream corresponding to the most recent co-process.
+.IP
+\f5SH_IOHISTFILE\fP:
+The stream corresponding to the history file.
+If no stream exists corresponding to \fIfd\fP or the stream
+can not be accessed in the specified mode, \f5NULL\fP is returned.
+.SH SEE ALSO
+builtin(1)
+cdt(3)
+error(3)
+nval(3)
+sfio(3)
+stk(3)
+tksh(1)
+.SH AUTHOR
+David G. Korn (dgk@research.att.com).
diff --git a/src/cmd/ksh93/tests/alias.sh b/src/cmd/ksh93/tests/alias.sh
new file mode 100755
index 0000000..5a75fa3
--- /dev/null
+++ b/src/cmd/ksh93/tests/alias.sh
@@ -0,0 +1,102 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+alias foo='print hello'
+if [[ $(foo) != hello ]]
+then err_exit 'foo, where foo is alias for "print hello" failed'
+fi
+if [[ $(foo world) != 'hello world' ]]
+then err_exit 'foo world, where foo is alias for "print hello" failed'
+fi
+alias foo='print hello '
+alias bar=world
+if [[ $(foo bar) != 'hello world' ]]
+then err_exit 'foo bar, where foo is alias for "print hello " failed'
+fi
+if [[ $(foo \bar) != 'hello bar' ]]
+then err_exit 'foo \bar, where foo is alias for "print hello " failed'
+fi
+alias bar='foo world'
+if [[ $(bar) != 'hello world' ]]
+then err_exit 'bar, where bar is alias for "foo world" failed'
+fi
+if [[ $(alias bar) != "bar='foo world'" ]]
+then err_exit 'alias bar, where bar is alias for "foo world" failed'
+fi
+unalias foo || err_exit "unalias foo failed"
+alias foo 2> /dev/null && err_exit "alias for non-existent alias foo returns true"
+unset bar
+alias bar="print foo$bar"
+bar=bar
+if [[ $(bar) != foo ]]
+then err_exit 'alias bar, where bar is alias for "print foo$bar" failed'
+fi
+unset bar
+alias bar='print hello'
+if [[ $bar != '' ]]
+then err_exit 'alias bar cause variable bar to be set'
+fi
+alias !!=print
+if [[ $(!! hello 2>/dev/null) != hello ]]
+then err_exit 'alias for !!=print not working'
+fi
+alias foo=echo
+if [[ $(print "$(foo bar)" ) != bar ]]
+then err_exit 'alias in command substitution not working'
+fi
+( unalias foo)
+if [[ $(foo bar 2> /dev/null) != bar ]]
+then err_exit 'alias not working after unalias in subshell'
+fi
+builtin -d rm 2> /dev/null
+if whence rm > /dev/null
+then [[ ! $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not set'
+ PATH=$PATH
+ [[ $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not cleared'
+fi
+if hash -r 2>/dev/null && [[ ! $(hash) ]]
+then PATH=$tmp:/bin:/usr/bin
+ for i in foo -foo --
+ do print ':' > $tmp/$i
+ chmod +x $tmp/$i
+ hash -r -- $i 2>/dev/null || err_exit "hash -r -- $i failed"
+ [[ $(hash) == $i=$tmp/$i ]] || err_exit "hash -r -- $i failed, expected $i=$tmp/$i, got $(hash)"
+ done
+else err_exit 'hash -r failed'
+fi
+( alias :pr=print) 2> /dev/null || err_exit 'alias beginning with : fails'
+( alias p:r=print) 2> /dev/null || err_exit 'alias with : in name fails'
+
+unalias no_such_alias && err_exit 'unalias should return non-zero for unknown alias'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/append.sh b/src/cmd/ksh93/tests/append.sh
new file mode 100755
index 0000000..80a7f25
--- /dev/null
+++ b/src/cmd/ksh93/tests/append.sh
@@ -0,0 +1,86 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+{
+x=abc
+x+=def ;} 2> /dev/null
+if [[ $x != abcdef ]]
+then err_exit 'abc+def != abcdef'
+fi
+integer i=3
+{ i+=4;} 2> /dev/null
+if (( i != 7 ))
+then err_exit '3+4!=7'
+fi
+iarray=( one two three )
+{ iarray+= (four five six) ;} 2> /dev/null
+if [[ ${iarray[@]} != 'one two three four five six' ]]
+then err_exit 'index array append fails'
+fi
+unset iarray
+iarray=one
+{ iarray+= (four five six) ;} 2> /dev/null
+if [[ ${iarray[@]} != 'one four five six' ]]
+then err_exit 'index array append to scalar fails'
+fi
+typeset -A aarray
+aarray=( [1]=1 [3]=4 [xyz]=xyz )
+aarray+=( [2]=2 [3]=3 [foo]=bar )
+if [[ ${aarray[3]} != 3 ]]
+then err_exit 'associative array append fails'
+fi
+if [[ ${#aarray[@]} != 5 ]]
+then err_exit 'number of elements of associative array append fails'
+fi
+point=(x=1 y=2)
+point+=( y=3 z=4)
+if [[ ${point.y} != 3 ]]
+then err_exit 'compound append fails'
+fi
+if [[ ${point.x} != 1 ]]
+then err_exit 'compound append to compound variable unsets existing variables'
+fi
+unset foo
+foo=one
+foo+=(two)
+if [[ ${foo[@]} != 'one two' ]]
+then err_exit 'array append to non array variable fails'
+fi
+unset foo
+foo[0]=(x=3)
+foo+=(x=4)
+[[ ${foo[1].x} == 4 ]] || err_exit 'compound append to index array not working'
+[[ ${foo[0].x} == 3 ]] || err_exit 'compound append to index array unsets existing variables'
+
+unset foo
+foo=a
+foo+=''
+[[ $foo == 'a' ]] || err_exit 'appending an empty string not working'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arith.sh b/src/cmd/ksh93/tests/arith.sh
new file mode 100755
index 0000000..4d48ac2
--- /dev/null
+++ b/src/cmd/ksh93/tests/arith.sh
@@ -0,0 +1,737 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+trap '' FPE # NOTE: osf.alpha requires this (no ieee math)
+
+integer x=1 y=2 z=3
+if (( 2+2 != 4 ))
+then err_exit 2+2!=4
+fi
+if ((x+y!=z))
+then err_exit x+y!=z
+fi
+if (($x+$y!=$z))
+then err_exit $x+$y!=$z
+fi
+if (((x|y)!=z))
+then err_exit "(x|y)!=z"
+fi
+if ((y >= z))
+then err_exit "y>=z"
+fi
+if ((y+3 != z+2))
+then err_exit "y+3!=z+2"
+fi
+if ((y<<2 != 1<<3))
+then err_exit "y<<2!=1<<3"
+fi
+if ((133%10 != 3))
+then err_exit "133%10!=3"
+ if (( 2.5 != 2.5 ))
+ then err_exit 2.5!=2.5
+ fi
+fi
+d=0
+((d || 1)) || err_exit 'd=0; ((d||1))'
+if (( d++!=0))
+then err_exit "d++!=0"
+fi
+if (( --d!=0))
+then err_exit "--d!=0"
+fi
+if (( (d++,6)!=6 && d!=1))
+then err_exit '(d++,6)!=6 && d!=1'
+fi
+d=0
+if (( (1?2+1:3*4+d++)!=3 || d!=0))
+then err_exit '(1?2+1:3*4+d++) !=3'
+fi
+for ((i=0; i < 20; i++))
+do :
+done
+if (( i != 20))
+then err_exit 'for (( expr)) failed'
+fi
+for ((i=0; i < 20; i++)); do : ; done
+if (( i != 20))
+then err_exit 'for (( expr));... failed'
+fi
+for ((i=0; i < 20; i++)) do : ; done
+if (( i != 20))
+then err_exit 'for (( expr))... failed'
+fi
+if (( (i?0:1) ))
+then err_exit '(( (i?0:1) )) failed'
+fi
+if (( (1 || 1 && 0) != 1 ))
+then err_exit '( (1 || 1 && 0) != 1) failed'
+fi
+if (( (_=1)+(_x=0)-_ ))
+then err_exit '(_=1)+(_x=0)-_ failed'
+fi
+if (( (3^6) != 5))
+then err_exit '((3^6) != 5) failed'
+fi
+integer x=1
+if (( (x=-x) != -1 ))
+then err_exit '(x=-x) != -1 failed'
+fi
+i=2
+if (( 1$(($i))3 != 123 ))
+then err_exit ' 1$(($i))3 failed'
+fi
+((pi=4*atan(1.)))
+point=(
+ float x
+ float y
+)
+(( point.x = cos(pi/6), point.y = sin(pi/6) ))
+if (( point.x*point.x + point.y*point.y > 1.01 ))
+then err_exit 'cos*cos +sin*sin > 1.01'
+fi
+if (( point.x*point.x + point.y*point.y < .99 ))
+then err_exit 'cos*cos +sin*sin < .99'
+fi
+if [[ $((y=x=1.5)) != 1 ]]
+then err_exit 'typecast not working in arithmetic evaluation'
+fi
+typeset -E x=1.5
+( ((x++)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'postincrement of floating point allowed'
+fi
+( ((++x)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'preincrement of floating point allowed'
+fi
+x=1.5
+( ((x%1.1)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'floating point allowed with % operator'
+fi
+x=.125
+if [[ $(( 4 * x/2 )) != 0.25 ]]
+then err_exit '(( 4 * x/2 )) is not 0.25, with x=.125'
+fi
+if [[ $(( pow(2,3) )) != 8 ]]
+then err_exit '$(( pow(2,3) )) != 8'
+fi
+( [[ $(( pow(2,(3)) )) == 8 ]] ) 2> /dev/null
+if (( $? ))
+then err_exit '$(( pow(2,(3)) )) != 8'
+fi
+unset x
+integer x=1; integer x=1
+if [[ $x != 1 ]]
+then err_exit 'two consecutive integer x=1 not working'
+fi
+unset z
+{ z=$(typeset -RZ2 z2; (( z2 = 8 )); print $z2) ;} 2>/dev/null
+if [[ $z != "08" ]]
+then err_exit "typeset -RZ2 leading 0 decimal not working [z=$z]"
+fi
+{ z=$(typeset -RZ3 z3; (( z3 = 8 )); print $z3) ;} 2>/dev/null
+if [[ $z != "008" ]]
+then err_exit "typeset -RZ3 leading 0 decimal not working [z=$z]"
+fi
+unset z
+typeset -Z3 z=010
+(( z=z+1))
+if [[ $z != 011 ]]
+then err_exit "leading 0's in -Z not treated as decimal"
+fi
+unset x
+integer x=0
+if [[ $((x+=1)) != 1 ]] || ((x!=1))
+then err_exit "+= not working"
+ x=1
+fi
+x=1
+if [[ $((x*=5)) != 5 ]] || ((x!=5))
+then err_exit "*= not working"
+ x=5
+fi
+if [[ $((x%=4)) != 1 ]] || ((x!=1))
+then err_exit "%= not working"
+ x=1
+fi
+if [[ $((x|=6)) != 7 ]] || ((x!=7))
+then err_exit "|= not working"
+ x=7
+fi
+if [[ $((x&=5)) != 5 ]] || ((x!=5))
+then err_exit "&= not working"
+ x=5
+fi
+function newscope
+{
+ float x=1.5
+ (( x += 1 ))
+ print -r -- $x
+}
+if [[ $(newscope) != 2.5 ]]
+then err_exit "arithmetic using wrong scope"
+fi
+unset x
+integer y[3]=9 y[4]=2 i=3
+(( x = y[3] + y[4] ))
+if [[ $x != 11 ]]
+then err_exit "constant index array arithmetic failure"
+fi
+(( x = $empty y[3] + y[4] ))
+if [[ $x != 11 ]]
+then err_exit "empty constant index array arithmetic failure"
+fi
+(( x = y[i] + y[i+1] ))
+if [[ $x != 11 ]]
+then err_exit "variable subscript index array arithmetic failure"
+fi
+integer a[5]=3 a[2]=4
+(( x = y[a[5]] + y[a[2]] ))
+if [[ $x != 11 ]]
+then err_exit "nested subscript index array arithmetic failure"
+fi
+unset y
+typeset -Ai y
+y[three]=9 y[four]=2
+three=four
+four=three
+(( x = y[three] + y[four] ))
+if [[ $x != 11 ]]
+then err_exit "constant associative array arithmetic failure"
+fi
+(( x = y[$three] + y[$four] ))
+if [[ $x != 11 ]]
+then err_exit "variable subscript associative array arithmetic failure"
+fi
+$SHELL -nc '((a = 1))' 2> /dev/null || err_exit "sh -n fails with arithmetic"
+$SHELL -nc '((a.b++))' 2> /dev/null || err_exit "sh -n fails with arithmetic2"
+unset z
+float z=7.5
+if { (( z%2 != 1));} 2> /dev/null
+then err_exit '% not working on floating point'
+fi
+chr=(a ' ' '=' '\r' '\n' '\\' '\"' '$' "\\'" '[' ']' '(' ')' '<' '\xab' '\040' '`' '{' '}' '*' '\E')
+if (('a' == 97))
+then val=(97 32 61 13 10 92 34 36 39 91 93 40 41 60 171 32 96 123 125 42 27)
+else val=(129 64 126 13 21 224 127 91 125 173 189 77 93 76 171 32 121 192 208 92 39 21)
+fi
+q=0
+for ((i=0; i < ${#chr[@]}; i++))
+do if (( '${chr[i]}' != ${val[i]} ))
+ then err_exit "(( '${chr[i]}' != ${val[i]} ))"
+ fi
+ if [[ $(( '${chr[i]}' )) != ${val[i]} ]]
+ then err_exit "(( '${chr[i]}' )) != ${val[i]}"
+ fi
+ if [[ $(( L'${chr[i]}' )) != ${val[i]} ]]
+ then err_exit "(( '${chr[i]}' )) != ${val[i]}"
+ fi
+ if eval '((' "'${chr[i]}'" != ${val[i]} '))'
+ then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
+ fi
+ if eval '((' "'${chr[i]}'" != ${val[i]} ' + $q ))'
+ then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
+ fi
+done
+unset x
+typeset -ui x=4294967293
+[[ $x != 4294967293 ]] && err_exit "unsigned integers not working"
+x=32767
+x=x+1
+[[ $x != 32768 ]] && err_exit "unsigned integer addition not working"
+unset x
+float x=99999999999999999999999999
+if (( x < 1e20 ))
+then err_exit 'large integer constants not working'
+fi
+unset x y
+function foobar
+{
+ nameref x=$1
+ (( x +=1 ))
+ print $x
+}
+x=0 y=4
+if [[ $(foobar y) != 5 ]]
+then err_exit 'name references in arithmetic statements in functions broken'
+fi
+if (( 2**3 != pow(2,3) ))
+then err_exit '2**3 not working'
+fi
+if (( 2**3*2 != pow(2,3)*2 ))
+then err_exit '2**3*2 not working'
+fi
+if (( 4**3**2 != pow(4,pow(3,2)) ))
+then err_exit '4**3**2 not working'
+fi
+if (( (4**3)**2 != pow(pow(4,3),2) ))
+then err_exit '(4**3)**2 not working'
+fi
+typeset -Z3 x=11
+typeset -i x
+if (( x != 11 ))
+then err_exit '-Z3 not treated as decimal'
+fi
+unset x
+typeset -ui x=-1
+(( x >= 0 )) || err_exit 'unsigned integer not working'
+(( $x >= 0 )) || err_exit 'unsigned integer not working as $x'
+unset x
+typeset -ui42 x=50
+if [[ $x != 42#18 ]]
+then err_exit 'display of unsigned integers in non-decimal bases wrong'
+fi
+$SHELL -c 'i=0;(( ofiles[i] != -1 && (ofiles[i] < mins || mins == -1) ));exit 0' 2> /dev/null || err_exit 'lexical error with arithemtic expression'
+$SHELL -c '(( +1 == 1))' 2> /dev/null || err_exit 'unary + not working'
+typeset -E20 val=123.01234567890
+[[ $val == 123.0123456789 ]] || err_exit "rounding error val=$val"
+if [[ $(print x$((10))=foo) != x10=foo ]]
+then err_exit 'parsing error with x$((10))=foo'
+fi
+$SHELL -c 'typeset x$((10))=foo' 2> /dev/null || err_exit 'typeset x$((10)) parse error'
+unset x
+x=$(( exp(log(2.0)) ))
+(( x > 1.999 && x < 2.001 )) || err_exit 'composite functions not working'
+unset x y n
+typeset -Z8 x=0 y=0
+integer n
+for (( n=0; n < 20; n++ ))
+do let "x = $x+1"
+ (( y = $y+1 ))
+done
+(( x == n )) || err_exit 'let with zero filled fields not working'
+(( y == n )) || err_exit '((...)) with zero filled fields not working'
+typeset -RZ3 x=10
+[[ $(($x)) == 10 && $((1$x)) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros'
+unset y
+[[ $(let y=$x;print $y) == 10 && $(let y=1$x;print $y) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros with let'
+unset i ip ipx
+typeset -i hex=( 172 30 18 1)
+typeset -ui ip=0 ipx=0
+integer i
+for ((i=0; i < 4; i++))
+do (( ip = (ip<<8) | hex[i]))
+done
+for ((i=0; i < 4; i++))
+do (( ipx = ip % 256 ))
+ (( ip /= 256 ))
+ (( ipx != hex[3-i] )) && err_exit "hex digit $((3-i)) not correct"
+done
+unset x
+x=010
+(( x == 10 )) || err_exit 'leading zeros in x treated as octal arithmetic with $((x))'
+(( $x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic with $x'
+unset x
+typeset -Z x=010
+(( x == 10 )) || err_exit 'leading zeros not ignored for arithmetic'
+(( $x == 10 )) || err_exit 'leading zeros not ignored for arithmetic with $x'
+typeset -i i=x
+(( i == 10 )) || err_exit 'leading zeros not ignored for arithmetic assignment'
+(( ${x:0:1} == 0 )) || err_exit 'leading zero should not be stripped for x:a:b'
+c010=3
+(( c$x == 3 )) || err_exit 'leading zero with variable should not be stripped'
+[[ $( ($SHELL -c '((++1))' 2>&1) 2>/dev/null ) == *++1:* ]] || err_exit "((++1)) not generating error message"
+i=2
+(( "22" == 22 )) || err_exit "double quoted constants fail"
+(( "2$i" == 22 )) || err_exit "double quoted variables fail"
+(( "18+$i+2" == 22 )) || err_exit "double quoted expressions fail"
+# 04-04-28 bug fix
+unset i; typeset -i i=01-2
+(( i == -1 )) || err_exit "01-2 is not -1"
+
+cat > $tmp/script <<-\!
+tests=$*
+typeset -A blop
+function blop.get
+{
+ .sh.value=777
+}
+function mkobj
+{
+ nameref obj=$1
+ obj=()
+ [[ $tests == *1* ]] && {
+ (( obj.foo = 1 ))
+ (( obj.bar = 2 ))
+ (( obj.baz = obj.foo + obj.bar )) # ok
+ echo $obj
+ }
+ [[ $tests == *2* ]] && {
+ (( obj.faz = faz = obj.foo + obj.bar )) # ok
+ echo $obj
+ }
+ [[ $tests == *3* ]] && {
+ # case 3, 'active' variable involved, w/ intermediate variable
+ (( obj.foz = foz = ${blop[1]} )) # coredump
+ echo $obj
+ }
+ [[ $tests == *4* ]] && {
+ # case 4, 'active' variable, in two steps
+ (( foz = ${blop[1]} )) # ok
+ (( obj.foz = foz )) # ok
+ echo $obj
+ }
+ [[ $tests == *5* ]] && {
+ # case 5, 'active' variable involved, w/o intermediate variable
+ (( obj.fuz = ${blop[1]} )) # coredump
+ echo $obj
+ }
+ [[ $tests == *6* ]] && {
+ echo $(( obj.baz = obj.foo + obj.bar )) # coredump
+ }
+ [[ $tests == *7* ]] && {
+ echo $(( obj.foo + obj.bar )) # coredump
+ }
+}
+mkobj bla
+!
+chmod +x $tmp/script
+[[ $($tmp/script 1) != '( bar=2 baz=3 foo=1 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 2) != '( faz=0 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 3) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 4) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 5) != '( fuz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 6) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 7) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+unset foo
+typeset -F1 foo=123456789.19
+[[ $foo == 123456789.2 ]] || err_exit 'typeset -F1 not working correctly'
+
+# divide by zero
+
+for expr in '1/(1/2)' '8%(1/2)' '8%(1.0/2)'
+do [[ $( ( $SHELL -c "( (($expr)) ) || print ok" ) 2>/dev/null ) == ok ]] || err_exit "divide by zero not trapped: $expr"
+done
+
+for expr in '1/(1.0/2)' '1/(1/2.0)'
+do [[ $( ( $SHELL -c "( print -r -- \$(($expr)) )" ) 2>/dev/null ) == 2 ]] || err_exit "invalid value for: $expr"
+done
+[[ $((5||0)) == 1 ]] || err_exit '$((5||0))'" == $((5||0)) should be 1"
+$SHELL -c 'integer x=3 y=2; (( (y += x += 2) == 7 && x==5))' 2> /dev/null || err_exit '((y += x += 2)) not working'
+$SHELL -c 'b=0; [[ $((b?a=1:b=9)) == 9 ]]' 2> /dev/null || err_exit 'b?a=1:b=9 not working'
+unset x
+(( x = 4*atan(1.0) ))
+[[ $x == "$((x))" ]] || err_exit '$x !- $((x)) when x is pi'
+$SHELL -c "[[ ${x//./} == {14,100}(\d) ]]" 2> /dev/null || err_exit 'pi has less than 14 significant places'
+if (( Inf+1 == Inf ))
+then set \
+ Inf inf \
+ -Inf -inf \
+ Nan nan \
+ -Nan -nan \
+ 1.0/0.0 inf
+ while (( $# >= 2 ))
+ do x=$(printf "%g\n" $(($1)))
+ [[ $x == $2 ]] || err_exit "printf '%g\\n' \$(($1)) failed -- expected $2, got $x"
+ x=$(printf "%g\n" $1)
+ [[ $x == $2 ]] || err_exit "printf '%g\\n' $1 failed -- expected $2, got $x"
+ x=$(printf -- $(($1)))
+ [[ $x == $2 ]] || err_exit "print -- \$(($1)) failed -- expected $2, got $x"
+ shift 2
+ done
+ (( 1.0/0.0 == Inf )) || err_exit '1.0/0.0 != Inf'
+ [[ $(print -- $((0.0/0.0))) == ?(-)nan ]] || err_exit '0.0/0.0 != NaN'
+ (( Inf*Inf == Inf )) || err_exit 'Inf*Inf != Inf'
+ (( NaN != NaN )) || err_exit 'NaN == NaN'
+ (( -5*Inf == -Inf )) || err_exit '-5*Inf != -Inf'
+ [[ $(print -- $((sqrt(-1.0)))) == ?(-)nan ]]|| err_exit 'sqrt(-1.0) != NaN'
+ (( pow(1.0,Inf) == 1.0 )) || err_exit 'pow(1.0,Inf) != 1.0'
+ (( pow(Inf,0.0) == 1.0 )) || err_exit 'pow(Inf,0.0) != 1.0'
+ [[ $(print -- $((NaN/Inf))) == ?(-)nan ]] || err_exit 'NaN/Inf != NaN'
+ (( 4.0/Inf == 0.0 )) || err_exit '4.0/Inf != 0.0'
+else err_exit 'Inf and NaN not working'
+fi
+unset x y n r
+n=14.555
+float x=$n y
+y=$(printf "%a" x)
+r=$y
+[[ $r == $n ]] || err_exit "output of printf %a not self preserving -- expected $x, got $y"
+unset x y r
+x=-0
+y=$(printf "%g %g %g %g %g %g\n" -0. -0 $((-0)) x $x $((x)))
+r="-0 -0 -0 -0 -0 -0"
+[[ $y == "$r" ]] || err_exit "-0 vs -0.0 inconsistency -- expected '$r', got '$y'"
+$SHELL -c '(( x=));:' 2> /dev/null && err_exit '((x=)) should be an error'
+$SHELL -c '(( x+=));:' 2> /dev/null && err_exit '((x+=)) should be an error'
+$SHELL -c '(( x=+));:' 2> /dev/null && err_exit '((x=+)) should be an error'
+$SHELL -c 'x=();x.arr[0]=(z=3); ((x.arr[0].z=2))' 2> /dev/null || err_exit '(((x.arr[0].z=2)) should not be an error'
+
+float t
+typeset a b r
+v="-0.0 0.0 +0.0 -1.0 1.0 +1.0"
+for a in $v
+do for b in $v
+ do (( r = copysign(a,b) ))
+ (( t = copysign(a,b) ))
+ [[ $r == $t ]] || err_exit $(printf "float t=copysign(%3.1f,%3.1f) => %3.1f -- expected %3.1f\n" a b t r)
+ done
+done
+
+typeset -l y y_ascii
+(( y=sin(90) ))
+y_ascii=$y
+(( y == y_ascii )) || err_exit "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n" y_ascii)"
+
+( $SHELL <<- \EOF
+ p=5
+ t[p]=6
+ while (( t[p] != 0 )) ; do
+ ((
+ p+=1 ,
+ t[p]+=2 ,
+ p+=3 ,
+ t[p]+=5 ,
+ p+=1 ,
+ t[p]+=2 ,
+ p+=1 ,
+ t[p]+=1 ,
+ p-=6 ,
+ t[p]-=1
+ ))
+ :
+ done
+EOF) 2> /dev/null || err_exit 'error with comma expression'
+
+N=(89551 89557)
+i=0 j=1
+[[ $(printf "%d" N[j]-N[i]) == 6 ]] || err_exit 'printf %d N[i]-N[j] failed'
+[[ $((N[j]-N[i])) == 6 ]] || err_exit '$((N[j]-N[i])) incorrect'
+
+unset a x
+x=0
+((a[++x]++))
+(( x==1)) || err_exit '((a[++x]++)) should only increment x once'
+(( a[1]==1)) || err_exit 'a[1] not incremented'
+unset a
+x=0
+((a[x++]++))
+(( x==1)) || err_exit '((a[x++]++)) should only increment x once'
+(( a[0]==1)) || err_exit 'a[0] not incremented'
+unset a
+x=0
+((a[x+=2]+=1))
+(( x==2)) || err_exit '((a[x+=2]++)) should result in x==2'
+(( a[2]==1)) || err_exit 'a[0] not 1'
+
+unset a i
+typeset -a a
+i=1
+(( a[i]=1 ))
+(( a[0] == 0 )) || err_exit 'a[0] not 0'
+(( a[1] == 1 )) || err_exit 'a[1] not 1'
+
+unset a
+typeset -i a
+for ((i=0;i<1000;i++))
+do ((a[RANDOM%2]++))
+done
+(( (a[0]+a[1])==1000)) || err_exit '(a[0]+a[1])!=1000'
+
+(( 4.**3/10 == 6.4 )) || err_exit '4.**3/10!=6.4'
+(( (.5+3)/7 == .5 )) || err_exit '(.5+3)/7!==.5'
+
+function .sh.math.mysin x
+{
+ ((.sh.value = x - x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
+}
+
+(( abs(sin(.5)-mysin(.5)) < 1e-6 )) || err_exit 'mysin() not close to sin()'
+
+$SHELL 2> /dev/null <<- \EOF || err_exit "arithmetic functions defined and referenced in compound command not working"
+{
+ function .sh.math.mysin x
+ {
+ ((.sh.value = x-x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
+ }
+ (( abs(sin(.5)-mysin(.5)) < 1e-6 ))
+ exit 0
+}
+EOF
+
+
+
+function .sh.math.max x y z
+{
+ .sh.value=x
+ (( y > x )) && .sh.value=y
+ (( z > .sh.value )) && .sh.value=z
+}
+(( max(max(3,8,5),7,5)==8)) || err_exit 'max(max(3,8,5),7,5)!=8'
+(( max(max(3,8,5),7,9)==9)) || err_exit 'max(max(3,8,9),7,5)!=9'
+(( max(6,max(3,9,5),7)==9 )) || err_exit 'max(6,max(3,8,5),7)!=9'
+(( max(6,7, max(3,8,5))==8 )) || err_exit 'max(6,7,max(3,8,5))!=8'
+
+enum color_t=(red green blue yellow)
+color_t shirt pants=blue
+(( pants == blue )) || err_exit 'pants should be blue'
+(( shirt == red )) || err_exit 'pants should be red'
+(( shirt != green )) || err_exit 'shirt should not be green'
+(( pants != shirt )) || err_exit 'pants should be the same as shirt'
+(( pants = yellow ))
+(( pants == yellow )) || err_exit 'pants should be yellow'
+
+unset z
+integer -a z=( [1]=90 )
+function x
+{
+ nameref nz=$1
+ float x y
+ float x=$((log10(nz))) y=$((log10($nz)))
+ (( abs(x-y) < 1e-10 )) || err_exit '$nz and nz differs in arithmetic expression when nz is reference to array instance'
+}
+x z[1]
+
+unset x
+float x
+x=$( ($SHELL -c 'print -- $(( asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(.5)))))))))))))))))))))))) )) ';:) 2> /dev/null)
+(( abs(x-.5) < 1.e-10 )) || err_exit 'bug in composite function evaluation'
+
+unset x
+typeset -X x=16
+{ (( $x == 16 )) ;} 2> /dev/null || err_exit 'expansions of hexfloat not working in arithmetic expansions'
+
+unset foo
+function foobar
+{
+ (( foo = 8))
+}
+typeset -i foo
+foobar
+(( foo == 8 )) || err_exit 'arithmetic assignment binding to the wrong scope'
+
+(( tgamma(4)/12 )) || err_exit 'floating point attribute for functions not preserved'
+
+unset F
+function f
+{
+ ((F=1))
+}
+f
+[[ $F == 1 ]] || err_exit 'scoping bug with arithmetic expression'
+
+F=1
+function f
+{
+ typeset F
+ ((F=2))
+}
+[[ $F == 1 ]] || err_exit 'scoping bug2 with arithmetic expression'
+
+unset play foo x z
+typeset -A play
+x=foo
+play[$x]=(x=2)
+for ((i=0; i < 2; i++))
+do (( play[$x].y , z++ ))
+done
+(( z==2 )) || err_exit 'unset compound array variable error with for loop optimization'
+
+[[ $($SHELL 2> /dev/null -c 'print -- $(( ldexp(1, 4) ))' ) == 16 ]] || err_exit 'function ldexp not implement or not working correctly'
+
+
+$SHELL 2> /dev/null -c 'str="0x1.df768ed398ee1e01329a130627ae0000p-1";typeset -l -E x;((x=str))' || err_exit '((x=var)) fails for hexfloat with var begining with 0x1.nnn'
+
+x=(3 6 12)
+(( x[2] /= x[0]))
+(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for index array'
+
+x=([0]=3 [1]=6 [2]=12)
+(( x[2] /= x[0]))
+(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for associative array'
+
+got=$($SHELL 2> /dev/null -c 'compound -a x;compound -a x[0].y; integer -a x[0].y[0].z; (( x[0].y[0].z[2]=3 )); typeset -p x')
+exp='typeset -C -a x=((typeset -C -a y=( [0]=(typeset -a -l -i z=([2]=3);));))'
+[[ $got == "$exp" ]] || err_exit '(( x[0].y[0].z[2]=3 )) not working'
+
+unset x
+let x=010
+[[ $x == 10 ]] || err_exit 'let treating 010 as octal'
+set -o letoctal
+let x=010
+[[ $x == 8 ]] || err_exit 'let not treating 010 as octal with letoctal on'
+
+float z=0
+integer aa=2 a=1
+typeset -A A
+A[a]=(typeset -A AA)
+A[a].AA[aa]=1
+(( z= A[a].AA[aa]++ ))
+(( z == 1 )) || err_exit "z should be 1 but is $z for associative array of
+associative array arithmetic"
+[[ ${A[a].AA[aa]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for associative array of associative array arithmetic'
+unset A[a]
+
+A[a]=(typeset -a AA)
+A[a].AA[aa]=1
+(( z += A[a].AA[aa++]++ ))
+(( z == 2 )) || err_exit "z should be 2 but is $z for associative array of
+index array arithmetic"
+(( aa == 3 )) || err_exit "subscript aa should be 3 but is $aa after ++"
+[[ ${A[a].AA[aa-1]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for ssociative array of index array arithmetic'
+unset A
+
+typeset -a A
+A[a]=(typeset -A AA)
+A[a].AA[aa]=1
+(( z += A[a].AA[aa]++ ))
+(( z == 3 )) || err_exit "z should be 3 but is $z for index array of
+associative array arithmetic"
+[[ ${A[a].AA[aa]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for index array of associative array arithmetic'
+unset A[a]
+
+A[a]=(typeset -a AA)
+A[a].AA[aa]=1
+(( z += A[a++].AA[aa++]++ ))
+(( z == 4 )) || err_exit "z should be 4 but is $z for index array of
+index array arithmetic"
+[[ ${A[a-1].AA[aa-1]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for index array of index array arithmetic'
+(( aa == 4 )) || err_exit "subscript aa should be 4 but is $aa after ++"
+(( a == 2 )) || err_exit "subscript a should be 2 but is $a after ++"
+unset A
+
+unset r x
+integer x
+r=020
+(($r == 16)) || err_exit 'leading 0 not treated as octal inside ((...))'
+x=$(($r))
+(( x == 16 )) || err_exit 'leading 0 not treated as octal inside $((...))'
+x=$r
+((x == 20 )) || err_exit 'leading 0 should not be treated as octal outside ((...))'
+print -- -020 | read x
+((x == -20)) || err_exit 'numbers with leading -0 should not be treated as octal outside ((...))'
+print -- -8#20 | read x
+((x == -16)) || err_exit 'numbers with leading -8# should be treated as octal'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arrays.sh b/src/cmd/ksh93/tests/arrays.sh
new file mode 100755
index 0000000..8aec386
--- /dev/null
+++ b/src/cmd/ksh93/tests/arrays.sh
@@ -0,0 +1,588 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function fun
+{
+ integer i
+ unset xxx
+ for i in 0 1
+ do xxx[$i]=$i
+ done
+}
+
+set -A x zero one two three four 'five six'
+if [[ $x != zero ]]
+then err_exit '$x is not element 0'
+fi
+if [[ ${x[0]} != zero ]]
+then err_exit '${x[0] is not element 0'
+fi
+if (( ${#x[0]} != 4 ))
+then err_exit "length of ${x[0]} is not 4"
+fi
+if (( ${#x[@]} != 6 ))
+then err_exit 'number of elements of x is not 6'
+fi
+if [[ ${x[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+if [[ ${x[@]:2:1} != two ]]
+then err_exit ' ${x[@]:2:1} is not two'
+fi
+set -A y -- ${x[*]}
+if [[ $y != zero ]]
+then err_exit '$x is not element 0'
+fi
+if [[ ${y[0]} != zero ]]
+then err_exit '${y[0] is not element 0'
+fi
+if (( ${#y[@]} != 7 ))
+then err_exit 'number of elements of y is not 7'
+fi
+if [[ ${y[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+set +A y nine ten
+if [[ ${y[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+if [[ ${y[0]} != nine ]]
+then err_exit '${y[0] is not nine'
+fi
+unset y[4]
+if (( ${#y[@]} != 6 ))
+then err_exit 'number of elements of y is not 6'
+fi
+if (( ${#y[4]} != 0 ))
+then err_exit 'string length of unset element is not 0'
+fi
+unset foo
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of unset variable foo is not 0'
+fi
+foo=''
+if (( ${#foo[0]} != 0 ))
+then err_exit 'string length of null element is not 0'
+fi
+if (( ${#foo[@]} != 1 ))
+then err_exit 'number of elements of null variable foo is not 1'
+fi
+unset foo
+foo[0]=foo
+foo[3]=bar
+unset foo[0]
+unset foo[3]
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of left in variable foo is not 0'
+fi
+unset foo
+foo[3]=bar
+foo[0]=foo
+unset foo[3]
+unset foo[0]
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of left in variable foo again is not 0'
+fi
+fun
+if (( ${#xxx[@]} != 2 ))
+then err_exit 'number of elements of left in variable xxx is not 2'
+fi
+fun
+if (( ${#xxx[@]} != 2 ))
+then err_exit 'number of elements of left in variable xxx again is not 2'
+fi
+set -A foo -- "${x[@]}"
+if (( ${#foo[@]} != 6 ))
+then err_exit 'number of elements of foo is not 6'
+fi
+if (( ${#PWD[@]} != 1 ))
+then err_exit 'number of elements of PWD is not 1'
+fi
+unset x
+x[2]=foo x[4]=bar
+if (( ${#x[@]} != 2 ))
+then err_exit 'number of elements of x is not 2'
+fi
+s[1]=1 c[1]=foo
+if [[ ${c[s[1]]} != foo ]]
+then err_exit 'c[1]=foo s[1]=1; ${c[s[1]]} != foo'
+fi
+unset s
+typeset -Ai s
+y=* z=[
+s[$y]=1
+s[$z]=2
+if (( ${#s[@]} != 2 ))
+then err_exit 'number of elements of is not 2'
+fi
+(( s[$z] = s[$z] + ${s[$y]} ))
+if [[ ${s[$z]} != 3 ]]
+then err_exit '[[ ${s[$z]} != 3 ]]'
+fi
+if (( s[$z] != 3 ))
+then err_exit '(( s[$z] != 3 ))'
+fi
+(( s[$y] = s[$y] + ${s[$z]} ))
+if [[ ${s[$y]} != 4 ]]
+then err_exit '[[ ${s[$y]} != 4 ]]'
+fi
+if (( s[$y] != 4 ))
+then err_exit '(( s[$y] != 4 ))'
+fi
+set -A y 2 4 6
+typeset -i y
+z=${y[@]}
+typeset -R12 y
+typeset -i y
+if [[ ${y[@]} != "$z" ]]
+then err_exit 'error in array conversion from int to R12'
+fi
+if (( ${#y[@]} != 3 ))
+then err_exit 'error in count of array conversion from int to R12'
+fi
+unset abcdefg
+: ${abcdefg[1]}
+set | grep '^abcdefg$' >/dev/null && err_exit 'empty array variable in set list'
+unset x y
+x=1
+typeset -i y[$x]=4
+if [[ ${y[1]} != 4 ]]
+then err_exit 'arithmetic expressions in typeset not working'
+fi
+unset foo
+typeset foo=bar
+typeset -A foo
+if [[ ${foo[0]} != bar ]]
+then err_exit 'initial value not preserved when typecast to associative'
+fi
+unset foo
+foo=(one two)
+typeset -A foo
+foo[two]=3
+if [[ ${#foo[*]} != 3 ]]
+then err_exit 'conversion of indexed to associative array failed'
+fi
+set a b c d e f g h i j k l m
+if [[ ${#} != 13 ]]
+then err_exit '${#} not 13'
+fi
+unset xxx
+xxx=foo
+if [[ ${!xxx[@]} != 0 ]]
+then err_exit '${!xxx[@]} for scalar not 0'
+fi
+if [[ ${11} != k ]]
+then err_exit '${11} not working'
+fi
+if [[ ${@:4:1} != d ]]
+then err_exit '${@:4:1} not working'
+fi
+foovar1=abc
+foovar2=def
+if [[ ${!foovar@} != +(foovar[[:alnum:]]?([ ])) ]]
+then err_exit '${!foovar@} does not expand correctly'
+fi
+if [[ ${!foovar1} != foovar1 ]]
+then err_exit '${!foovar1} != foovar1'
+fi
+unset xxx
+: ${xxx[3]}
+if [[ ${!xxx[@]} ]]
+then err_exit '${!xxx[@]} should be null'
+fi
+integer i=0
+{
+ set -x
+ xxx[++i]=1
+ set +x
+} 2> /dev/null
+if (( i != 1))
+then err_exit 'execution trace side effects with array subscripts'
+fi
+unset list
+: $(set -A list foo bar)
+if (( ${#list[@]} != 0))
+then err_exit '$(set -A list ...) leaves side effects'
+fi
+unset list
+list= (foo bar bam)
+( set -A list one two three four)
+if [[ ${list[1]} != bar ]]
+then err_exit 'array not restored after subshell'
+fi
+XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
+xpath=( $( IFS=: ; echo $XPATH ) )
+if [[ $(print -r "${xpath[@]##*/}") != 'bin bin ucb bin . sbin sbin' ]]
+then err_exit '${xpath[@]##*/} not applied to each element'
+fi
+foo=( zero one '' three four '' six)
+integer n=-1
+if [[ ${foo[@]:n} != six ]]
+then err_exit 'array offset of -1 not working'
+fi
+if [[ ${foo[@]: -3:1} != four ]]
+then err_exit 'array offset of -3:1 not working'
+fi
+$SHELL -c 'x=(if then else fi)' 2> /dev/null || err_exit 'reserved words in x=() assignment not working'
+unset foo
+foo=one
+foo=( $foo two)
+if [[ ${#foo[@]} != 2 ]]
+then err_exit 'array getting unset before right hand side evaluation'
+fi
+foo=(143 3643 38732)
+export foo
+typeset -i foo
+if [[ $($SHELL -c 'print $foo') != 143 ]]
+then err_exit 'exporting indexed array not exporting 0-th element'
+fi
+( $SHELL -c '
+ unset foo
+ typeset -A foo=([0]=143 [1]=3643 [2]=38732)
+ export foo
+ typeset -i foo
+ [[ $($SHELL -c "print $foo") == 143 ]]'
+) 2> /dev/null ||
+ err_exit 'exporting associative array not exporting 0-th element'
+unset foo
+typeset -A foo
+foo[$((10))]=ok 2> /dev/null || err_exit 'arithmetic expression as subscript not working'
+unset foo
+typeset -A foo
+integer foo=0
+[[ $foo == 0 ]] || err_exit 'zero element of associative array not being set'
+unset foo
+typeset -A foo=( [two]=1)
+for i in one three four five
+do : ${foo[$i]}
+done
+if [[ ${!foo[@]} != two ]]
+then err_exit 'error in subscript names'
+fi
+unset x
+x=( 1 2 3)
+(x[1]=8)
+[[ ${x[1]} == 2 ]] || err_exit 'index array produce side effects in subshells'
+x=( 1 2 3)
+(
+ x+=(8)
+ [[ ${#x[@]} == 4 ]] || err_exit 'index array append in subshell error'
+)
+[[ ${#x[@]} == 3 ]] || err_exit 'index array append in subshell effects parent'
+x=( [one]=1 [two]=2 [three]=3)
+(x[two]=8)
+[[ ${x[two]} == 2 ]] || err_exit 'associative array produce side effects in subshells'
+unset x
+x=( [one]=1 [two]=2 [three]=3)
+(
+ x+=( [four]=4 )
+ [[ ${#x[@]} == 4 ]] || err_exit 'associative array append in subshell error'
+)
+[[ ${#x[@]} == 3 ]] || err_exit 'associative array append in subshell effects parent'
+unset x
+integer i
+for ((i=0; i < 40; i++))
+do x[i]=$i
+done
+[[ ${#x[@]} == 40 ]] || err_exit 'index arrays loosing values'
+[[ $( ($SHELL -c 'typeset -A var; (IFS=: ; set -A var a:b:c ;print ${var[@]});:' )2>/dev/null) == 'a b c' ]] || err_exit 'change associative to index failed'
+unset foo
+[[ $(foo=good
+for ((i=0; i < 2; i++))
+do [[ ${foo[i]} ]] && print ok
+done) == ok ]] || err_exit 'invalid optimization for subscripted variables'
+(
+x=([foo]=bar)
+set +A x bam
+) 2> /dev/null && err_exit 'set +A with associative array should be an error'
+unset bam foo
+foo=0
+typeset -A bam
+unset bam[foo]
+bam[foo]=value
+[[ $bam == value ]] && err_exit 'unset associative array element error'
+: only first element of an array can be exported
+unset bam
+print 'print ${var[0]} ${var[1]}' > $tmp/script
+chmod +x $tmp/script
+[[ $($SHELL -c "var=(foo bar);export var;$tmp/script") == foo ]] || err_exit 'export array not exporting just first element'
+
+unset foo
+set --allexport
+foo=one
+foo[1]=two
+foo[0]=three
+[[ $foo == three ]] || err_exit '--allexport not working with arrays'
+set --noallexport
+unset foo
+
+cat > $tmp/script <<- \!
+ typeset -A foo
+ print foo${foo[abc]}
+!
+[[ $($SHELL -c "typeset -A foo;$tmp/script") == foo ]] 2> /dev/null || err_exit 'empty associative arrays not being cleared correctly before scripts'
+[[ $($SHELL -c "typeset -A foo;foo[abc]=abc;$tmp/script") == foo ]] 2> /dev/null || err_exit 'associative arrays not being cleared correctly before scripts'
+unset foo
+foo=(one two)
+[[ ${foo[@]:1} == two ]] || err_exit '${foo[@]:1} == two'
+[[ ! ${foo[@]:2} ]] || err_exit '${foo[@]:2} not null'
+unset foo
+foo=one
+[[ ! ${foo[@]:1} ]] || err_exit '${foo[@]:1} not null'
+function EMPTY
+{
+ typeset i
+ typeset -n ARRAY=$1
+ for i in ${!ARRAY[@]}
+ do unset ARRAY[$i]
+ done
+}
+unset foo
+typeset -A foo
+foo[bar]=bam
+foo[x]=y
+EMPTY foo
+[[ $(typeset | grep foo$) == *associative* ]] || err_exit 'array lost associative attribute'
+[[ ! ${foo[@]} ]] || err_exit 'array not empty'
+[[ ! ${!foo[@]} ]] || err_exit 'array names not empty'
+unset foo
+foo=bar
+set -- "${foo[@]:1}"
+(( $# == 0 )) || err_exit '${foo[@]:1} should not have any values'
+unset bar
+exp=4
+: ${_foo[bar=4]}
+(( bar == 4 )) || err_exit "subscript of unset variable not evaluated -- expected '4', got '$got'"
+unset bar
+: ${_foo[bar=$exp]}
+(( bar == $exp )) || err_exit "subscript of unset variable not evaluated -- expected '$exp', got '$got'"
+unset foo bar
+foo[5]=4
+bar[4]=3
+bar[0]=foo
+foo[0]=bam
+foo[4]=5
+[[ ${!foo[2+2]} == 'foo[4]' ]] || err_exit '${!var[sub]} should be var[sub]'
+[[ ${bar[${foo[5]}]} == 3 ]] || err_exit 'array subscript cannot be an array instance'
+[[ $bar[4] == 3 ]] || err_exit '$bar[x] != ${bar[x]} inside [[ ]]'
+(( $bar[4] == 3 )) || err_exit '$bar[x] != ${bar[x]} inside (( ))'
+[[ $bar[$foo[5]] == 3 ]] || err_exit '$bar[foo[x]] != ${bar[foo[x]]} inside [[ ]]'
+(( $bar[$foo[5]] == 3 )) || err_exit '$bar[foo[x]] != ${bar[foo[x]]} inside (( ))'
+x=$bar[4]
+[[ $x == 4 ]] && err_exit '$bar[4] should not be an array in an assignment'
+x=${bar[$foo[5]]}
+(( $x == 3 )) || err_exit '${bar[$foo[sub]]} not working'
+[[ $($SHELL <<- \++EOF+++
+ typeset -i test_variable=0
+ typeset -A test_array
+ test_array[1]=100
+ read test_array[2] <<-!
+ 2
+ !
+ read test_array[3] <<-!
+ 3
+ !
+ test_array[3]=4
+ print "val=${test_array[3]}"
+++EOF+++
+) == val=4 ]] 2> /dev/null || err_exit 'after reading array[j] and assign array[j] fails'
+[[ $($SHELL <<- \+++EOF+++
+ pastebin=( typeset -a form)
+ pastebin.form+=( name="name" data="clueless" )
+ print -r -- ${pastebin.form[0].name}
++++EOF+++
+) == name ]] 2> /dev/null || err_exit 'indexed array in compound variable not working'
+unset foo bar
+: ${foo[bar=2]}
+[[ $bar == 2 ]] || err_exit 'subscript not evaluated for unset variable'
+unset foo bar
+bar=1
+typeset -a foo=([1]=ok [2]=no)
+[[ $foo[bar] == ok ]] || err_exit 'typeset -a not working for simple assignment'
+unset foo
+typeset -a foo=([1]=(x=ok) [2]=(x=no))
+[[ $(typeset | grep 'foo$') == *index* ]] || err_exit 'typeset -a not creating an indexed array'
+foo+=([5]=good)
+[[ $(typeset | grep 'foo$') == *index* ]] || err_exit 'append to indexed array not preserving array type'
+unset foo
+typeset -A foo=([1]=ok [2]=no)
+[[ $foo[bar] == ok ]] && err_exit 'typeset -A not working for simple assignment'
+unset foo
+typeset -A foo=([1]=(x=ok) [2]=(x=no))
+[[ ${foo[bar].x} == ok ]] && err_exit 'typeset -A not working for compound assignment'
+[[ $($SHELL -c 'typeset -a foo;typeset | grep "foo$"' 2> /dev/null) == *index* ]] || err_exit 'typeset fails for indexed array with no elements'
+xxxxx=(one)
+[[ $(typeset | grep xxxxx$) == *'indexed array'* ]] || err_exit 'array of one element not an indexed array'
+unset foo
+foo[1]=(x=3 y=4)
+{ [[ ${!foo[1].*} == 'foo[1].x foo[1].y' ]] ;} 2> /dev/null || err_exit '${!foo[sub].*} not expanding correctly'
+unset x
+x=( typeset -a foo=( [0]="a" [1]="b" [2]="c" ))
+[[ ${@x.foo} == 'typeset -a'* ]] || err_exit 'x.foo is not an indexed array'
+x=( typeset -A foo=( [0]="a" [1]="b" [2]="c" ))
+[[ ${@x.foo} == 'typeset -A'* ]] || err_exit 'x.foo is not an associative array'
+$SHELL -c $'x=(foo\n\tbar\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with new-lines not working'
+$SHELL -c $'x=(foo\n\tbar:\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with labels not working'
+$SHELL -c $'x=(foo\n\tdone\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with reserved words not working'
+[[ $($SHELL -c 'typeset -A A; print $(( A[foo].bar ))' 2> /dev/null) == 0 ]] || err_exit 'unset variable not evaluating to 0'
+unset a
+typeset -A a
+a[a].z=1
+a[z].z=2
+unset a[a]
+[[ ${!a[@]} == z ]] || err_exit '"unset a[a]" unsets entire array'
+unset a
+a=([x]=1 [y]=2 [z]=(foo=3 bar=4))
+eval "b=$(printf "%B\n" a)"
+eval "c=$(printf "%#B\n" a)"
+[[ ${a[*]} == "${b[*]}" ]] || err_exit 'printf %B not preserving values for arrays'
+[[ ${a[*]} == "${c[*]}" ]] || err_exit 'printf %#B not preserving values for arrays'
+unset a
+a=(zero one two three four)
+a[6]=six
+[[ ${a[-1]} == six ]] || err_exit 'a[-1] should be six'
+[[ ${a[-3]} == four ]] || err_exit 'a[-3] should be four'
+[[ ${a[-3..-1]} == 'four six' ]] || err_exit "a[-3,-1] should be 'four six'"
+
+FILTER=(typeset scope)
+FILTER[0].scope=include
+FILTER[1].scope=exclude
+[[ ${#FILTER[@]} == 2 ]] || err_exit "FILTER array should have two elements not ${#FILTER[@]}"
+
+unset x
+function x.get
+{
+ print sub=${.sh.subscript}
+}
+x[2]=
+z=$(: ${x[1]} )
+[[ $z == sub=1 ]] || err_exit 'get function not invoked for index array'
+
+unset x
+typeset -A x
+function x.get
+{
+ print sub=${.sh.subscript}
+}
+x[2]=
+z=$(: ${x[1]} )
+[[ $z == sub=1 ]] || err_exit 'get function not invoked for associative array'
+
+unset y
+i=1
+a=(11 22)
+typeset -m y=a[i]
+[[ $y == 22 ]] || err_exit 'typeset -m for index array not working'
+[[ ${a[i]} || ${a[0]} != 11 ]] && err_exit 'typeset -m for index array not deleting element'
+
+unset y
+a=([0]=11 [1]=22)
+typeset -m y=a[$i]
+[[ $y == 22 ]] || err_exit 'typeset -m for associative array not working'
+[[ ${a[$i]} || ${a[0]} != 11 ]] && err_exit 'typeset -m for associative array not deleting element'
+unset x a j
+
+typeset -a a=( [0]="aa" [1]="bb" [2]="cc" )
+typeset -m 'j=a[0]'
+typeset -m 'a[0]=a[1]'
+typeset -m 'a[1]=j'
+[[ ${a[@]} == 'bb aa cc' ]] || err_exit 'moving index array elements not working'
+unset a j
+
+typeset -A a=( [0]="aa" [1]="bb" [2]="cc" )
+typeset -m 'j=a[0]'
+typeset -m 'a[0]=a[1]'
+typeset -m 'a[1]=j'
+[[ ${a[@]} == 'bb aa cc' ]] || err_exit 'moving associative array elements not working'
+unset a j
+
+z=(a b c)
+unset x
+typeset -m x[1]=z
+[[ ${x[1][@]} == 'a b c' ]] || err_exit 'moving indexed array to index array element not working'
+
+unset x z
+z=([0]=a [1]=b [2]=c)
+typeset -m x[1]=z
+[[ ${x[1][@]} == 'a b c' ]] || err_exit 'moving associative array to index array element not working'
+
+{
+typeset -a arr=(
+ float
+)
+} 2> /dev/null
+[[ ${arr[0]} == float ]] || err_exit 'typeset -a should not expand alias for float'
+unset arr
+
+{
+typeset -r -a arr=(
+ float
+)
+} 2> /dev/null
+[[ ${arr[0]} == float ]] || err_exit 'typeset -r -a should not expand alias for float'
+{
+typeset -a arr2=(
+ typeset +r
+)
+} 2> /dev/null
+[[ ${arr2[0]} == typeset ]] || err_exit 'typeset -a should not process declarations'
+unset arr2
+
+$SHELL 2> /dev/null -c $'typeset -a arr=(\nfor)' || err_exit 'typeset -a should allow reserved words as first argument'
+
+$SHELL 2> /dev/null -c $'typeset -r -a arr=(\nfor)' || err_exit 'typeset -r -a should allow reserved words as first argument'
+
+typeset arr2[6]
+[[ ${#arr2[@]} == 0 ]] || err_exit 'declartion "typeset array[6]" should not show any elements'
+
+arr2[1]=def
+[[ ${arr2[1]} == def ]] || err_exit 'declaration "typeset array[6]" causes arrays causes wrong side effects'
+
+unset foo
+typeset foo[7]
+[[ ${#foo[@]} == 0 ]] || err_exit 'typeset foo[7] should not have one element'
+
+a=123 $SHELL 2> /dev/null -c 'integer a[5]=3 a[2]=4; unset a;x=0; ((a[++x]++));:' || err_exit 'unsetting array variable leaves side effect'
+
+unset foo
+foo=(aa bb cc)
+foo=( ${foo[@]:1} )
+[[ ${foo[@]} == 'bb cc' ]] || err_exit "indexed array assignment using parts of array for values gives wrong result of ${foo[@]}"
+
+unset foo
+foo=([xx]=aa [yy]=bb [zz]=cc)
+foo=( ${foo[yy]} ${foo[zz]} )
+[[ ${foo[@]} == 'bb cc' ]] || err_exit "associative array assignment using parts of array for values gives wrong result of ${foo[@]}"
+
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arrays2.sh b/src/cmd/ksh93/tests/arrays2.sh
new file mode 100755
index 0000000..70de3b0
--- /dev/null
+++ b/src/cmd/ksh93/tests/arrays2.sh
@@ -0,0 +1,212 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do a[i][j]=$i$j
+ done
+done
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do [[ ${a[i][j]} == "$i$j" ]] || err_exit "\${a[$i][$j]} != $i$j"
+ done
+done
+for ((i=0; i < 4; i++ ))
+do j=0;for k in ${a[i][@]}
+ do [[ $k == "$i$j" ]] || err_exit "\${a[i][@]} != $i$j"
+ (( j++ ))
+ done
+done
+unset a
+a=(
+ ( 00 01 02 03 04 )
+ ( 10 11 12 13 14 15)
+ ( 20 21 22 23 24 )
+ ( 30 31 32 33 34 )
+)
+
+function check
+{
+ nameref a=$1
+ nameref b=a[2]
+ typeset c=$1
+ integer i j
+ for ((i=0; i < 4; i++ ))
+ do for ((j=0; j < 5; j++ ))
+ do [[ ${a[$i][$j]} == "$i$j" ]] || err_exit "\${$c[$i][$j]} != $i$j"
+ done
+ done
+ (( ${#a[@]} == 4 )) || err_exit "\${#$c[@]} not 4"
+ (( ${#a[0][@]} == 5 )) || err_exit "\${#$c[0][@]} not 5"
+ (( ${#a[1][@]} == 6 )) || err_exit "\${#$c[1][@]} not 6"
+ set -s -- ${!a[@]}
+ [[ ${@} == '0 1 2 3' ]] || err_exit "\${!$c[@]} not 0 1 2 3"
+ set -s -- ${!a[0][@]}
+ [[ ${@} == '0 1 2 3 4' ]] || err_exit "\${!$c[0][@]} not 0 1 2 3 4"
+ set -s -- ${!a[1][@]}
+ [[ ${@} == '0 1 2 3 4 5' ]] || err_exit "\${!$c[1][@]} not 0 1 2 3 4 5"
+ [[ $a == 00 ]] || err_exit "\$$c is not 00"
+ [[ ${a[0]} == 00 ]] || err_exit "\${$a[0]} is not 00"
+ [[ ${a[0][0]} == 00 ]] || err_exit "${a[0][0]} is not 00"
+ [[ ${a[0][0][0]} == 00 ]] || err_exit "\${$c[0][0][0]} is not 00"
+ [[ ${a[0][0][1]} == '' ]] || err_exit "\${$c[0][0][1]} is not empty"
+ [[ ${b[3]} == 23 ]] || err_exit "${!b}[3] not = 23"
+}
+
+check a
+
+unset a
+typeset -A a
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do a[$i][j]=$i$j
+ done
+done
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do [[ ${a[$i][j]} == "$i$j" ]] || err_exit "\${a[$i][$j]} == $i$j"
+ done
+done
+a[1][5]=15
+b=(
+ [0]=( 00 01 02 03 04 )
+ [1]=( 10 11 12 13 14 15)
+ [2]=( 20 21 22 23 24 )
+ [3]=( 30 31 32 33 34 )
+)
+check b
+[[ ${a[1][@]} == "${b[1][@]}" ]] || err_exit "a[1] not equal to b[1]"
+c=(
+ [0]=( [0]=00 [1]=01 [2]=02 [3]=03 [4]=04 )
+ [1]=( [0]=10 [1]=11 [2]=12 [3]=13 [4]=14 [5]=15)
+ [2]=( [0]=20 [1]=21 [2]=22 [3]=23 [4]=24 )
+ [3]=( [0]=30 [1]=31 [2]=32 [3]=33 [4]=34 )
+)
+check c
+typeset -A d
+d[0]=( [0]=00 [1]=01 [2]=02 [3]=03 [4]=04 )
+d[1]=( [0]=10 [1]=11 [2]=12 [3]=13 [4]=14 [5]=15)
+d[2]=( [0]=20 [1]=21 [2]=22 [3]=23 [4]=24 )
+d[3]=( [0]=30 [1]=31 [2]=32 [3]=33 [4]=34 )
+check d
+unset a b c d
+[[ ${a-set} ]] || err_exit "a is set after unset"
+[[ ${b-set} ]] || err_exit "b is set after unset"
+[[ ${c-set} ]] || err_exit "c is set after unset"
+[[ ${d-set} ]] || err_exit "c is set after unset"
+
+$SHELL 2> /dev/null <<\+++ || err_exit 'input of 3 dimensional array not working'
+typeset x=(
+ ( (g G) (h H) (i I) )
+ ( (d D) (e E) (f F) )
+ ( (a A) (b B) (c C) )
+)
+[[ ${x[0][0][0]} == g ]] || err_exit '${x[0][0][0]} == G'
+[[ ${x[1][1][0]} == e ]] || err_exit '${x[1][1][0]} == e'
+[[ ${x[1][1][1]} == E ]] || err_exit '${x[2][2][1]} == C'
+[[ ${x[0][2][1]} == I ]] || err_exit '${x[0][2][1]} == I'
++++
+
+typeset -a -si x=( [0]=(1 2 3) [1]=(4 5 6) [2]=(7 8 9) )
+[[ ${x[1][1]} == 5 ]] || err_exit 'changing two dimensional indexed array to short integer failed'
+unset x
+typeset -A -si x=( [0]=(1 2 3) [1]=(4 5 6) [2]=(7 8 9) )
+[[ ${x[1][2]} == 6 ]] || err_exit 'changing two dimensional associative array to short integer failed'
+
+unset ar x y
+integer -a ar
+integer i x y
+for (( i=0 ; i < 100 ; i++ ))
+do (( ar[y][x++]=i ))
+ (( x > 9 )) && (( y++ , x=0 ))
+done
+[[ ${#ar[0][*]} == 10 ]] || err_exit "\${#ar[0][*]} is '${#ar[0][*]}', should be 10"
+[[ ${#ar[*]} == 10 ]] || err_exit "\${#ar[*]} is '${#ar[*]}', should be 10"
+[[ ${ar[5][5]} == 55 ]] || err_exit "ar[5][5] is '${ar[5][5]}', should be 55"
+
+unset ar
+integer -a ar
+x=0 y=0
+for (( i=0 ; i < 81 ; i++ ))
+do nameref ar_y=ar[$y]
+ (( ar_y[x++]=i ))
+ (( x > 8 )) && (( y++ , x=0 ))
+ typeset +n ar_y
+done
+[[ ${#ar[0][*]} == 9 ]] || err_exit "\${#ar[0][*]} is '${#ar[0][*]}', should be 9"
+[[ ${#ar[*]} == 9 ]] || err_exit "\${#ar[*]} is '${#ar[*]}', should be 9"
+[[ ${ar[4][4]} == 40 ]] || err_exit "ar[4][4] is '${ar[4][4]}', should be 40"
+
+$SHELL 2> /dev/null -c 'compound c;float -a c.ar;(( c.ar[2][3][3] = 5))' || 'multi-dimensional arrays in arithemtic expressions not working'
+
+expected='typeset -a -l -E c.ar=([2]=([3]=([3]=5) ) )'
+unset c
+float c.ar
+c.ar[2][3][3]=5
+[[ $(typeset -p c.ar) == "$expected" ]] || err_exit "c.ar[2][3][3]=5;typeset -c c.ar expands to $(typeset -p c.ar)"
+
+unset values
+float -a values=( [1][3]=90 [1][4]=89 )
+function fx
+{
+ nameref arg=$1
+ [[ ${arg[0..5]} == '90 89' ]] || err_exit '${arg[0..5]} not correct where arg is a nameref to values[1]'
+}
+fx values[1]
+
+function test_short_integer
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound -r -a tests=(
+ ( cmd='integer -s -r -a x=( 1 2 3 ) ; print "${x[2]}"' stdoutpattern='3' )
+ ( cmd='integer -s -r -A x=( [0]=1 [1]=2 [2]=3 ) ; print "${x[2]}"' stdoutpattern='3' )
+ # 2D integer arrays: the following two tests crash for both "integer -s" and "integer"
+ ( cmd='integer -r -a x=( [0]=( [0]=1 [1]=2 [2]=3 ) [1]=( [0]=4 [1]=5 [2]=6 ) [2]=( [0]=7 [1]=8 [2]=9 ) ) ; print "${x[1][1]}"' stdoutpattern='5' )
+ ( cmd='integer -s -r -a x=( [0]=( [0]=1 [1]=2 [2]=3 ) [1]=( [0]=4 [1]=5 [2]=6 ) [2]=( [0]=7 [1]=8 [2]=9 ) ) ; print "${x[1][1]}"' stdoutpattern='5' )
+ )
+ typeset testname
+ integer i
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref tst=tests[i]
+ testname="${0}/${i}"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${tst.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == ${tst.stdoutpattern} ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "${tst.stdoutpattern}"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+
+ return 0
+}
+# run tests
+test_short_integer
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/attributes.sh b/src/cmd/ksh93/tests/attributes.sh
new file mode 100755
index 0000000..9deca59
--- /dev/null
+++ b/src/cmd/ksh93/tests/attributes.sh
@@ -0,0 +1,418 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+r=readonly u=Uppercase l=Lowercase i=22 i8=10 L=abc L5=def uL5=abcdef xi=20
+x=export t=tagged H=hostname LZ5=026 RZ5=026 Z5=123 lR5=ABcdef R5=def n=l
+for option in u l i i8 L L5 LZ5 RZ5 Z5 r x H t R5 uL5 lR5 xi n
+do typeset -$option $option
+done
+(r=newval) 2> /dev/null && err_exit readonly attribute fails
+i=i+5
+if ((i != 27))
+then err_exit integer attributes fails
+fi
+if [[ $i8 != 8#12 ]]
+then err_exit integer base 8 fails
+fi
+if [[ $u != UPPERCASE ]]
+then err_exit uppercase fails
+fi
+if [[ $l != lowercase ]]
+then err_exit lowercase fails
+fi
+if [[ $n != lowercase ]]
+then err_exit reference variables fail
+fi
+if [[ t=tagged != $(typeset -t) ]]
+then err_exit tagged fails
+fi
+if [[ t != $(typeset +t) ]]
+then err_exit tagged fails
+fi
+if [[ $Z5 != 00123 ]]
+then err_exit zerofill fails
+fi
+if [[ $RZ5 != 00026 ]]
+then err_exit right zerofill fails
+fi
+L=12345
+if [[ $L != 123 ]]
+then err_exit leftjust fails
+fi
+if [[ $L5 != "def " ]]
+then err_exit leftjust fails
+fi
+if [[ $uL5 != ABCDE ]]
+then err_exit leftjust uppercase fails
+fi
+if [[ $lR5 != bcdef ]]
+then err_exit rightjust fails
+fi
+if [[ $R5 != " def" ]]
+then err_exit rightjust fails
+fi
+if [[ $($SHELL -c 'echo $x') != export ]]
+then err_exit export fails
+fi
+if [[ $($SHELL -c 'xi=xi+4;echo $xi') != 24 ]]
+then err_exit export attributes fails
+fi
+x=$(foo=abc $SHELL <<!
+ foo=bar
+ $SHELL -c 'print \$foo'
+!
+)
+if [[ $x != bar ]]
+then err_exit 'environment variables require re-export'
+fi
+(typeset + ) > /dev/null 2>&1 || err_exit 'typeset + not working'
+(typeset -L-5 buf="A" 2>/dev/null)
+if [[ $? == 0 ]]
+then err_exit 'typeset allows negative field for left/right adjust'
+fi
+a=b
+readonly $a=foo
+if [[ $b != foo ]]
+then err_exit 'readonly $a=b not working'
+fi
+if [[ $(export | grep '^PATH=') != PATH=* ]]
+then err_exit 'export not working'
+fi
+picture=(
+ bitmap=/fruit
+ size=(typeset -E x=2.5)
+)
+string="$(print $picture)"
+if [[ "${string}" != *'size=( typeset -E'* ]]
+then err_exit 'print of compound exponential variable not working'
+fi
+sz=(typeset -E y=2.2)
+string="$(print $sz)"
+if [[ "${sz}" == *'typeset -E -F'* ]]
+then err_exit 'print of exponential shows both -E and -F attributes'
+fi
+print 'typeset -i m=48/4+1;print -- $m' > $tmp/script
+chmod +x $tmp/script
+typeset -Z2 m
+if [[ $($tmp/script) != 13 ]]
+then err_exit 'attributes not cleared for script execution'
+fi
+print 'print VAR=$VAR' > $tmp/script
+typeset -L70 VAR=var
+$tmp/script > $tmp/script.1
+[[ $(< $tmp/script.1) == VAR= ]] || err_exit 'typeset -L should not be inherited'
+typeset -Z LAST=00
+unset -f foo
+function foo
+{
+ if [[ $1 ]]
+ then LAST=$1
+ else ((LAST++))
+ fi
+}
+foo 1
+if (( ${#LAST} != 2 ))
+then err_exit 'LAST!=2'
+fi
+foo
+if (( ${#LAST} != 2 ))
+then err_exit 'LAST!=2'
+fi
+[[ $(set | grep LAST) == LAST=02 ]] || err_exit "LAST not correct in set list"
+set -a
+unset foo
+foo=bar
+if [[ $(export | grep ^foo=) != 'foo=bar' ]]
+then err_exit 'all export not working'
+fi
+unset foo
+read foo <<!
+bar
+!
+if [[ $(export | grep ^foo=) != 'foo=bar' ]]
+then err_exit 'all export not working with read'
+fi
+if [[ $(typeset | grep PS2) == PS2 ]]
+then err_exit 'typeset without arguments outputs names without attributes'
+fi
+unset a z q x
+w1=hello
+w2=world
+t1="$w1 $w2"
+if (( 'a' == 97 ))
+then b1=aGVsbG8gd29ybGQ=
+ b2=aGVsbG8gd29ybGRoZWxsbyB3b3JsZA==
+else b1=iIWTk5ZAppaZk4Q=
+ b2=iIWTk5ZAppaZk4SIhZOTlkCmlpmThA==
+fi
+z=$b1
+typeset -b x=$b1
+[[ $x == "$z" ]] || print -u2 'binary variable not expanding correctly'
+[[ $(printf "%B" x) == $t1 ]] || err_exit 'typeset -b not working'
+typeset -b -Z5 a=$b1
+[[ $(printf "%B" a) == $w1 ]] || err_exit 'typeset -b -Z5 not working'
+typeset -b q=$x$x
+[[ $q == $b2 ]] || err_exit 'typeset -b not working with concatination'
+[[ $(printf "%B" q) == $t1$t1 ]] || err_exit 'typeset -b concatination not working'
+x+=$b1
+[[ $x == $b2 ]] || err_exit 'typeset -b not working with append'
+[[ $(printf "%B" x) == $t1$t1 ]] || err_exit 'typeset -b append not working'
+typeset -b -Z20 z=$b1
+(( $(printf "%B" z | wc -c) == 20 )) || err_exit 'typeset -b -Z20 not storing 20 bytes'
+{
+ typeset -b v1 v2
+ read -N11 v1
+ read -N22 v2
+} << !
+hello worldhello worldhello world
+!
+[[ $v1 == "$b1" ]] || err_exit "v1=$v1 should be $b1"
+[[ $v2 == "$x" ]] || err_exit "v1=$v2 should be $x"
+if env '!=1' >/dev/null 2>&1
+then [[ $(env '!=1' $SHELL -c 'echo ok' 2>/dev/null) == ok ]] || err_exit 'malformed environment terminates shell'
+fi
+unset var
+typeset -b var
+printf '12%Z34' | read -r -N 5 var
+[[ $var == MTIAMzQ= ]] || err_exit 'binary files with zeros not working'
+unset var
+if command typeset -usi var=0xfffff 2> /dev/null
+then (( $var == 0xffff )) || err_exit 'unsigned short integers not working'
+else err_exit 'typeset -usi cannot be used for unsigned short'
+fi
+[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:-3}' 2> /dev/null) == 3 ]] || err_exit '${foo:-3} not 3 when typeset -Z2 field undefined'
+[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:=3}' 2> /dev/null) == 03 ]] || err_exit '${foo:=-3} not 3 when typeset -Z2 foo undefined'
+unset foo bar
+unset -f fun
+function fun
+{
+ export foo=hello
+ typeset -x bar=world
+ [[ $foo == hello ]] || err_exit 'export scoping problem in function'
+}
+fun
+[[ $(export | grep foo) == 'foo=hello' ]] || err_exit 'export not working in functions'
+[[ $(export | grep bar) ]] && err_exit 'typeset -x not local'
+[[ $($SHELL -c 'typeset -r IFS=;print -r $(pwd)' 2> /dev/null) == "$(pwd)" ]] || err_exit 'readonly IFS causes command substitution to fail'
+fred[66]=88
+[[ $(typeset -pa) == *fred* ]] || err_exit 'typeset -pa not working'
+unset x y z
+typeset -LZ3 x=abcd y z=00abcd
+y=03
+[[ $y == "3 " ]] || err_exit '-LZ3 not working for value 03'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value abcd'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value 00abcd'
+unset x z
+set +a
+[[ $(typeset -p z) ]] && err_exit "typeset -p for z undefined failed"
+unset z
+x='typeset -i z=45'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -a z=(a b c)'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -C z=(
+ foo=bar
+ xxx=bam
+)'
+eval "$x"
+x=${x//$'\t'}
+x=${x//$'(\n'/'('}
+x=${x//$'\n'/';'}
+x=${x%';)'}')'
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -A z=([bar]=bam [xyz]=bar)'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+foo=abc
+x='typeset -n z=foo'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+typeset +n z
+unset foo z
+typeset -T Pt_t=(
+ float x=1 y=2
+)
+Pt_t z
+x=${z//$'\t'}
+x=${x//$'(\n'/'('}
+x=${x//$'\n'/';'}
+x=${x%';)'}')'
+[[ $(typeset -p z) == "Pt_t z=$x" ]] || err_exit "typeset -p for type failed"
+[[ $(typeset +p z) == "Pt_t z" ]] || err_exit "typeset +p for type failed"
+unset z
+function foo
+{
+ typeset -p bar
+}
+bar=xxx
+[[ $(foo) == bar=xxx ]] || err_exit 'typeset -p not working inside a function'
+unset foo
+typeset -L5 foo
+[[ $(typeset -p foo) == 'typeset -L 5 foo' ]] || err_exit 'typeset -p not working for variables with attributes but without a value'
+{ $SHELL <<- EOF
+ typeset -L3 foo=aaa
+ typeset -L6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} || err_exit 'typeset -L should not preserve old attributes'
+{ $SHELL <<- EOF
+ typeset -R3 foo=aaa
+ typeset -R6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} 2> /dev/null || err_exit 'typeset -R should not preserve old attributes'
+
+expected='YWJjZGVmZ2hpag=='
+unset foo
+typeset -b -Z10 foo
+read foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -Z10 foo
+read -N10 foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -A foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -A" foo not working'
+unset foo
+typeset -b -a foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -a" foo not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary associative array element not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary indexed array element not working'
+unset foo
+
+$SHELL 2> /dev/null -c 'export foo=(bar=3)' && err_exit 'compound variables cannot be exported'
+
+$SHELL -c 'builtin date' >/dev/null 2>&1 &&
+{
+
+# check env var changes against a builtin that uses the env var
+
+SEC=1234252800
+ETZ=EST5EDT
+EDT=03
+PTZ=PST8PDT
+PDT=00
+
+CMD="date -f%H \\#$SEC"
+
+export TZ=$ETZ
+
+set -- \
+ "$EDT $PDT $EDT" "" "TZ=$PTZ" "" \
+ "$EDT $PDT $EDT" "" "TZ=$PTZ" "TZ=$ETZ" \
+ "$EDT $PDT $EDT" "TZ=$ETZ" "TZ=$PTZ" "TZ=$ETZ" \
+ "$PDT $EDT $PDT" "TZ=$PTZ" "" "TZ=$PTZ" \
+ "$PDT $EDT $PDT" "TZ=$PTZ" "TZ=$ETZ" "TZ=$PTZ" \
+ "$EDT $PDT $EDT" "foo=bar" "TZ=$PTZ" "TZ=$ETZ" \
+
+while (( $# >= 4 ))
+do exp=$1
+ got=$(print $($SHELL -c "builtin date; $2 $CMD; $3 $CMD; $4 $CMD"))
+ [[ $got == $exp ]] || err_exit "[ '$2' '$3' '$4' ] env sequence failed -- expected '$exp', got '$got'"
+ shift 4
+done
+
+}
+
+unset v
+typeset -H v=/dev/null
+[[ $v == *nul* ]] || err_exit 'typeset -H for /dev/null not working'
+
+unset x
+(typeset +C x) 2> /dev/null && err_exit 'typeset +C should be an error'
+(typeset +A x) 2> /dev/null && err_exit 'typeset +A should be an error'
+(typeset +a x) 2> /dev/null && err_exit 'typeset +a should be an error'
+
+unset x
+{
+x=$($SHELL -c 'integer -s x=5;print -r -- $x')
+} 2> /dev/null
+[[ $x == 5 ]] || err_exit 'integer -s not working'
+
+[[ $(typeset -l) == *namespace*.sh* ]] && err_exit 'typeset -l should not contain namespace .sh'
+
+unset got
+typeset -u got
+exp=100
+((got=$exp))
+[[ $got == $exp ]] || err_exit "typeset -l fails on numeric value -- expected '$exp', got '$got'"
+
+unset s
+typeset -a -u s=( hello world chicken )
+[[ ${s[2]} == CHICKEN ]] || err_exit 'typeset -u not working with indexed arrays'
+unset s
+typeset -A -u s=( [1]=hello [0]=world [2]=chicken )
+[[ ${s[2]} == CHICKEN ]] || err_exit 'typeset -u not working with associative arrays'
+expected=$'(\n\t[0]=WORLD\n\t[1]=HELLO\n\t[2]=CHICKEN\n)'
+[[ $(print -v s) == "$expected" ]] || err_exit 'typeset -u for associative array does not display correctly'
+
+unset s
+if command typeset -M totitle s 2> /dev/null
+then [[ $(typeset +p s) == 'typeset -M totitle s' ]] || err_exit 'typeset -M totitle does not display correctly with typeset -p'
+fi
+
+{ $SHELL <<- \EOF
+ compound -a a1
+ for ((i=1 ; i < 100 ; i++ ))
+ do [[ "$( typeset + a1[$i] )" == '' ]] && a1[$i].text='hello'
+ done
+ [[ ${a1[70].text} == hello ]]
+EOF
+} 2> /dev/null
+(( $? )) && err_exit 'typeset + a[i] not working'
+
+typeset groupDB="" userDB=""
+typeset -l -L1 DBPick=""
+[[ -n "$groupDB" ]] && err_exit 'typeset -l -L1 causes unwanted side effect'
+
+HISTFILE=foo
+typeset -u PS1='hello --- '
+HISTFILE=foo
+[[ $HISTFILE == foo ]] || err_exit 'typeset -u PS1 affects HISTFILE'
+
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh
new file mode 100755
index 0000000..2941543
--- /dev/null
+++ b/src/cmd/ksh93/tests/basic.sh
@@ -0,0 +1,513 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test basic file operations like redirection, pipes, file expansion
+set -- \
+ go+r 0000 \
+ go-r 0044 \
+ ug=r 0330 \
+ go+w 0000 \
+ go-w 0022 \
+ ug=w 0550 \
+ go+x 0000 \
+ go-x 0011 \
+ ug=x 0660 \
+ go-rx 0055 \
+ uo-wx 0303 \
+ ug-rw 0660 \
+ o= 0007
+while (( $# >= 2 ))
+do umask 0
+ umask $1
+ g=$(umask)
+ [[ $g == $2 ]] || err_exit "umask 0; umask $1 failed -- expected $2, got $g"
+ shift 2
+done
+umask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed"
+if [[ $(umask -S) != u=rwx,g=rx,o=rx ]]
+then err_exit 'umask -S incorrect'
+fi
+pwd=$PWD
+[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+um=$(umask -S)
+( umask 0777; > foobar )
+rm -f foobar
+> foobar
+[[ -r foobar ]] || err_exit 'umask not being restored after subshell'
+umask "$um"
+rm -f foobar
+# optimizer bug test
+> foobar
+for i in 1 2
+do print foobar*
+ rm -f foobar
+done > out
+if [[ "$(<out)" != "foobar"$'\n'"foobar*" ]]
+then print -u2 "optimizer bug with file expansion"
+fi
+rm -f out foobar
+mkdir dir
+if [[ $(print */) != dir/ ]]
+then err_exit 'file expansion with trailing / not working'
+fi
+if [[ $(print *) != dir ]]
+then err_exit 'file expansion with single file not working'
+fi
+print hi > .foo
+if [[ $(print *) != dir ]]
+then err_exit 'file expansion leading . not working'
+fi
+date > dat1 || err_exit "date > dat1 failed"
+test -r dat1 || err_exit "dat1 is not readable"
+x=dat1
+cat <$x > dat2 || err_exit "cat < $x > dat2 failed"
+cat dat1 dat2 | cat | cat | cat > dat3 || err_exit "cat pipe failed"
+cat > dat4 <<!
+$(date)
+!
+cat dat1 dat2 | cat | cat | cat > dat5 &
+wait $!
+set -- dat*
+if (( $# != 5 ))
+then err_exit "dat* matches only $# files"
+fi
+if (command > foo\\abc) 2> /dev/null
+then set -- foo*
+ if [[ $1 != 'foo\abc' ]]
+ then err_exit 'foo* does not match foo\abc'
+ fi
+fi
+if ( : > TT* && : > TTfoo ) 2>/dev/null
+then set -- TT*
+ if (( $# < 2 ))
+ then err_exit 'TT* not expanding when file TT* exists'
+ fi
+fi
+cd ~- || err_exit "cd back failed"
+cat > $tmp/script <<- !
+ #! $SHELL
+ print -r -- \$0
+!
+chmod 755 $tmp/script
+if [[ $($tmp/script) != "$tmp/script" ]]
+then err_exit '$0 not correct for #! script'
+fi
+bar=foo
+eval foo=\$bar
+if [[ $foo != foo ]]
+then err_exit 'eval foo=\$bar not working'
+fi
+bar='foo=foo\ bar'
+eval $bar
+if [[ $foo != 'foo bar' ]]
+then err_exit 'eval foo=\$bar, with bar="foo\ bar" not working'
+fi
+cd /tmp
+cd ../../tmp || err_exit "cd ../../tmp failed"
+if [[ $PWD != /tmp ]]
+then err_exit 'cd ../../tmp is not /tmp'
+fi
+( sleep 2; cat <<!
+foobar
+!
+) | cat > $tmp/foobar &
+wait $!
+foobar=$( < $tmp/foobar)
+if [[ $foobar != foobar ]]
+then err_exit "$foobar is not foobar"
+fi
+{
+ print foo
+ /bin/echo bar
+ print bam
+} > $tmp/foobar
+if [[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
+fi
+cat > $tmp/foobar <<\!
+ print foo
+ /bin/echo bar
+ print bam
+!
+chmod +x $tmp/foobar
+if [[ $($tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "script not working"
+fi
+if [[ $($tmp/foobar | /bin/cat) != $'foo\nbar\nbam' ]]
+then err_exit "script | cat not working"
+fi
+if [[ $( $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
+fi
+rm -f $tmp/foobar
+x=$( (print foo) ; (print bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (print foo);(print bar ) failed"
+fi
+x=$( (/bin/echo foo) ; (print bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (/bin/echo);(print bar ) failed"
+fi
+x=$( (/bin/echo foo) ; (/bin/echo bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (/bin/echo);(/bin/echo bar ) failed"
+fi
+cat > $tmp/script <<\!
+if [[ -p /dev/fd/0 ]]
+then builtin cat
+ cat - > /dev/null
+ [[ -p /dev/fd/0 ]] && print ok
+else print no
+fi
+!
+chmod +x $tmp/script
+case $( (print) | $tmp/script;:) in
+ok) ;;
+no) err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;;
+*) err_exit "builtin replaces standard input pipe" ;;
+esac
+print 'print $0' > $tmp/script
+print ". $tmp/script" > $tmp/scriptx
+chmod +x $tmp/scriptx
+if [[ $($tmp/scriptx) != $tmp/scriptx ]]
+then err_exit '$0 not correct for . script'
+fi
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+print ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e
+chmod 755 a b c d e
+x=$(./a)
+if [[ $x != "hello there" ]]
+then err_exit "nested scripts failed"
+fi
+x=$( (./a) | cat)
+if [[ $x != "hello there" ]]
+then err_exit "scripts in subshells fail"
+fi
+cd ~- || err_exit "cd back failed"
+x=$( (/bin/echo foo) 2> /dev/null )
+if [[ $x != foo ]]
+then err_exit "subshell in command substitution fails"
+fi
+exec 9>& 1
+exec 1>&-
+x=$(print hello)
+if [[ $x != hello ]]
+then err_exit "command subsitution with stdout closed failed"
+fi
+exec >& 9
+cd $pwd
+x=$(cat <<\! | $SHELL
+/bin/echo | /bin/cat
+/bin/echo hello
+!
+)
+if [[ $x != $'\n'hello ]]
+then err_exit "$SHELL not working when standard input is a pipe"
+fi
+x=$( (/bin/echo hello) 2> /dev/null )
+if [[ $x != hello ]]
+then err_exit "subshell in command substitution with 1 closed fails"
+fi
+cat > $tmp/script <<- \!
+read line 2> /dev/null
+print done
+!
+if [[ $($SHELL $tmp/script <&-) != done ]]
+then err_exit "executing script with 0 closed fails"
+fi
+trap '' INT
+cat > $tmp/script <<- \!
+trap 'print bad' INT
+kill -s INT $$
+print good
+!
+chmod +x $tmp/script
+if [[ $($SHELL $tmp/script) != good ]]
+then err_exit "traps ignored by parent not ignored"
+fi
+trap - INT
+cat > $tmp/script <<- \!
+read line
+/bin/cat
+!
+if [[ $($SHELL $tmp/script <<!
+one
+two
+!
+) != two ]]
+then err_exit "standard input not positioned correctly"
+fi
+word=$(print $'foo\nbar' | { read line; /bin/cat;})
+if [[ $word != bar ]]
+then err_exit "pipe to { read line; /bin/cat;} not working"
+fi
+word=$(print $'foo\nbar' | ( read line; /bin/cat) )
+if [[ $word != bar ]]
+then err_exit "pipe to ( read line; /bin/cat) not working"
+fi
+if [[ $(print x{a,b}y) != 'xay xby' ]]
+then err_exit 'brace expansion not working'
+fi
+if [[ $(for i in foo bar
+ do ( tgz=$(print $i)
+ print $tgz)
+ done) != $'foo\nbar' ]]
+then err_exit 'for loop subshell optimizer bug'
+fi
+unset a1
+optbug()
+{
+ set -A a1 foo bar bam
+ integer i
+ for ((i=0; i < 3; i++))
+ do
+ (( ${#a1[@]} < 2 )) && return 0
+ set -- "${a1[@]}"
+ shift
+ set -A a1 -- "$@"
+ done
+ return 1
+}
+optbug || err_exit 'array size optimzation bug'
+wait # not running --pipefail which would interfere with subsequent tests
+: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect)
+sleep 20 &
+pids=$!
+if [[ $(jobs -p) != $! ]]
+then err_exit 'jobs -p not reporting a background job'
+fi
+sleep 20 &
+pids="$pids $!"
+foo()
+{
+ set -- $(jobs -p)
+ (( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected"
+}
+foo
+kill $pids
+
+[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working'
+[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored'
+[[ $($SHELL -c 'o=foobar; for x in foo bar; do (o=save);print $o;done' 2> /dev/null ) == $'foobar\nfoobar' ]] || err_exit 'for loop optimization subshell bug'
+command exec 3<> /dev/null
+if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
+then [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working'
+ [[ $($SHELL -c $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
+ line0
+ line1
+ line2
+ !!!
+ wait
+ cat '$tmp/scriptx 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails'
+ > $tmp/scriptx
+ [[ $($SHELL -c $'
+ for i in 1
+ do tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
+ line0
+ line1
+ line2
+ !!!
+ done
+ wait
+ cat '$tmp/scriptx 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop'
+ [[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] ||
+ err_exit 'process substitution of compound commands not working'
+fi
+[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted'
+print cat > $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($SHELL -c "print foo | $tmp/scriptx ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails'
+[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure'
+[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure'
+if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
+then [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop"
+ $SHELL -c '[[ $(for i in 1;do cat <(print hello);done ) == hello ]]' 2> /dev/null|| err_exit "process substitution not working in for or while loop"
+fi
+exec 3> /dev/null
+print 'print foo "$@"' > $tmp/scriptx
+[[ $( print "($tmp/scriptx bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails'
+print "#! $SHELL" > $tmp/scriptx
+print 'print -- $0' >> $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($tmp/scriptx) == $tmp/scriptx ]] || err_exit "\$0 is $0 instead of $tmp/scriptx"
+cat > $tmp/scriptx <<- \EOF
+ myfilter() { x=$(print ok | cat); print -r -- $SECONDS;}
+ set -o pipefail
+ sleep 3 | myfilter
+EOF
+(( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
+exec 3<&-
+( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset'
+$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported'
+$SHELL 2> /dev/null <<- \EOF || err_exit 'multiline ${...} command substitution not supported'
+ x=${
+ print hello
+ }
+ [[ $x == hello ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit '${...} command substitution with side effects not supported '
+ y=bye
+ x=${
+ y=hello
+ print hello
+ }
+ [[ $y == $x ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported'
+ x=${
+ print ${ print hello;} $(print world)
+ }
+ [[ $x == 'hello world' ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }'
+ x=${ { print -n } ; print -n hello ; } ; print ' world' }
+ [[ $x == '}hello world' ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working'
+ f()
+ {
+ print foo
+ }
+ [[ ${ f;}bar == foobar ]]
+EOF
+
+unset foo
+[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
+[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
+[[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]'
+[[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]'
+unset foo
+foo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false'
+expected=foreback
+got=$(print -n fore; (sleep 2;print back)&)
+[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"
+
+binfalse=$(whence -p false)
+for false in false $binfalse
+do x=$($false) && err_exit "x=\$($false) should fail"
+ $($false) && err_exit "\$($false) should fail"
+ $($false) > /dev/null && err_exit "\$($false) > /dev/null should fail"
+done
+if env x-a=y >/dev/null 2>&1
+then [[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
+fi
+float s=SECONDS
+sleep=$(whence -p sleep)
+for i in 1 2
+do print $i
+done | while read sec; do ( $sleep $sec; $sleep $sec) done
+(( (SECONDS-s) < 4)) && err_exit '"command | while read...done" finishing too fast'
+s=SECONDS
+set -o pipefail
+for ((i=0; i < 30; i++))
+do print hello
+ sleep .1
+done | $sleep 1
+(( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe'
+[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered'
+var=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!)
+[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered'
+
+exp=
+got=$(
+ function fun
+ {
+ $binfalse && echo FAILED
+ }
+ : works if this line deleted : |
+ fun
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'"
+got=$(
+ : works if this line deleted : |
+ { $binfalse && echo FAILED; }
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'"
+
+got=$(
+ : works if this line deleted : |
+ ( $binfalse && echo FAILED )
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'"
+
+( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null || err_exit 'trap DEBUG fails'
+
+bintrue=$(whence -p true)
+set -o pipefail
+float start=$SECONDS end
+for ((i=0; i < 2; i++))
+do print foo
+ sleep 1.5
+done | { read; $bintrue; end=$SECONDS ;}
+(( (SECONDS-start) < 1 )) && err_exit "pipefail not waiting for pipe to finish"
+set +o pipefail
+(( (SECONDS-end) > 2 )) && err_exit "pipefail causing $bintrue to wait for other end of pipe"
+
+
+{ env A__z=C+SHLVL $SHELL -c : ;} 2> /dev/null || err_exit "SHLVL with wrong attribute fails"
+
+if [[ $bintrue ]]
+then float t0=SECONDS
+ { time sleep 1.5 | $bintrue ;} 2> /dev/null
+ (( (SECONDS-t0) < 1 )) && err_exit 'time not waiting for pipeline to complete'
+fi
+
+cat > $tmp/foo.sh <<- \EOF
+ eval "cat > /dev/null < /dev/null"
+ sleep 1
+EOF
+float sec=SECONDS
+. $tmp/foo.sh | cat > /dev/null
+(( (SECONDS-sec) < .7 )) && err_exit '. script does not restore output redirection with eval'
+
+file=$tmp/foobar
+builtin cat
+for ((n=0; n < 1000; n++))
+do
+ > $file
+ { sleep .001;echo $? >$file;} | cat > /dev/null
+ if [[ ! -s $file ]]
+ then err_exit 'output from pipe is lost with pipe to builtin'
+ break;
+ fi
+done
+
+$SHELL -c 'kill -0 123456789123456789123456789' 2> /dev/null && err_exit 'kill not catching process id overflows'
+
+[[ $($SHELL -c '{ cd..; print ok;}' 2> /dev/null) == ok ]] || err_exit 'command name ending in .. causes shell to abort'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/bracket.sh b/src/cmd/ksh93/tests/bracket.sh
new file mode 100755
index 0000000..cfe4055
--- /dev/null
+++ b/src/cmd/ksh93/tests/bracket.sh
@@ -0,0 +1,340 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+null=''
+if [[ ! -z $null ]]
+then err_exit "-z: null string should be of zero length"
+fi
+file=$tmp/original
+newer_file=$tmp/newer
+if [[ -z $file ]]
+then err_exit "-z: $file string should not be of zero length"
+fi
+if [[ -a $file ]]
+then err_exit "-a: $file shouldn't exist"
+fi
+if [[ -e $file ]]
+then err_exit "-e: $file shouldn't exist"
+fi
+> $file
+if [[ ! -a $file ]]
+then err_exit "-a: $file should exist"
+fi
+if [[ ! -e $file ]]
+then err_exit "-e: $file should exist"
+fi
+chmod 777 $file
+if [[ ! -r $file ]]
+then err_exit "-r: $file should be readable"
+fi
+if [[ ! -w $file ]]
+then err_exit "-w: $file should be writable"
+fi
+if [[ ! -w $file ]]
+then err_exit "-x: $file should be executable"
+fi
+if [[ ! -w $file || ! -r $file ]]
+then err_exit "-rw: $file should be readable/writable"
+fi
+if [[ -s $file ]]
+then err_exit "-s: $file should be of zero size"
+fi
+if [[ ! -f $file ]]
+then err_exit "-f: $file should be an ordinary file"
+fi
+if [[ -d $file ]]
+then err_exit "-f: $file should not be a directory file"
+fi
+if [[ ! -d . ]]
+then err_exit "-d: . should not be a directory file"
+fi
+if [[ -f /dev/null ]]
+then err_exit "-f: /dev/null should not be an ordinary file"
+fi
+chmod 000 $file
+if [[ -r $file ]]
+then err_exit "-r: $file should not be readable"
+fi
+if [[ ! -O $file ]]
+then err_exit "-r: $file should be owned by me"
+fi
+if [[ -w $file ]]
+then err_exit "-w: $file should not be writable"
+fi
+if [[ -w $file ]]
+then err_exit "-x: $file should not be executable"
+fi
+if [[ -w $file || -r $file ]]
+then err_exit "-rw: $file should not be readable/writable"
+fi
+if [[ -z x && -z x || ! -z x ]]
+then :
+else err_exit " wrong precedence"
+fi
+if [[ -z x && (-z x || ! -z x) ]]
+then err_exit " () grouping not working"
+fi
+if [[ foo < bar ]]
+then err_exit "foo comes before bar"
+fi
+[[ . -ef $(pwd) ]] || err_exit ". is not $PWD"
+set -o allexport
+[[ -o allexport ]] || err_exit '-o: did not set allexport option'
+if [[ -n $null ]]
+then err_exit "'$null' has non-zero length"
+fi
+if [[ ! -r /dev/fd/0 ]]
+then err_exit "/dev/fd/0 not open for reading"
+fi
+if [[ ! -w /dev/fd/2 ]]
+then err_exit "/dev/fd/2 not open for writing"
+fi
+sleep 1
+> $newer_file
+if [[ ! $file -ot $newer_file ]]
+then err_exit "$file should be older than $newer_file"
+fi
+if [[ $file -nt $newer_file ]]
+then err_exit "$newer_file should be newer than $file"
+fi
+if [[ $file != $tmp/* ]]
+then err_exit "$file should match $tmp/*"
+fi
+if [[ $file == $tmp'/*' ]]
+then err_exit "$file should not equal $tmp'/*'"
+fi
+[[ ! ( ! -z $null && ! -z x) ]] || err_exit "negation and grouping"
+[[ -z '' || -z '' || -z '' ]] || err_exit "three ors not working"
+[[ -z '' && -z '' && -z '' ]] || err_exit "three ors not working"
+(exit 8)
+if [[ $? -ne 8 || $? -ne 8 ]]
+then err_exit 'value $? within [[...]]'
+fi
+x='(x'
+if [[ '(x' != '('* ]]
+then err_exit " '(x' does not match '('* within [[...]]"
+fi
+if [[ '(x' != "("* ]]
+then err_exit ' "(x" does not match "("* within [[...]]'
+fi
+if [[ '(x' != \(* ]]
+then err_exit ' "(x" does not match \(* within [[...]]'
+fi
+if [[ 'x(' != *'(' ]]
+then err_exit " 'x(' does not match '('* within [[...]]"
+fi
+if [[ 'x&' != *'&' ]]
+then err_exit " 'x&' does not match '&'* within [[...]]"
+fi
+if [[ 'xy' == *'*' ]]
+then err_exit " 'xy' matches *'*' within [[...]]"
+fi
+if [[ 3 > 4 ]]
+then err_exit '3 < 4'
+fi
+if [[ 4 < 3 ]]
+then err_exit '3 > 4'
+fi
+if [[ 3x > 4x ]]
+then err_exit '3x < 4x'
+fi
+x='@(bin|dev|?)'
+cd /
+if [[ $(print $x) != "$x" ]]
+then err_exit 'extended pattern matching on command arguments'
+fi
+if [[ dev != $x ]]
+then err_exit 'extended pattern matching not working on variables'
+fi
+if [[ -u $SHELL ]]
+then err_exit "setuid on $SHELL"
+fi
+if [[ -g $SHELL ]]
+then err_exit "setgid on $SHELL"
+fi
+test -d . -a '(' ! -f . ')' || err_exit 'test not working'
+if [[ '!' != ! ]]
+then err_exit 'quoting unary operator not working'
+fi
+test \( -n x \) -o \( -n y \) 2> /dev/null || err_exit 'test ( -n x ) -o ( -n y) not working'
+test \( -n x \) -o -n y 2> /dev/null || err_exit 'test ( -n x ) -o -n y not working'
+chmod 600 $file
+exec 4> $file
+print -u4 foobar
+if [[ ! -s $file ]]
+then err_exit "-s: $file should be non-zero"
+fi
+exec 4>&-
+if [[ 011 -ne 11 ]]
+then err_exit "leading zeros in arithmetic compares not ignored"
+fi
+{
+ set -x
+ [[ foo > bar ]]
+} 2> /dev/null || { set +x; err_exit "foo<bar with -x enabled" ;}
+set +x
+(
+ eval "[[ (a) ]]"
+) 2> /dev/null || err_exit "[[ (a) ]] not working"
+> $file
+chmod 4755 "$file"
+if test -u $file && test ! -u $file
+then err_exit "test ! -u suidfile not working"
+fi
+for i in '(' ')' '[' ']'
+do [[ $i == $i ]] || err_exit "[[ $i != $i ]]"
+done
+(
+ [[ aaaa == {4}(a) ]] || err_exit 'aaaa != {4}(a)'
+ [[ aaaa == {2,5}(a) ]] || err_exit 'aaaa != {2,4}(a)'
+ [[ abcdcdabcd == {3,6}(ab|cd) ]] || err_exit 'abcdcdabcd == {3,4}(ab|cd)'
+ [[ abcdcdabcde == {5}(ab|cd)e ]] || err_exit 'abcdcdabcd == {5}(ab|cd)e'
+) || err_exit 'errors with {..}(...) patterns'
+[[ D290.2003.02.16.temp == D290.+(2003.02.16).temp* ]] || err_exit 'pattern match bug with +(...)'
+rm -rf $file
+{
+[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after creat'
+sleep 2
+print 'hello world'
+[[ -N $file ]] || err_exit 'test -N $tmp/*: st_mtime<=st_atime after write'
+sleep 2
+read
+[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after read'
+} > $file < $file
+if rm -rf "$file" && ln -s / "$file"
+then [[ -L "$file" ]] || err_exit '-L not working'
+ [[ -L "$file"/ ]] && err_exit '-L with file/ not working'
+fi
+$SHELL -c 't=1234567890; [[ $t == @({10}(\d)) ]]' 2> /dev/null || err_exit ' @({10}(\d)) pattern not working'
+$SHELL -c '[[ att_ == ~(E)(att|cus)_.* ]]' 2> /dev/null || err_exit ' ~(E)(att|cus)_* pattern not working'
+$SHELL -c '[[ att_ =~ (att|cus)_.* ]]' 2> /dev/null || err_exit ' =~ ere not working'
+$SHELL -c '[[ abc =~ a(b)c ]]' 2> /dev/null || err_exit '[[ abc =~ a(b)c ]] fails'
+$SHELL -xc '[[ abc =~ \babc\b ]]' 2> /dev/null || err_exit '[[ abc =~ \babc\b ]] fails'
+[[ abc == ~(E)\babc\b ]] || err_exit '\b not preserved for ere when not in ()'
+[[ abc == ~(iEi)\babc\b ]] || err_exit '\b not preserved for ~(iEi) when not in ()'
+
+e=$($SHELL -c '[ -z "" -a -z "" ]' 2>&1)
+[[ $e ]] && err_exit "[ ... ] compatibility check failed -- $e"
+i=hell
+[[ hell0 == $i[0] ]] || err_exit 'pattern $i[0] interpreded as array ref'
+test '(' = ')' && err_exit '"test ( = )" should not be true'
+[[ $($SHELL -c 'case F in ~(Eilr)[a-z0-9#]) print ok;;esac' 2> /dev/null) == ok ]] || err_exit '~(Eilr) not working in case command'
+[[ $($SHELL -c "case Q in ~(Fi)q | \$'\E') print ok;;esac" 2> /dev/null) == ok ]] || err_exit '~(Fi)q | \E not working in case command'
+
+for l in C en_US.ISO8859-15
+do [[ $($SHELL -c "LC_COLLATE=$l" 2>&1) ]] && continue
+ export LC_COLLATE=$l
+ set -- \
+ 'A' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ 'Z' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ '/' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '.' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '_' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '-' 1 1 1 1 1 1 0 0 0 0 0 0 \
+ '%' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '@' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '!' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '^' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ # retain this line #
+ while (( $# >= 13 ))
+ do c=$1
+ shift
+ for p in \
+ '[![.-.]]' \
+ '[![.-.][:upper:]]' \
+ '[![.-.]A-Z]' \
+ '[!-]' \
+ '[!-[:upper:]]' \
+ '[!-A-Z]' \
+ '[[.-.]]' \
+ '[[.-.][:upper:]]' \
+ '[[.-.]A-Z]' \
+ '[-]' \
+ '[-[:upper:]]' \
+ '[-A-Z]' \
+ # retain this line #
+ do e=$1
+ shift
+ [[ $c == $p ]]
+ g=$?
+ [[ $g == $e ]] || err_exit "[[ '$c' == $p ]] for LC_COLLATE=$l failed -- expected $e, got $g"
+ done
+ done
+done
+integer n
+if ( : < /dev/tty ) 2>/dev/null && exec {n}< /dev/tty
+then [[ -t $n ]] || err_exit "[[ -t n ]] fails when n > 9"
+fi
+foo=([1]=a [2]=b [3]=c)
+[[ -v foo[1] ]] || err_exit 'foo[1] should be set'
+[[ ${foo[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+[[ ${foo[@]+x} ]] || err_exit '${foo[@]+x} should be x'
+unset foo[1]
+[[ -v foo[1] ]] && err_exit 'foo[1] should not be set'
+[[ ${foo[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+bar=(a b c)
+[[ -v bar[1] ]] || err_exit 'bar[1] should be set'
+[[ ${bar[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+unset bar[1]
+[[ ${bar[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+[[ -v bar ]] || err_exit 'bar should be set'
+[[ -v bar[1] ]] && err_exit 'bar[1] should not be set'
+integer z=( 1 2 4)
+[[ -v z[1] ]] || err_exit 'z[1] should be set'
+unset z[1]
+[[ -v z[1] ]] && err_exit 'z[1] should not be set'
+typeset -si y=( 1 2 4)
+[[ -v y[6] ]] && err_exit 'y[6] should not be set'
+[[ -v y[1] ]] || err_exit 'y[1] should be set'
+unset y[1]
+[[ -v y[1] ]] && err_exit 'y[1] should not be set'
+x=abc
+[[ -v x[0] ]] || err_exit 'x[0] should be set'
+[[ ${x[0]+x} ]] || err_exit print '${x[0]+x} should be x'
+[[ -v x[3] ]] && err_exit 'x[3] should not be set'
+[[ ${x[3]+x} ]] && err_exit '${x[0]+x} should be Empty'
+unset x
+[[ ${x[@]+x} ]] && err_exit '${x[@]+x} should be Empty'
+unset x y z foo bar
+
+{ x=$($SHELL -c '[[ (( $# -eq 0 )) ]] && print ok') 2> /dev/null;}
+[[ $x == ok ]] || err_exit '((...)) inside [[...]] not treated as nested ()'
+
+[[ -e /dev/fd/ ]] || err_exit '/dev/fd/ does not exits'
+[[ -e /dev/tcp/ ]] || err_exit '/dev/tcp/ does not exist'
+[[ -e /dev/udp/ ]] || err_exit '/dev/udp/ does not exist'
+[[ -e /dev/xxx/ ]] && err_exit '/dev/xxx/ exists'
+
+$SHELL 2> /dev/null -c '[[(-n foo)]]' || err_exit '[[(-n foo)]] should not require space in front of ('
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh
new file mode 100755
index 0000000..6346aff
--- /dev/null
+++ b/src/cmd/ksh93/tests/builtins.sh
@@ -0,0 +1,562 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test shell builtin commands
+builtin getconf
+: ${foo=bar} || err_exit ": failed"
+[[ $foo == bar ]] || err_exit ": side effects failed"
+set -- - foobar
+[[ $# == 2 && $1 == - && $2 == foobar ]] || err_exit "set -- - foobar failed"
+set -- -x foobar
+[[ $# == 2 && $1 == -x && $2 == foobar ]] || err_exit "set -- -x foobar failed"
+getopts :x: foo || err_exit "getopts :x: returns false"
+[[ $foo == x && $OPTARG == foobar ]] || err_exit "getopts :x: failed"
+OPTIND=1
+getopts :r:s var -r
+if [[ $var != : || $OPTARG != r ]]
+then err_exit "'getopts :r:s var -r' not working"
+fi
+OPTIND=1
+getopts :d#u OPT -d 16177
+if [[ $OPT != d || $OPTARG != 16177 ]]
+then err_exit "'getopts :d#u OPT=d OPTARG=16177' failed -- OPT=$OPT OPTARG=$OPTARG"
+fi
+OPTIND=1
+while getopts 'ab' option -a -b
+do [[ $OPTIND == $((OPTIND)) ]] || err_exit "OPTIND optimization bug"
+done
+
+USAGE=$'[-][S:server?Operate on the specified \asubservice\a:]:[subservice:=pmserver]
+ {
+ [p:pmserver]
+ [r:repserver]
+ [11:notifyd]
+ }'
+set pmser p rep r notifyd -11
+while (( $# > 1 ))
+do OPTIND=1
+ getopts "$USAGE" OPT -S $1
+ [[ $OPT == S && $OPTARG == $2 ]] || err_exit "OPT=$OPT OPTARG=$OPTARG -- expected OPT=S OPTARG=$2"
+ shift 2
+done
+
+false ${foo=bar} && err_exit "false failed"
+read <<!
+hello world
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed"
+print x:y | IFS=: read a b
+if [[ $a != x ]]
+then err_exit "IFS=: read ... not working"
+fi
+read <<!
+hello \
+world
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read continuation failed"
+read -d x <<!
+hello worldxfoobar
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed"
+read <<\!
+hello \
+ world \
+
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read continuation2 failed"
+print "one\ntwo" | { read line
+ print $line | /bin/cat > /dev/null
+ read line
+}
+read <<\!
+\
+a\
+\
+\
+b
+!
+if [[ $REPLY != ab ]]
+then err_exit "read multiple continuation failed"
+fi
+if [[ $line != two ]]
+then err_exit "read from pipeline failed"
+fi
+line=two
+read line < /dev/null
+if [[ $line != "" ]]
+then err_exit "read from /dev/null failed"
+fi
+if [[ $(print -R -) != - ]]
+then err_exit "print -R not working correctly"
+fi
+if [[ $(print -- -) != - ]]
+then err_exit "print -- not working correctly"
+fi
+print -f "hello%nbar\n" size > /dev/null
+if (( size != 5 ))
+then err_exit "%n format of printf not working"
+fi
+print -n -u2 2>&1-
+[[ -w /dev/fd/1 ]] || err_exit "2<&1- with built-ins has side effects"
+x=$0
+if [[ $(eval 'print $0') != $x ]]
+then err_exit '$0 not correct for eval'
+fi
+$SHELL -c 'read x <<< hello' 2> /dev/null || err_exit 'syntax <<< not recognized'
+($SHELL -c 'read x[1] <<< hello') 2> /dev/null || err_exit 'read x[1] not working'
+unset x
+readonly x
+set -- $(readonly)
+if [[ " $@ " != *" x "* ]]
+then err_exit 'unset readonly variables are not displayed'
+fi
+if [[ $( for i in foo bar
+ do print $i
+ continue 10
+ done
+ ) != $'foo\nbar' ]]
+then err_exit 'continue breaks out of loop'
+fi
+(continue bad 2>/dev/null && err_exit 'continue bad should return an error')
+(break bad 2>/dev/null && err_exit 'break bad should return an error')
+(continue 0 2>/dev/null && err_exit 'continue 0 should return an error')
+(break 0 2>/dev/null && err_exit 'break 0 should return an error')
+breakfun() { break;}
+continuefun() { continue;}
+for fun in break continue
+do if [[ $( for i in foo
+ do ${fun}fun
+ print $i
+ done
+ ) != foo ]]
+ then err_exit "$fun call in ${fun}fun breaks out of for loop"
+ fi
+done
+if [[ $(print -f "%b" "\a\n\v\b\r\f\E\03\\oo") != $'\a\n\v\b\r\f\E\03\\oo' ]]
+then err_exit 'print -f "%b" not working'
+fi
+if [[ $(print -f "%P" "[^x].*b\$") != '*[!x]*b' ]]
+then err_exit 'print -f "%P" not working'
+fi
+if [[ $(abc: for i in foo bar;do print $i;break abc;done) != foo ]]
+then err_exit 'break labels not working'
+fi
+if [[ $(command -v if) != if ]]
+then err_exit 'command -v not working'
+fi
+read -r var <<\!
+
+!
+if [[ $var != "" ]]
+then err_exit "read -r of blank line not working"
+fi
+mkdir -p $tmp/a/b/c 2>/dev/null || err_exit "mkdir -p failed"
+$SHELL -c "cd $tmp/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails"
+
+trap 'print TERM' TERM
+exp=$'trap -- \'print TERM\' TERM\ntrap -- \'cd /; rm -rf '$tmp$'\' EXIT'
+got=$(trap)
+[[ $got == $exp ]] || err_exit "\$(trap) failed -- expected \"$exp\", got \"$got\""
+exp='print TERM'
+got=$(trap -p TERM)
+[[ $got == $exp ]] || err_exit "\$(trap -p TERM) failed -- expected \"$exp\", got \"$got\""
+
+[[ $($SHELL -c 'trap "print ok" SIGTERM; kill -s SIGTERM $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized'
+[[ $($SHELL -c 'trap "print ok" sigterm; kill -s sigterm $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized'
+[[ $($SHELL -c '( trap "" TERM);kill $$;print bad' == bad) ]] 2> /dev/null && err_exit 'trap ignored in subshell causes it to be ignored by parent'
+${SHELL} -c 'kill -1 -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working'
+${SHELL} -c 'kill -1 -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -n1 -pid not working'
+${SHELL} -c 'kill -s HUP -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working'
+n=123
+typeset -A base
+base[o]=8#
+base[x]=16#
+base[X]=16#
+for i in d i o u x X
+do if (( $(( ${base[$i]}$(printf "%$i" $n) )) != n ))
+ then err_exit "printf %$i not working"
+ fi
+done
+if [[ $( trap 'print done' EXIT) != done ]]
+then err_exit 'trap on EXIT not working'
+fi
+if [[ $( trap 'print done' EXIT; trap - EXIT) == done ]]
+then err_exit 'trap on EXIT not being cleared'
+fi
+if [[ $(LC_MESSAGES=C type test) != 'test is a shell builtin' ]]
+then err_exit 'whence -v test not a builtin'
+fi
+builtin -d test
+if [[ $(type test) == *builtin* ]]
+then err_exit 'whence -v test after builtin -d incorrect'
+fi
+typeset -Z3 percent=$(printf '%o\n' "'%'")
+forrmat=\\${percent}s
+if [[ $(printf "$forrmat") != %s ]]
+then err_exit "printf $forrmat not working"
+fi
+if (( $(printf 'x\0y' | wc -c) != 3 ))
+then err_exit 'printf \0 not working'
+fi
+if [[ $(printf "%bx%s\n" 'f\to\cbar') != $'f\to' ]]
+then err_exit 'printf %bx%s\n not working'
+fi
+alpha=abcdefghijklmnop
+if [[ $(printf "%10.*s\n" 5 $alpha) != ' abcde' ]]
+then err_exit 'printf %10.%s\n not working'
+fi
+float x2=.0000625
+if [[ $(printf "%10.5E\n" x2) != 6.25000E-05 ]]
+then err_exit 'printf "%10.5E" not normalizing correctly'
+fi
+x2=.000000001
+if [[ $(printf "%g\n" x2 2>/dev/null) != 1e-09 ]]
+then err_exit 'printf "%g" not working correctly'
+fi
+#FIXME#($SHELL read -s foobar <<\!
+#FIXME#testing
+#FIXME#!
+#FIXME#) 2> /dev/null || err_exit ksh read -s var fails
+if [[ $(printf +3 2>/dev/null) != +3 ]]
+then err_exit 'printf is not processing formats beginning with + correctly'
+fi
+if printf "%d %d\n" 123bad 78 >/dev/null 2>/dev/null
+then err_exit "printf not exiting non-zero with conversion errors"
+fi
+if [[ $(trap --version 2> /dev/null;print done) != done ]]
+then err_exit 'trap builtin terminating after --version'
+fi
+if [[ $(set --version 2> /dev/null;print done) != done ]]
+then err_exit 'set builtin terminating after --veresion'
+fi
+unset -f foobar
+function foobar
+{
+ print 'hello world'
+}
+OPTIND=1
+if [[ $(getopts $'[+?X\ffoobar\fX]' v --man 2>&1) != *'Xhello world'X* ]]
+then err_exit '\f...\f not working in getopts usage strings'
+fi
+if [[ $(printf '%H\n' $'<>"& \'\tabc') != '&lt;&gt;&quot;&amp;&nbsp;&apos;&#9;abc' ]]
+then err_exit 'printf %H not working'
+fi
+if [[ $( printf 'foo://ab_c%#H\n' $'<>"& \'\tabc') != 'foo://ab_c%3C%3E%22%26%20%27%09abc' ]]
+then err_exit 'printf %#H not working'
+fi
+if [[ $(printf '%R %R %R %R\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]]
+then err_exit 'printf %R not working'
+fi
+if [[ $(printf '%..:c\n' abc) != a:b:c ]]
+then err_exit "printf '%..:c' not working"
+fi
+if [[ $(printf '%..*c\n' : abc) != a:b:c ]]
+then err_exit "printf '%..*c' not working"
+fi
+if [[ $(printf '%..:s\n' abc def ) != abc:def ]]
+then err_exit "printf '%..:s' not working"
+fi
+if [[ $(printf '%..*s\n' : abc def) != abc:def ]]
+then err_exit "printf '%..*s' not working"
+fi
+[[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments'
+# we won't get hit by the one second boundary twice, right?
+[[ $(printf '%T\n' now) == "$(date)" ]] ||
+[[ $(printf '%T\n' now) == "$(date)" ]] ||
+err_exit 'printf "%T" now'
+behead()
+{
+ read line
+ left=$(cat)
+}
+print $'line1\nline2' | behead
+if [[ $left != line2 ]]
+then err_exit "read reading ahead on a pipe"
+fi
+read -n1 y <<!
+abc
+!
+exp=a
+if [[ $y != $exp ]]
+then err_exit "read -n1 failed -- expected '$exp', got '$y'"
+fi
+print -n $'{ read -r line;print $line;}\nhello' > $tmp/script
+chmod 755 $tmp/script
+if [[ $($SHELL < $tmp/script) != hello ]]
+then err_exit 'read of incomplete line not working correctly'
+fi
+set -f
+set -- *
+if [[ $1 != '*' ]]
+then err_exit 'set -f not working'
+fi
+unset pid1 pid2
+false &
+pid1=$!
+pid2=$(
+ wait $pid1
+ (( $? == 127 )) || err_exit "job known to subshell"
+ print $!
+)
+wait $pid1
+(( $? == 1 )) || err_exit "wait not saving exit value"
+wait $pid2
+(( $? == 127 )) || err_exit "subshell job known to parent"
+env=
+v=$(getconf LIBPATH)
+for v in ${v//,/ }
+do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && env="$env $v=\"\$$v\""
+done
+if [[ $(foo=bar; eval foo=\$foo $env exec -c \$SHELL -c \'print \$foo\') != bar ]]
+then err_exit '"name=value exec -c ..." not working'
+fi
+$SHELL -c 'OPTIND=-1000000; getopts a opt -a' 2> /dev/null
+[[ $? == 1 ]] || err_exit 'getopts with negative OPTIND not working'
+getopts 'n#num' opt -n 3
+[[ $OPTARG == 3 ]] || err_exit 'getopts with numerical arguments failed'
+if [[ $($SHELL -c $'printf \'%2$s %1$s\n\' world hello') != 'hello world' ]]
+then err_exit 'printf %2$s %1$s not working'
+fi
+val=$(( 'C' ))
+set -- \
+ "'C" $val 0 \
+ "'C'" $val 0 \
+ '"C' $val 0 \
+ '"C"' $val 0 \
+ "'CX" $val 1 \
+ "'CX'" $val 1 \
+ "'C'X" $val 1 \
+ '"CX' $val 1 \
+ '"CX"' $val 1 \
+ '"C"X' $val 1
+while (( $# >= 3 ))
+do arg=$1 val=$2 code=$3
+ shift 3
+ for fmt in '%d' '%g'
+ do out=$(printf "$fmt" "$arg" 2>/dev/null)
+ err=$(printf "$fmt" "$arg" 2>&1 >/dev/null)
+ printf "$fmt" "$arg" >/dev/null 2>&1
+ ret=$?
+ [[ $out == $val ]] || err_exit "printf $fmt $arg failed -- expected '$val', got '$out'"
+ if (( $code ))
+ then [[ $err ]] || err_exit "printf $fmt $arg failed, error message expected"
+ else [[ $err ]] && err_exit "$err: printf $fmt $arg failed, error message not expected -- got '$err'"
+ fi
+ (( $ret == $code )) || err_exit "printf $fmt $arg failed -- expected exit code $code, got $ret"
+ done
+done
+((n=0))
+((n++)); ARGC[$n]=1 ARGV[$n]=""
+((n++)); ARGC[$n]=2 ARGV[$n]="-a"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x y"
+for ((i=1; i<=n; i++))
+do set -- ${ARGV[$i]}
+ OPTIND=0
+ while getopts -a tst "av:" OPT
+ do :
+ done
+ if [[ $OPTIND != ${ARGC[$i]} ]]
+ then err_exit "\$OPTIND after getopts loop incorrect -- expected ${ARGC[$i]}, got $OPTIND"
+ fi
+done
+options=ab:c
+optarg=foo
+set -- -a -b $optarg -c bar
+while getopts $options opt
+do case $opt in
+ a|c) [[ $OPTARG ]] && err_exit "getopts $options \$OPTARG for flag $opt failed, expected \"\", got \"$OPTARG\"" ;;
+ b) [[ $OPTARG == $optarg ]] || err_exit "getopts $options \$OPTARG failed -- \"$optarg\" expected, got \"$OPTARG\"" ;;
+ *) err_exit "getopts $options failed -- got flag $opt" ;;
+ esac
+done
+
+[[ $($SHELL 2> /dev/null -c 'readonly foo; getopts a: foo -a blah; echo foo') == foo ]] || err_exit 'getopts with readonly variable causes script to abort'
+
+unset a
+{ read -N3 a; read -N1 b;} <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -N3 here-document failed -- expected '$exp', got '$a'"
+exp=d
+[[ $b == $exp ]] || err_exit "read -N1 here-document failed -- expected '$exp', got '$b'"
+read -n3 a <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -n3 here-document failed -- expected '$exp', got '$a'"
+#(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
+#[[ $a == $exp ]] || err_exit "read -N3 from pipe failed -- expected '$exp', got '$a'"
+#exp=d
+#[[ $b == $exp ]] || err_exit "read -N1 from pipe failed -- expected '$exp', got '$b'"
+#(print -n a;sleep 1; print -n bcde) | read -n3 a
+#exp=a
+#[[ $a == $exp ]] || err_exit "read -n3 from pipe failed -- expected '$exp', got '$a'"
+#rm -f $tmp/fifo
+#if mkfifo $tmp/fifo 2> /dev/null
+#then (print -n a; sleep 1;print -n bcde) > $tmp/fifo &
+# {
+# read -u5 -n3 -t2 a || err_exit 'read -n3 from fifo timedout'
+# read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout'
+# } 5< $tmp/fifo
+# exp=a
+# [[ $a == $exp ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$a'"
+# rm -f $tmp/fifo
+# mkfifo $tmp/fifo 2> /dev/null
+# (print -n a; sleep 1;print -n bcde) > $tmp/fifo &
+# {
+# read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out'
+# read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout'
+# } 5< $tmp/fifo
+# exp=abc
+# [[ $a == $exp ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$a'"
+# exp=d
+# [[ $b == $exp ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$b'"
+#fi
+#rm -f $tmp/fifo
+
+function longline
+{
+ integer i
+ for((i=0; i < $1; i++))
+ do print argument$i
+ done
+}
+# test command -x option
+integer sum=0 n=10000
+if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1
+then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) 2> /dev/null)
+ do ((sum += $i))
+ done
+ (( sum == n )) || err_exit "command -x processed only $sum arguments"
+ command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1
+ [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x'
+fi
+# test command -x option with extra arguments
+integer sum=0 n=10000
+if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1
+then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) one two three) #2> /dev/null)
+ do ((sum += $i))
+ done
+ (( sum > n )) || err_exit "command -x processed only $sum arguments"
+ (( (sum-n)%3==0 )) || err_exit "command -x processed only $sum arguments"
+ (( sum == n+3)) && err_exit "command -x processed only $sum arguments"
+ command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1
+ [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x'
+fi
+# test for debug trap
+[[ $(typeset -i i=0
+ trap 'print $i' DEBUG
+ while (( i <2))
+ do (( i++))
+ done) == $'0\n0\n1\n1\n2' ]] || err_exit "DEBUG trap not working"
+getconf UNIVERSE - ucb
+[[ $($SHELL -c 'echo -3') == -3 ]] || err_exit "echo -3 not working in ucb universe"
+typeset -F3 start_x=SECONDS total_t delay=0.02
+typeset reps=50 leeway=5
+#sleep $(( 2 * leeway * reps * delay )) |
+#for (( i=0 ; i < reps ; i++ ))
+#do read -N1 -t $delay
+#done
+#(( total_t = SECONDS - start_x ))
+#if (( total_t > leeway * reps * delay ))
+#then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too long"
+#elif (( total_t < reps * delay ))
+#then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too fast"
+#fi
+#$SHELL -c 'sleep $(printf "%a" .95)' 2> /dev/null || err_exit "sleep doesn't except %a format constants"
+#$SHELL -c 'test \( ! -e \)' 2> /dev/null ; [[ $? == 1 ]] || err_exit 'test \( ! -e \) not working'
+[[ $(ulimit) == "$(ulimit -fS)" ]] || err_exit 'ulimit is not the same as ulimit -fS'
+tmpfile=$tmp/file.2
+print $'\nprint -r -- "${.sh.file} ${LINENO} ${.sh.lineno}"' > $tmpfile
+[[ $( . "$tmpfile") == "$tmpfile 2 1" ]] || err_exit 'dot command not working'
+print -r -- "'xxx" > $tmpfile
+[[ $($SHELL -c ". $tmpfile"$'\n print ok' 2> /dev/null) == ok ]] || err_exit 'syntax error in dot command affects next command'
+
+#float sec=$SECONDS del=4
+#exec 3>&2 2>/dev/null
+#$SHELL -c "( sleep 1; kill -ALRM \$\$ ) & sleep $del" 2> /dev/null
+#exitval=$?
+#(( sec = SECONDS - sec ))
+#exec 2>&3-
+#(( exitval )) && err_exit "sleep doesn't exit 0 with ALRM interupt"
+#(( sec > (del - 1) )) || err_exit "ALRM signal causes sleep to terminate prematurely -- expected 3 sec, got $sec"
+typeset -r z=3
+y=5
+for i in 123 z %x a.b.c
+do ( unset $i) 2>/dev/null && err_exit "unset $i should fail"
+done
+a=()
+for i in y y y[8] t[abc] y.d a.b a
+do unset $i || print -u2 "err_exit unset $i should not fail"
+done
+[[ $($SHELL -c 'y=3; unset 123 y;print $?$y') == 1 ]] 2> /dev/null || err_exit 'y is not getting unset with unset 123 y'
+[[ $($SHELL -c 'trap foo TERM; (trap;(trap) )') == 'trap -- foo TERM' ]] || err_exit 'traps not getting reset when subshell is last process'
+
+n=$(printf "%b" 'a\0b\0c' | wc -c)
+(( n == 5 )) || err_exit '\0 not working with %b format with printf'
+
+t=$(ulimit -t)
+[[ $($SHELL -c 'ulimit -v 15000 2>/dev/null; ulimit -t') == "$t" ]] || err_exit 'ulimit -v changes ulimit -t'
+
+$SHELL 2> /dev/null -c 'cd ""' && err_exit 'cd "" not producing an error'
+[[ $($SHELL 2> /dev/null -c 'cd "";print hi') != hi ]] && err_exit 'cd "" should not terminate script'
+
+bincat=$(whence -p cat)
+builtin cat
+out=$tmp/seq.out
+seq 11 >$out
+cmp -s <(print -- "$($bincat<( $bincat $out ) )") <(print -- "$(cat <( cat $out ) )") || err_exit "builtin cat differs from $bincat"
+
+[[ $($SHELL -c '{ printf %R "["; print ok;}' 2> /dev/null) == ok ]] || err_exit $'\'printf %R "["\' causes shell to abort'
+
+v=$( $SHELL -c $'
+ trap \'print "usr1"\' USR1
+ trap exit USR2
+ sleep 1 && {
+ kill -USR1 $$ && sleep 1
+ kill -0 $$ 2>/dev/null && kill -USR2 $$
+ } &
+ sleep 2 | read
+ echo done
+' ) 2> /dev/null
+[[ $v == $'usr1\ndone' ]] || err_exit 'read not terminating when receiving USR1 signal'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/case.sh b/src/cmd/ksh93/tests/case.sh
new file mode 100755
index 0000000..7fe01ea
--- /dev/null
+++ b/src/cmd/ksh93/tests/case.sh
@@ -0,0 +1,85 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+bar=foo2
+bam=foo[3]
+for i in foo1 foo2 foo3 foo4 foo5 foo6
+do foo=0
+ case $i in
+ foo1) foo=1;;
+ $bar) foo=2;;
+ $bam) foo=3;;
+ foo[4]) foo=4;;
+ ${bar%?}5)
+ foo=5;;
+ "${bar%?}6")
+ foo=6;;
+ esac
+ if [[ $i != foo$foo ]]
+ then err_exit "$i not matching correct pattern"
+ fi
+done
+f="[ksh92]"
+case $f in
+\[*\]) ;;
+*) err_exit "$f does not match \[*\]";;
+esac
+
+if [[ $($SHELL -c '
+ x=$(case abc {
+ abc) { print yes;};;
+ *) print no;;
+ }
+ )
+ print -r -- "$x"' 2> /dev/null) != yes ]]
+then err_exit 'case abc {...} not working'
+fi
+[[ $($SHELL -c 'case a in
+a) print -n a > /dev/null ;&
+b) print b;;
+esac') != b ]] && err_exit 'bug in ;& at end of script'
+[[ $(VMDEBUG=1 $SHELL -c '
+ tmp=foo
+ for i in a b
+ do case $i in
+ a) : tmp=$tmp tmp.h=$tmp.h;;
+ b) ( tmp=bar )
+ for j in a
+ do print -r -- $tmp.h
+ done
+ ;;
+ esac
+ done
+') == foo.h ]] || err_exit "optimizer bug"
+
+x=$($SHELL -ec 'case a in a) echo 1; false; echo 2 ;& b) echo 3;; esac')
+[[ $x == 1 ]] || err_exit 'set -e ignored on case fail through'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/comvar.sh b/src/cmd/ksh93/tests/comvar.sh
new file mode 100755
index 0000000..e08f972
--- /dev/null
+++ b/src/cmd/ksh93/tests/comvar.sh
@@ -0,0 +1,689 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+#test for compound variables
+Command=${0##*/}
+integer Errors=0
+Point=(
+ float x=1. y=0.
+)
+eval p="$Point"
+if (( (p.x*p.x + p.y*p.y) > 1.01 ))
+then err_exit 'compound variable not working'
+fi
+nameref foo=p
+if [[ ${foo.x} != ${Point.x} ]]
+then err_exit 'reference to compound object not working'
+fi
+unset foo
+rec=(
+ name='Joe Blow'
+ born=(
+ month=jan
+ integer day=16
+ year=1980
+ )
+)
+eval newrec="$rec"
+if [[ ${newrec.name} != "${rec.name}" ]]
+then err_exit 'copying a compound object not working'
+fi
+if (( newrec.born.day != 16 ))
+then err_exit 'copying integer field of compound object not working'
+fi
+p_t=(
+ integer z=0
+ typeset -A tokens
+)
+unset x
+typeset -A x
+x=( [foo]=bar )
+if [[ ${x[@]} != bar ]]
+then err_exit 'compound assignemnt of associative arrays not working'
+fi
+unset -n foo x
+unset foo x
+foo=( x=3)
+nameref x=foo
+if [[ ${!x.@} != foo.x ]]
+then err_exit 'name references not expanded on prefix matching'
+fi
+unset x
+unset -n x
+(
+ x=()
+ x.foo.bar=7
+ [[ ${x.foo.bar} == 7 ]] || err_exit '[[ ${x.foo.bar} != 7 ]]'
+ (( x.foo.bar == 7 ))|| err_exit '(( x.foo.bar != 7 ))'
+ [[ ${x.foo} == *bar=7* ]] || err_exit '[[ ${x.foo} != *bar=7* ]]'
+)
+foo=(integer x=3)
+if [[ ${foo} != *x=3* ]]
+then err_exit "compound variable with integer subvariable not working"
+fi
+$SHELL -c $'x=(foo=bar)\n[[ x == x ]]' 2> /dev/null ||
+ err_exit '[[ ... ]] not working after compound assignment'
+unset foo
+[[ ${!foo.@} ]] && err_exit 'unset compound variable leaves subvariables'
+suitable=(
+ label="Table Viewer"
+ langs="ksh"
+ uselang=ksh
+ launch=no
+ groups="default"
+ default=(
+ label="Table Viewer Preferences"
+ entrylist=" \
+ vieworigin viewsize viewcolor viewfontname viewfontsize \
+ showheader header showfooter footer showtitle title showlegends \
+ class_td_lg1_style class_tr_tr1_style \
+ class_th_th1_style class_td_td1_style \
+ fields fieldorder \
+ "
+ entries=(
+ vieworigin=(
+ type=coord var=vieworigin val="0 0" label="Window Position"
+ )
+ viewsize=(
+ type=coord var=viewsize val="400 400" label="Window Size"
+ )
+ viewcolor=(
+ type=2colors var=viewcolor val="gray black"
+ label="Window Colors"
+ )
+ viewfontname=(
+ type=fontname var=viewfontname val="Times-Roman"
+ label="Window Font Name"
+ )
+ viewfontsize=(
+ type=fontsize var=viewfontsize val=14 label="Window Font Size"
+ )
+
+ showheader=(
+ type=yesno var=showheader val=no label="Show Header"
+ )
+ header=(
+ type=text var=header val="" label="Header"
+ )
+
+ showfooter=(
+ type=yesno var=showfooter val=no label="Show Footer"
+ )
+ footer=(
+ type=text var=footer val="" label="Footer"
+ )
+
+ showtitle=(
+ type=yesno var=showtitle val=yes label="Show Title"
+ )
+ title=(
+ type=text var=title val="SWIFTUI - Table View" label="Title"
+ )
+
+ showlegends=(
+ type=yesno var=showlegends val=yes label="Show Legends"
+ )
+
+ class_td_lg1_style=(
+ type=style var=class_td_lg1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt"
+ label="Legend 1 Style"
+ )
+
+ class_tr_tr1_style=(
+ type=style var=class_tr_tr1_style val="background: black"
+ label="Table Row 1 Style"
+ )
+
+ class_th_th1_style=(
+ type=style var=class_th_th1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left"
+ label="Table Header 1 Style"
+ )
+
+ class_td_td1_style=(
+ type=style var=class_td_td1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left"
+ label="Table Cell 1 Style"
+ )
+
+ fields=(
+ type=text var=fields val= label="List of Fields"
+ )
+ fieldorder=(
+ type=text var=fieldorder val= label="Order of Fields"
+ )
+ )
+ )
+)
+[[ "${suitable}" == *entrylist=* ]] || err_exit 'compound variable expansion omitting fields'
+foo=( bar=foo barbar=bar)
+[[ $foo == *bar=foo* ]] || err_exit 'no prefix elements in compound variable output'
+function localvar
+{
+ typeset point=(typeset -i x=3 y=4)
+ (( (point.x*point.x + point.y*point.y) == 25 )) || err_exit "local compound variable not working"
+}
+point=(integer x=6 y=8)
+localvar
+ (( (point.x*point.x + point.y*point.y) == 100 )) || err_exit "global compound variable not preserved"
+[[ $($SHELL -c 'foo=();foo.[x]=(y z); print ${foo.x[@]}') == 'y z' ]] 2> /dev/null || err_exit 'foo=( [x]=(y z) not working'
+function staticvar
+{
+ if [[ $1 ]]
+ then print -r -- "$point"
+ return
+ fi
+ typeset -S point=(typeset -i x=3 y=4)
+ (( (point.x*point.x + point.y*point.y) == 25 )) || err_exit "local compound variable not working"
+ point.y=5
+ point.z=foobar
+}
+staticvar
+ (( (point.x*point.x + point.y*point.y) == 100 )) || err_exit "global compound variable not preserved"
+[[ $(staticvar x) == $'(\n\ttypeset -i x=3\n\ttypeset -i y=5\n\tz=foobar\n)' ]] || err_exit 'static variables in function not working'
+integer x=3
+( typeset -S x=+++)2> /dev/null || err_exit "typeset -S doesn't unset first"
+
+unset z
+( [[ ${z.foo.bar:-abc} == abc ]] 2> /dev/null) || err_exit ':- not working with compound variables'
+stack=()
+typeset -a stack.items=([0]=foo [1]=bar)
+[[ ${stack.items[0]} == foo ]] || err_exit 'typeset -a variable not expanding correctly'
+$SHELL -c 'typeset -a info=( [1]=( passwd=( since=2005-07-20) ))' || err_exit 'problem with embedded index array in compound variable'
+x=(foo=([1]=(y=([2]=(z=4)))))
+[[ $x == *'.y'=* ]] && err_exit 'expansion with bogus leading . in name'
+unset z
+z=1
+function foo
+{
+ z=3
+ [[ ${a.z} == 3 ]] && err_exit "\${a.z} should not be 3"
+ print hi
+}
+a=( b=$(foo) )
+[[ ${a.z} == 3 ]] && err_exit 'a.z should not be set to 3'
+function a.b.get
+{
+ .sh.value=foo
+}
+{ b=( b1=${a.b} ) ;} 2> /dev/null
+[[ ${b.b1} == foo ]] || err_exit '${b.b1} should be foo'
+function dcl1
+{
+ eval 'a=1
+ function a.set
+ { print ${.sh.name}=${.sh.value}; }'
+}
+function dcl2
+{
+ eval 'b=(typeset x=0; typeset y=0 )
+ function b.x.set
+ { print ${.sh.name}=${.sh.value}; }'
+}
+dcl1
+[[ ${ a=123;} == 'a=123' ]] || err_exit 'should be a=123'
+dcl2
+[[ ${ b.x=456;} == 'b.x=456' ]] || err_exit 'should be b.x=456'
+eval 'b=(typeset x=0; typeset y=0 )
+function b.x.set
+{ print ${.sh.name}=${.sh.value}; }' > /dev/null
+[[ ${ b.x=789;} == 'b.x=789' ]] || err_exit 'should be b.x=789'
+unset a b
+function func
+{
+ typeset X
+ X=( bar=2 )
+}
+
+X=( foo=1 )
+func
+[[ $X == $'(\n\tfoo=1\n)' ]] || err_exit 'scoping problem with compound variables'
+unset foo
+typeset -A foo=([a]=aa;[b]=bb;[c]=cc)
+[[ ${foo[c]} == cc ]] || err_exit 'associative array assignment with; not working'
+[[ $({ $SHELL -c 'x=(); typeset -a x.foo; x.foo=bar; print -r -- "$x"' ;} 2> /dev/null) == $'(\n\ttypeset -a foo=bar\n)' ]] || err_exit 'indexed array in compound variable with only element 0 defined fails'
+unset foo
+foo=(typeset -a bar)
+[[ $foo == *'typeset -a bar'* ]] || err_exit 'array attribute -a not preserved in compound variable'
+unset s
+typeset -A s=( [foo]=(y=2 z=3) [bar]=(y=4 z=5))
+[[ ${s[@]} == *z=*z=* ]] || err_exit 'missing elements in compound associative array'
+unset nodes
+typeset -A nodes
+nodes[0]+=( integer x=5)
+[[ ${nodes[0].x} == 5 ]] || err_exit '${nodes[0].x} should be 5'
+unset foo
+typeset -C foo
+foo.bar=abc
+[[ $foo == $'(\n\tbar=abc\n)' ]] || err_exit 'typeset -C not working for foo'
+typeset -C foo=(bar=def)
+[[ $foo == $'(\n\tbar=def\n)' ]] || err_exit 'typeset -C not working when initialized'
+foo=(
+ hello=ok
+ yes=( bam=2 yes=4)
+ typeset -A array=([one]=one [two]=2)
+ last=me
+)
+eval foo2="$foo"
+foo2.hello=notok foo2.yes.yex=no foo2.extra=yes.
+typeset -C bar bam
+{
+ read -Cu3 bar
+ read -Cu3 bam
+ read -ru3
+} 3<<- ++++
+ "$foo"
+ "$foo2"
+ last line
+++++
+[[ $? == 0 ]] || err_exit ' read -C failed'
+[[ $bar == "$foo" ]] || err_exit '$foo != $bar'
+[[ $bam == "$foo2" ]] || err_exit '$foo2 != $bmr'
+[[ $REPLY == 'last line' ]] || err_exit "\$REPLY=$REPLY should be 'last line"
+typeset x=( typeset -a foo=( [1][3]=hello [9][2]="world" ) )
+eval y="(typeset -a foo=$(printf "%B\n" x.foo) )"
+[[ $x == "$y" ]] || err_exit '$x.foo != $y.foo with %B'
+eval y="(typeset -a foo=$(printf "%#B\n" x.foo) )"
+[[ $x == "$y" ]] || err_exit '$x.foo != $y.foo with %#B'
+eval y="$(printf "%B\n" x)"
+[[ $x == "$y" ]] || err_exit '$x != $y with %B'
+eval y="$(printf "%#B\n" x)"
+[[ $x == "$y" ]] || err_exit '$x != $y with %#B'
+y=$(set | grep ^x=) 2> /dev/null
+eval "${y/#x/y}"
+[[ $x == "$y" ]] || err_exit '$x != $y with set | grep'
+unset x y z
+x=( float x=0 y=1; z=([foo]=abc [bar]=def))
+typeset -C y=x
+[[ $x == "$y" ]] || err_exit '$x != $y with typeset -C'
+unset y
+y=()
+y=x
+[[ $x == "$y" ]] || err_exit '$x != $y when x=y and x and y are -C '
+function foobar
+{
+ typeset -C z
+ z=x
+ [[ $x == "$z" ]] || err_exit '$x != $z when x=z and x and z are -C '
+ y=z
+}
+[[ $x == "$y" ]] || err_exit '$x != $y when x=y -C copied in a function '
+z=(foo=abc)
+y+=z
+[[ $y == *foo=abc* ]] || err_exit 'z not appended to y'
+unset y.foo
+[[ $x == "$y" ]] || err_exit '$x != $y when y.foo deleted'
+unset x y
+x=( foo=(z=abc d=ghi) bar=abc; typeset -A r=([x]=3 [y]=4))
+unset x
+x=()
+[[ $x == $'(\n)' ]] || err_exit 'unset compound variable is not empty'
+
+unset z
+z=()
+z.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
+z.bar[0]=hello
+z.bar[2]=world
+z.bar[1]=(x=4 y=5)
+exp='(
+ typeset -a bar=(
+ [0]=hello
+ [2]=world
+ [1]=(
+ x=4
+ y=5
+ )
+ )
+ typeset -A foo=(
+ [one]=hello
+ [three]=hi
+ [two]=(
+ x=3
+ y=4
+ )
+ )
+)'
+got=$z
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+typeset -A record
+record[a]=(
+ typeset -a x=(
+ [1]=(
+ X=1
+ )
+ )
+)
+exp=$'(\n\ttypeset -a x=(\n\t\t[1]=(\n\t\t\tX=1\n\t\t)\n\t)\n)'
+got=${record[a]}
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+unset r
+r=(
+ typeset -a x=(
+ [1]=(
+ X=1
+ )
+ )
+)
+exp=$'(\n\ttypeset -a x=(\n\t\t[1]=(\n\t\t\tX=1\n\t\t)\n\t)\n)'
+got=$r
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+# array of compund variables
+typeset -C data=(
+ typeset -a samples
+)
+data.samples+=(
+ type1="greeting1"
+ timestamp1="now1"
+ command1="grrrr1"
+)
+data.samples+=(
+ type2="greeting2"
+ timestamp2="now2"
+ command2="grrrr2"
+)
+
+[[ $data == %(()) ]] || err_exit "unbalanced parenthesis with compound variable containing array of compound variables"
+typeset -C -A hello=( [foo]=bar)
+[[ $(typeset -p hello) == 'typeset -C -A hello=([foo]=bar)' ]] || err_exit 'typeset -A -C with intial assignment not working'
+# this caused a core dump before ksh93t+
+[[ $($SHELL -c 'foo=(x=3 y=4);function bar { typeset z=4;: $z;};bar;print ${!foo.@}') == 'foo.x foo.y' ]] 2> /dev/null || err_exit '${!foo.@} after function not working'
+
+function foo
+{
+ typeset tmp
+ read -C tmp
+ read -C tmp
+}
+foo 2> /dev/null <<- \EOF || err_exit 'deleting compound variable in function failed'
+ (
+ typeset -A myarray3=(
+ [a]=( foo=bar)
+ [b]=( foo=bar)
+ [c d]=( foo=bar)
+ [e]=( foo=bar)
+ [f]=( foo=bar)
+ [g]=( foo=bar)
+ [h]=( foo=bar)
+ [i]=( foo=bar)
+ [j]=( foo=bar)
+ )
+ )
+ hello
+EOF
+
+typeset -C -a mica01
+mica01[4]=( a_string="foo bar" )
+typeset -C more_content=(
+ some_stuff="hello"
+)
+mica01[4]+=more_content
+expected=$'typeset -C -a mica01=([4]=(a_string=\'foo bar\';some_stuff=hello))'
+[[ $(typeset -p mica01) == "$expected" ]] || err_exit 'appened to indexed array compound variable not working'
+
+unset x
+compound x=( integer x ; )
+[[ ! -v x.x ]] && err_exit 'x.x should be set'
+expected=$'(\n\ttypeset -l -i x=0\n)'
+[[ $(print -v x) == "$expected" ]] || err_exit "'print -v x' should be $expected"
+
+typeset -C -A hello19=(
+ [19]=(
+ one="xone 19"
+ two="xtwo 19"
+ )
+ [23]=(
+ one="xone 23"
+ two="xtwo 23"
+ )
+)
+expected="typeset -C -A hello19=([19]=(one='xone 19';two='xtwo 19') [23]=(one='xone 23';two='xtwo 23'))"
+[[ $(typeset -p hello19) == "$expected" ]] || print -u2 'typeset -p hello19 incorrect'
+expected=$'(\n\tone=\'xone 19\'\n\ttwo=\'xtwo 19\'\n) (\n\tone=\'xone 23\'\n\ttwo=\'xtwo 23\'\n)'
+[[ ${hello19[@]} == "$expected" ]] || print -u2 '${hello19[@]} incorrect'
+
+typeset -C -A foo1=( abc="alphabet" ) foo2=( abc="alphabet" )
+function add_one
+{
+ nameref left_op=$1
+ typeset -C info
+ info.hello="world"
+ nameref x=info
+ left_op+=x
+}
+nameref node1="foo1[1234]"
+add_one "node1"
+add_one "foo2[1234]"
+[[ "${foo1[1234]}" == "${foo2[1234]}" ]] || err_exit "test failed\n$(diff -u <( print -r -- "${foo1[1234]}") <(print -r -- "${foo2[1234]}"))."
+
+typeset -C tree
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+
+ # move local note into the array
+ typeset -m tr.subtree["a_node"]=node
+}
+f1 tree
+expected=$'(\n\ttypeset -A subtree=(\n\t\t[a_node]=(\n\t\t\tone=hello\n\t\t\ttwo=world\n\t\t)\n\t)\n)'
+[[ $tree == "$expected" ]] || err_exit 'move of compound local variable to global variable not working'
+
+typeset -C -A array
+float array[12].amount=2.9
+expected='typeset -C -A array=([12]=(typeset -l -E amount=2.9))'
+[[ $(typeset -p array) == "$expected" ]] || err_exit 'typeset with compound variable with compound variable array not working'
+
+typeset -T foo_t=(
+ function diff
+ {
+ print 1.0
+ return 0
+ }
+)
+foo_t sw
+compound output=(
+ integer one=1
+ float mydiff=sw.diff
+ float end=.314
+)
+[[ $output == *end=* ]] || err_exit "The field 'name' end is missing"
+
+compound cpv1=( integer f=2 )
+compound x=(
+ integer a=1
+ compound b=cpv1
+)
+[[ $x == *f=2* ]] || err_exit "The field b containg 'f=2' is missing"
+
+unset x
+compound x=(
+ compound -a nodes=(
+ [4]=( )
+ )
+)
+expected='typeset -C x=(typeset -C -a nodes=([4]=());)'
+[[ $(typeset -p x) == "$expected" ]] || err_exit 'typeset -p with nested compound index array not working'
+
+unset v
+compound v=(
+ integer -A ar=(
+ [aa]=4 [bb]=9
+ )
+)
+expected='typeset -C v=(typeset -A -l -i ar=([aa]=4 [bb]=9);)'
+[[ $(typeset -p v) == "$expected" ]] || err_exit 'attributes for associative arrays embedded in compound variables not working'
+
+unset x
+compound -a x
+x[1]=( a=1 b=2 )
+[[ $(print -v x[1]) == "${x[1]}" ]] || err_exit 'print -v x[1] not working for index array of compound variables'
+
+unset x
+z='typeset -a x=(hello (x=12;y=5) world)'
+{ eval "$z" ;} 2> /dev/null
+[[ $(typeset -p x) == "$z" ]] || err_exit "compound assignment '$z' not working"
+
+expected='typeset -C -A l=([4]=(typeset -a ar=(1 2 3);b=1))'
+typeset -A -C l
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4]
+[[ $(typeset -p l) == "$expected" ]] || err_exit 'read -C for associative array of compound variables not working'
+
+unset x
+compound x=( z="a=b c")
+exp=$'typeset -C x=(z=a\\=\'b c\')'
+got=$(typeset -p x)
+[[ $got == "$exp" ]] || err_exit "typeset -p failed -- expected '$exp', got '$got'"
+
+x=(typeset -C -a y;float z=2)
+got=$(print -C x)
+expected='(typeset -C -a y;typeset -l -E z=2)'
+[[ $expected == "$got" ]] || err_exit "print -C x exects '$expected' got '$got'"
+
+unset vx vy
+compound vx=(
+ compound -a va=(
+ [3][17]=(
+ integer -A ar=( [aa]=4 [bb]=9 )
+ )
+ )
+)
+eval "vy=$(print -C vx)"
+[[ $vx == "$vy" ]] || err_exit 'print -C with multi-dimensional array not working'
+eval "vy=$(print -v vx)"
+[[ $vx == "$vy" ]] || err_exit 'print -v with multi-dimensional array not working'
+
+unset x
+typeset -C -A x=( [0]=(a=1) [1]=(b=2) )
+expected=$'(\n\t[0]=(\n\t\ta=1\n\t)\n\t[1]=(\n\t\tb=2\n\t)\n)'
+[[ $(print -v x) == "$expected" ]] || err_exit 'print -v not formatting correctly'
+
+compound -a x=( [0]=(a=1) [1]=(b=2) )
+typeset -m "z=x[1]"
+[[ $(typeset -p z 2>/dev/null) == 'typeset -C z=(b=2)' ]] || err_exit 'typeset -m not working with commpound -a variable'
+
+unset x z
+compound -A x=( [0]=(a=1) [1]=(b=2) )
+typeset -m "z=x[1]"
+[[ $(typeset -p z 2>/dev/null) == 'typeset -C z=(b=2)' ]] || err_exit 'typeset -m not working with commpound -a variable'
+typeset -m "x[1]=x[0]"
+typeset -m "x[0]=z"
+exp='([0]=(b=2) [1]=(a=1))'
+[[ $(print -C x) == "$exp" ]] || err_exit 'typeset -m not working for associative arrays'
+
+unset z r
+z=(a b c)
+r=(x=3 y=4)
+typeset -m z[1]=r
+exp='typeset -a z=(a (x=3;y=4) c)'
+[[ $(typeset -p z) == "$exp" ]] || err_exit 'moving compound variable into indexed array fails'
+
+unset c
+compound c
+compound -a c.a=( [1]=( aa=1 ) )
+compound -a c.b=( [2]=( bb=2 ) )
+typeset -m "c.b[9]=c.a[1]"
+exp='typeset -C c=(typeset -C -a a;typeset -C -a b=( [2]=(bb=2;)[9]=(aa=1));)'
+[[ $(typeset -p c) == "$exp" ]] || err_exit 'moving compound indexed array element to another index fails'
+
+unset c
+compound c
+compound -a c.a=( [1]=( aa=1 ) )
+compound -A c.b=( [2]=( bb=2 ) )
+typeset -m "c.b[9]=c.a[1]"
+exp='typeset -C c=(typeset -C -a a;typeset -C -A b=( [2]=(bb=2;)[9]=(aa=1));)'
+[[ $(typeset -p c) == "$exp" ]] || err_exit 'moving compound indexed array element to a compound associative array element fails'
+
+zzz=(
+ foo=(
+ bar=4
+ )
+)
+[[ $(set | grep "^zzz\.") ]] && err_exit 'set displays compound variables incorrectly'
+
+typeset -A stats
+stats[1]=(a=1 b=2)
+stats[2]=(a=1 b=2)
+stats[1]=(c=3 d=4)
+(( ${#stats[@]} == 2 )) || err_exit "stats[1] should contain 2 element not ${#stats[@]}"
+
+integer i=1
+foo[i++]=(x=3 y=4)
+[[ ${foo[1].x} == 3 ]] || err_exit "\${foo[1].x} should be 3"
+[[ ${foo[1].y} == 4 ]] || err_exit "\${foo[1].y} should be 4"
+
+# ${!x.} caused core dump in ks93u and earlier
+{ $SHELL -c 'compound x=(y=1); : ${!x.}' ; ((!$?));} || err_exit '${!x.} not working'
+
+$SHELL -c 'typeset -A a=([b]=c)' 2> /dev/null || err_exit 'typeset -A a=([b]=c) fails'
+
+compound -a a
+compound c=( name="container1" )
+a[4]=c
+[[ ${a[4]} == $'(\n\tname=container1\n)' ]] || err_exit 'assignment of compound variable to compound array element not working'
+
+unset c
+compound c
+compound -a c.board
+for ((i=2; i < 4; i++))
+do c.board[1][$i]=(foo=bar)
+done
+exp=$'(\n\ttypeset -C -a board=(\n\t\t[1]=(\n\t\t\t[2]=(\n\t\t\t\tfoo=bar\n\t\t\t)\n\t\t\t[3]=(\n\t\t\t\tfoo=bar\n\t\t\t)\n\t\t)\n\t)\n)'
+[[ "$(print -v c)" == "$exp" ]] || err_exit 'compound variable assignment to two dimensional array not working'
+
+unset zz
+zz=()
+zz.[foo]=abc
+zz.[2]=def
+exp='typeset -C zz=([2]=def;foo=abc)'
+[[ $(typeset -p zz) == "$exp" ]] || err_exit 'expansion of compound variables with non-identifiers not working'
+(
+ typeset -i zz.[3]=123
+ exec 2>& 3-
+ exp='typeset -C zz=([2]=def;typeset -i [3]=123;foo=abc)'
+ [[ $(typeset -p zz) == "$exp" ]] || err_exit 'expansion of compound variables with non-identifiers not working in subshells'
+) 3>&2 2> /dev/null || err_exit 'syntax errors expansion of compound variables with non-identifiers'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/comvario.sh b/src/cmd/ksh93/tests/comvario.sh
new file mode 100644
index 0000000..8ed803a
--- /dev/null
+++ b/src/cmd/ksh93/tests/comvario.sh
@@ -0,0 +1,686 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Roland Mainz <roland.mainz@nrubsig.org> #
+# #
+########################################################################
+
+# test setup
+function err_exit
+{
+ print -u2 -n '\t'
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+# "nounset" disabled for now
+#set -o nounset
+Command=${0##*/}
+integer Errors=0 HAVE_signbit=0
+
+if typeset -f .sh.math.signbit >/dev/null && (( signbit(-NaN) ))
+then HAVE_signbit=1
+else print -u2 "$0: warning: -lm does not support signbit(-NaN)"
+fi
+
+compound bracketstat=(
+ integer bopen=0
+ integer bclose=0
+)
+
+function count_brackets
+{
+ typeset x="$1"
+ typeset c
+
+ integer i
+ (( bracketstat.bopen=0 , bracketstat.bclose=0 ))
+
+ for (( i=0 ; i < ${#x} ; i++ )) ; do
+ c="${x:i:1}"
+ [[ "$c" == '(' ]] && (( bracketstat.bopen++ ))
+ [[ "$c" == ')' ]] && (( bracketstat.bclose++ ))
+ done
+
+ (( bracketstat.bopen != bracketstat.bclose )) && return 1
+
+ return 0
+}
+
+# compound variable "cat" nr.1, using $ print "%B\n" ... #
+function cpvcat1
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf '%B\n' tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.2, using $ print "%#B\n" ... #
+function cpvcat2
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf '%#B\n' tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.3, using $ print -C ... #
+function cpvcat3
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -C tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.4, using $ print -v ... #
+function cpvcat4
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -v tmp ; done
+ return 0
+}
+
+typeset s
+
+# Test 1:
+# Check whether "read -C" leaves the file pointer at the next line
+# (and does not read beyond that point).
+# Data layout is:
+# -- snip --
+# <compound var>
+# hello
+# -- snip --
+# (additionally we test some extra stuff like bracket count)
+s=${
+ compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ typeset -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+ )
+
+ {
+ printf "%B\n" x
+ print "hello"
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
+ read -C y
+ read s
+ }
+ print "x${s}x"
+} || err_exit "test returned exit code $?"
+
+[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}"
+count_brackets "$y" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+
+# cleanup
+unset x y || err_exit "unset failed"
+[[ "$x" == '' ]] || err_exit "cleanup failed for x"
+[[ "$y" == '' ]] || err_exit "cleanup failed for y"
+
+
+# Test 2:
+# Same as test 1 except one more compound var following the "hello"
+# line.
+# Data layout is:
+# -- snip --
+# <compound var>
+# hello
+# <compound var>
+# -- snip --
+s=${
+ compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ compound -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+ )
+
+ {
+ printf "%B\n" x
+ print "hello"
+ printf "%B\n" x
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
+ read -C y1
+ read s
+ read -C y2
+ }
+
+ print "x${s}x"
+} || err_exit "test returned exit code $?"
+
+[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}."
+[[ "${y1.myarray3[b].foo}" == "bar" ]] || err_exit "y1.myarray3[b].foo != bar"
+[[ "${y2.myarray3[b].foo}" == "bar" ]] || err_exit "y2.myarray3[b].foo != bar"
+[[ "$y1" != "" ]] || err_exit "y1 is empty"
+[[ "$y2" != "" ]] || err_exit "y2 is empty"
+(( ${#y1.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y1.myarray3[e].nested_cpv, got ${#y1.myarray3[e].nested_cpv[@]}"
+(( ${#y2.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y2.myarray3[e].nested_cpv, got ${#y2.myarray3[e].nested_cpv[@]}"
+(( isnan(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not a NaN"
+(( isnan(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not a NaN"
+if (( HAVE_signbit ))
+then (( signbit(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not negative"
+ (( signbit(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not negative"
+fi
+count_brackets "$y1" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$y2" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+[[ "$y1" == "$y2" ]] || err_exit "Expected $(printf "%q\n" "${y1}") == $(printf "%q\n" "${y2}")."
+[[ "$x" == "$y1" ]] || err_exit "Expected $(printf "%q\n" "${x}") == $(printf "%q\n" "${y}")."
+
+# cleanup
+unset x y1 y2 || err_exit "unset failed"
+[[ "$x" == '' ]] || err_exit "cleanup failed for x"
+[[ "$y1" == '' ]] || err_exit "cleanup failed for y1"
+[[ "$y2" == '' ]] || err_exit "cleanup failed for y2"
+
+
+# Test 3: Test compound variable copy operator vs. "read -C"
+compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ compound -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+)
+
+compound x_copy=x || err_exit "x_copy copy failed"
+[[ "${x_copy}" != "" ]] || err_exit "x_copy should not be empty"
+count_brackets "${x_copy}" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+
+compound nested_cpv_copy
+
+nested_cpv_copy=x.myarray3[e].nested_cpv || err_exit "x.myarray3[e].nested_cpv copy failed"
+(( ${#nested_cpv_copy.myarray[@]} == 10 )) || err_exit "Expected 10 elements in nested_cpv_copy.myarray, got ${#nested_cpv_copy.myarray[@]}"
+
+# unset branch "x.myarray3[e].nested_cpv" of the variable tree "x" ...
+unset x.myarray3[e].nested_cpv || err_exit "unset x.myarray3[e].nested_cpv failed"
+[[ "${x.myarray3[e].nested_cpv}" == "" ]] || err_exit "x.myarray3[e].nested_cpv still has a value"
+
+# ... and restore it from the saved copy
+printf "%B\n" nested_cpv_copy | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | read -C x.myarray3[e].nested_cpv || err_exit "read failed"
+
+# compare copy of the original tree and the modified one
+[[ "${x}" == "${x_copy}" ]] || err_exit "x != x_copy"
+count_brackets "${x}" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+(( ${#x.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in x.myarray3[e].nested_cpv, got ${#x.myarray3[e].nested_cpv[@]}"
+(( isnan(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not a NaN"
+if (( HAVE_signbit ))
+then (( signbit(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not negative"
+fi
+
+# cleanup
+unset x x_copy nested_cpv_copy || err_exit "unset failed"
+
+
+# Test 4: Test "read -C" failure for missing bracket at the end
+typeset s
+s=$($SHELL -c 'compound myvar ; print "( unfinished=1" | read -C myvar 2>'/dev/null' || print "error $?"') || err_exit 'shell failed'
+[[ "$s" == 'error 3' ]] || err_exit "compound_read: expected error 3, got ${s}"
+
+
+# Test 5: Test "read -C" failure for missing bracket at the beginning
+typeset s
+s=$($SHELL -c 'compound myvar ; print " unfinished=1 )" | read -C myvar 2>'/dev/null' || print "error $?"') || err_exit 'shell failed'
+[[ "$s" == 'error 3' ]] || err_exit "compound_read: expected error 3, got ${s}"
+
+
+# test6: Derived from the test2 for CR #6944386
+# ("compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v prints trash")
+# which caused compound variables to be corrupted like this:
+# -- snip --
+# ksh93 -c 'compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v'
+# (
+# typeset -A -l -i ar=(
+# [aa]=$'\004'
+# [bb]=$'\t'
+# )
+# )
+# -- snip --
+
+function test6
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound val
+ integer testid
+
+ compound -r -a tests=(
+ # subtests1:
+ ( cmd='compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='ar' )
+ ( cmd='compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='ar' )
+
+ # subtests2: Same as subtests1 but variable "v" is inside "vx"
+ ( cmd='compound vx=( compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='v.ar' )
+
+ # subtests3: Same as subtests1 but variable "va" is an indexed array
+ ( cmd='compound vx=( compound -a va=( [3]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3].ar' )
+
+ # subtests4: Same as subtests1 but variable "va" is an 2d indexed array
+ ( cmd='compound vx=( compound -a va=( [3][17]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3][17].ar' )
+
+ # subtests5: Same as subtests1 but variable "va" is an associative array
+ ( cmd='compound vx=( compound -A va=( [l]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[l].ar' )
+ )
+
+ for testid in "${!tests[@]}" ; do
+ nameref test=tests[testid]
+ typeset testname="test2/${testid}"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -c "${test.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ (( out.res == 0 )) || err_exit "${testname}: Test shell returned with exit code ${out.res}"
+ [[ "${out.stdout}" == ${test.stdoutpattern} ]] || err_exit "${testname}: Expected match for ${test.stdoutpattern}, got $(printf "%q\n" "${out.stdout}")"
+ [[ "${out.stderr}" == "" ]] || err_exit "${testname}: Expected empty stderr, got $(printf "%q\n" "${out.stderr}")"
+
+ read -C val <<<"${out.stdout}" || err_exit "${testname}: read -C val failed with exit code $?"
+ nameref ar="val.${test.arrefname}"
+ (( ar[aa] == 4 )) || err_exit "${testname}: Expected ar[aa] == 4, got ${ar[aa]}"
+ (( ar[bb] == 9 )) || err_exit "${testname}: Expected ar[bb] == 9, got ${ar[bb]}"
+ done
+
+ return 0
+}
+
+test6
+
+function test_3D_array_read_C
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+ typeset -r -a tests=(
+ # ast-ksh.2010-03-09 will print "ksh93[1]: read: line 4: 0[0]: invalid variable name" for 3D arrays passed to read -C
+ 'compound c=( typeset -a x ) ; for (( i=0 ; i < 3 ; i++ )) ; do for (( j=0 ; j < 3 ; j++ )) ; do for (( k=0 ; k < 3 ; k++ )) ; do c.x[i][j][k]="$i$j$k" ; done; done; done ; unset c.x[2][0][1] ; print -v c | read -C dummy'
+
+ # same test, 4D, fails with 'ksh[1]: read: line 4: 0: invalid variable name'
+ 'compound c=( typeset -a x ) ; for (( i=0 ; i < 3 ; i++ )) ; do for (( j=0 ; j < 3 ; j++ )) ; do for (( k=0 ; k < 3 ; k++ )) ; do for (( l=0 ; l < 3 ; l++ )) ; do c.x[i][j][k][l]="$i$j$k$l" ; done; done; done ; done ; unset c.x[2][0][1][2] ; print -v c | read -C dummy'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${tests[i]}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == '' ]] || err_exit "$0/${i}: Expected empty stdout, got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "$0/${i}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ done
+
+ return 0
+}
+
+
+function test_access_2Darray_in_type_in_compound
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+ typeset -r -a tests=(
+ # ast-ksh.2010-03-09 will print 'ksh: line 1: l.c.x[i][j]=: no parent'
+ 'typeset -T c_t=(typeset -a x) ; compound l=( c_t c ) ; for ((i=0;i<3;i++));do for ((j=0;j<3;j++));do l.c.x[i][j]="" ; done; done; print -v l | read -C dummy'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${tests[i]}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == '' ]] || err_exit "$0/${i}: Expected empty stdout, got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "$0/${i}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ done
+
+ return 0
+}
+
+function test_read_type_crash
+{
+ compound out=( typeset stdout stderr ; integer res )
+ typeset -r test='
+typeset -T field_t=(
+ typeset -a f
+
+ function reset
+ {
+ integer i j
+
+ for (( i=0 ; i < 3 ; i++ )) ; do
+ for (( j=0 ; j < 3 ; j++ )) ; do
+ _.f[i][j]=""
+ done
+ done
+ return 0
+ }
+
+ function enumerate_empty_fields
+ {
+ integer i j
+
+ for (( i=0 ; i < 3 ; i++ )) ; do
+ for (( j=0 ; j < 3 ; j++ )) ; do
+ [[ "${_.f[i][j]}" == "" ]] && printf "[%d][%d]\n" i j
+ done
+ done
+ return 0
+ }
+
+ function setf
+ {
+ _.f[$1][$2]="$3"
+ }
+)
+
+set -o nounset
+
+compound c1=( field_t x )
+
+c1.x.reset
+
+print -v c1 | read -C c2
+print -v c2
+'
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${test}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" != '' ]] || err_exit "$0: Expected nonempty stdout."
+ [[ "${out.stderr}" == '' ]] || err_exit "$0: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+
+ if [[ -f 'core' && -x '/usr/bin/pstack' ]] ; then
+ pstack 'core'
+ rm 'core'
+ fi
+
+ return 0
+}
+
+
+function test_read_C_into_array
+{
+ compound out=( typeset stdout stderr ; integer res )
+ # fixme:
+ # - The tests should cover 3D and 5D indexed arrays and namerefs to sub-dimensions of a 5D indexed array
+ compound -r -a tests=(
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4][6] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6][9][11][15] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4][6][9][11][15] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+
+ ( cmd=' typeset -A -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd=' typeset -A -C l ; nameref l4=l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4][6] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.l[4][6] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4][6][9][11][15] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.[4][6][9][11][15] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+
+ ( cmd='compound c ; typeset -A -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -A -C c.l ; nameref l4=c.l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ )
+ typeset cmd
+ typeset pat
+ integer i
+
+ compound -a test_variants
+
+ # build list of variations of the tests above
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref tst=tests[i]
+
+ # plain test
+ cmd="${tst.cmd}"
+ test_variants+=( testname="${0}/${i}/plain" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a function
+ cmd="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/{ function rf { nameref val=\$1 \; read -C val \; } \; rf \1 \; } \; }"
+ test_variants+=( testname="${0}/${i}/read_in_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a nested function
+ cmd="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/{ function rf2 { nameref val=\$1 \; read -C val \; } \; function rf { nameref val=\$1 \; rf2 val \; } \; rf \1 \; } \; }"
+ test_variants+=( testname="${0}/${i}/read_in_nested_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a nested function with target variable
+ # being a function-local variable of function "main"
+ cmd='function rf2 { nameref val=$1 ; read -C val ; } ; function rf { nameref val=$1 ; rf2 val ; } ; function main { '
+ cmd+="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/rf \1 \; }"
+ cmd+=' ; } ; main'
+ test_variants+=( testname="${0}/${i}/read_into_localvar_in_nested_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+ done
+
+ # run test variants
+ for (( i=0 ; i < ${#test_variants[@]} ; i++ )) ; do
+ nameref tv=test_variants[i]
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${tv.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ for pat in "${tv.stdoutpattern[@]}" ; do
+ [[ "${out.stdout}" == ${pat} ]] || err_exit "${tv.testname}: Expected stdout of $(printf '%q\n' "${tv.cmd}") to match $(printf '%q\n' "${pat}"), got $(printf '%q\n' "${out.stdout}")"
+ done
+ [[ "${out.stderr}" == '' ]] || err_exit "${tv.testname}: Expected empty stderr for $(printf '%q\n' "${tv.cmd}"), got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${tv.testname}: Unexpected exit code ${out.res} for $(printf '%q\n' "${tv.cmd}")"
+ done
+
+ return 0
+}
+
+
+# This test checks whether reading a compound variable value with
+# "read -C var" which contains special shell keywords or aliases
+# like "functions", "alias", "!" etc. in a string array causes the
+# shell to produce errors like this:
+# -- snip --
+# $ ksh93 -c 'print "( compound -A a1=( [4]=( typeset -a x=( alias ) ) ) ;
+# compound -A a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print -v c' 1>/dev/null
+# ksh93[1]: alias: c.a1[4].x: compound assignment requires sub-variable name
+# -- snip --
+# A 2nd issue indirectly tested here was that simple indexed string array
+# declarations in a function with the same special keywords did not work
+# either.
+# This happened in ast-ksh.2010-11-12 or older.
+function test_read_C_special_shell_keywords
+{
+ typeset -r -a testcmdpatterns=(
+ # this was the original testcase
+ 'print "( compound -A a1=( [4]=( typeset -a x=( %keyword% ) ) ) ; compound -A a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[4].x[0]}X"'
+ # same as above but uses indexed arrays instead of associative arrays
+ 'print "( compound -a a1=( [4]=( typeset -a x=( %keyword% ) ) ) ; compound -a a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[4].x[0]}X"'
+ # same as first testcase but uses a blank in the array index value
+ $'print "( compound -A a1=( [\'hello world\']=( typeset -a x=( %keyword% ) ) ) ; compound -A a2=( [\'hello world\']=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[\'hello world\'].x[0]}X"'
+ )
+ typeset -r -a shell_special_words=(
+ 'alias'
+ 'compound'
+ 'function'
+ 'functions'
+ 'integer'
+ 'local'
+ 'namespace'
+ 'typeset'
+ 'SECONDS'
+ '.sh.version'
+ '!'
+ )
+ integer spwi # shell_special_words index
+ integer tcpi # testcmdpatterns index
+ typeset testcmd
+ typeset testname
+ typeset shkeyword
+ compound out=( typeset stdout stderr ; integer res )
+
+ for (( tcpi=0 ; tcpi < ${#testcmdpatterns[@]} ; tcpi++ )) ; do
+ for (( spwi=0 ; spwi < ${#shell_special_words[@]} ; spwi++ )) ; do
+ shkeyword=${shell_special_words[spwi]}
+ testcmd="${testcmdpatterns[tcpi]//%keyword%/${shkeyword}}"
+ testname="${0}/${tcpi}/${spwi}/"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${testcmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == "X${shkeyword}X" ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "X${shkeyword}X"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+ done
+
+ return 0
+}
+
+
+test_3D_array_read_C
+test_access_2Darray_in_type_in_compound
+test_read_type_crash
+test_read_C_into_array
+test_read_C_special_shell_keywords
+
+
+# tests done
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/coprocess.sh b/src/cmd/ksh93/tests/coprocess.sh
new file mode 100755
index 0000000..749f691
--- /dev/null
+++ b/src/cmd/ksh93/tests/coprocess.sh
@@ -0,0 +1,360 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+# test the behavior of co-processes
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if [[ -d /cygdrive ]]
+then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system
+ exit $((Errors))
+fi
+
+bintrue=$(whence -p true)
+
+function ping # id
+{
+ integer x=0
+ while ((x++ < 5))
+ do read -r
+ print -r "$1 $REPLY"
+ done
+}
+
+cat |&
+print -p "hello"
+read -p line
+[[ $line == hello ]] || err_exit 'coprocessing fails'
+exec 5>&p 6<&p
+print -u5 'hello again' || err_exit 'write on u5 fails'
+read -u6 line
+[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails'
+exec 5<&- 6<&-
+wait $!
+
+ping three |&
+exec 3>&p
+ping four |&
+exec 4>&p
+ping pipe |&
+
+integer count
+for i in three four pipe four pipe four three pipe pipe three pipe
+do case $i in
+ three) to=-u3;;
+ four) to=-u4;;
+ pipe) to=-p;;
+ esac
+ (( count++ ))
+ print $to $i $count
+done
+
+while ((count > 0))
+do (( count-- ))
+ read -p
+ set -- $REPLY
+ if [[ $1 != $2 ]]
+ then err_exit "$1 does not match $2"
+ fi
+ case $1 in
+ three) ;;
+ four) ;;
+ pipe) ;;
+ *) err_exit "unknown message +|$REPLY|+" ;;
+ esac
+done
+kill $(jobs -p) 2>/dev/null
+
+file=$tmp/regress
+cat > $file <<\!
+/bin/cat |&
+!
+chmod +x $file
+sleep 10 |&
+$file 2> /dev/null || err_exit "parent coprocess prevents script coprocess"
+exec 5<&p 6>&p
+exec 5<&- 6>&-
+kill $(jobs -p) 2>/dev/null
+
+${SHELL-ksh} |&
+cop=$!
+exp=Done
+print -p $'print hello | cat\nprint '$exp
+read -t 5 -p
+read -t 5 -p
+got=$REPLY
+if [[ $got != $exp ]]
+then err_exit "${SHELL-ksh} coprocess io failed -- got '$got', expected '$exp'"
+fi
+exec 5<&p 6>&p
+exec 5<&- 6>&-
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "coprocess hung after 'exec 5<&p 6>&p; exec 5<&- 6>&-'"
+fi
+wait
+
+{
+echo line1 | grep 'line2'
+echo line2 | grep 'line1'
+} |&
+SECONDS=0 count=0
+while read -p -t 10 line
+do ((count++))
+done
+if (( SECONDS > 8 ))
+then err_exit "read -p hanging (SECONDS=$SECONDS count=$count)"
+fi
+wait $!
+
+( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) ||
+ err_exit "coprocess cleanup not working correctly"
+{ : |& } 2>/dev/null ||
+ err_exit "subshell coprocess lingers in parent"
+wait $!
+
+unset N r e
+integer N=5
+e=12345
+(
+ integer i
+ for ((i = 1; i <= N; i++))
+ do print $i |&
+ read -p r
+ print -n $r
+ wait $!
+ done
+ print
+) 2>/dev/null | read -t 10 r
+[[ $r == $e ]] || err_exit "coprocess timing bug -- expected $e, got '$r'"
+r=
+(
+ integer i
+ for ((i = 1; i <= N; i++))
+ do print $i |&
+ sleep 0.01
+ r=$r$(cat <&p)
+ wait $!
+ done
+ print $r
+) 2>/dev/null | read -t 10 r
+[[ $r == $e ]] || err_exit "coprocess command substitution bug -- expected $e, got '$r'"
+
+(
+ /bin/cat |&
+ sleep 0.01
+ exec 6>&p
+ print -u6 ok
+ exec 6>&-
+ sleep 2
+ kill $! 2> /dev/null
+) && err_exit 'coprocess with subshell would hang'
+for sig in IOT ABRT
+do if ( trap - $sig ) 2> /dev/null
+ then if [[ $( { sig=$sig $SHELL 2> /dev/null <<- '++EOF++'
+ cat |&
+ pid=$!
+ trap "print TRAP" $sig
+ (
+ sleep 2
+ kill -$sig $$
+ sleep 2
+ kill -$sig $$
+ kill $pid
+ sleep 2
+ kill $$
+ ) &
+ while read -p || (($? > 256))
+ do :
+ done
+ ++EOF++
+ } ) != $'TRAP\nTRAP' ]] 2> /dev/null
+ then err_exit 'traps when reading from coprocess not working'
+ fi
+ break
+ fi
+done
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 1 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+builtin cat
+cat |&
+pid=$!
+exec 5<&p 6>&p
+exp=hi
+print -u6 $exp; read -u5
+[[ $REPLY == "$exp" ]] || err_exit "REPLY failed -- expected '$exp', got '$REPLY'"
+exec 6>&-
+wait $pid
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+cat |&
+pid=$!
+print foo >&p 2> /dev/null || err_exit 'first write of foo to coprocess failed'
+print foo >&p 2> /dev/null || err_exit 'second write of foo to coprocess failed'
+kill $pid
+wait $pid 2> /dev/null
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+cat |&
+pid=$!
+print -p foo
+print -p bar
+read <&p || err_exit 'first read from coprocess failed'
+[[ $REPLY == foo ]] || err_exit "first REPLY is $REPLY not foo"
+read <&p || err_exit 'second read from coprocess failed'
+[[ $REPLY == bar ]] || err_exit "second REPLY is $REPLY not bar"
+kill $pid
+wait $pid 2> /dev/null
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+exp=ksh
+got=$(print -r $'#00315
+COATTRIBUTES=\'label=make \'
+# @(#)$Id: libcoshell (AT&T Research) 2008-04-28 $
+_COSHELL_msgfd=5
+{ { (eval \'function fun { trap \":\" 0; return 1; }; trap \"exit 0\" 0; fun; exit 1\') && PATH= print -u$_COSHELL_msgfd ksh; } || { times && echo bsh >&$_COSHELL_msgfd; } || { echo osh >&$_COSHELL_msgfd; }; } >/dev/null 2>&1' | $SHELL 5>&1)
+[[ $got == $exp ]] || err_exit "coshell(3) identification sequence failed -- expected '$exp', got '$got'"
+
+function cop
+{
+ read
+ print ok
+}
+
+exp=ok
+
+cop |&
+pid=$!
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+cop |&
+pid=$!
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
+)
+kill $pid 2>/dev/null
+wait
+
+exp='no coprocess'
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess subshell query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+)
+
+function mypipe
+{
+ read; read
+ print -r -- "$REPLY"
+}
+
+mypipe |&
+print -p "hello"
+z="$( $bintrue $($bintrue) )"
+{ print -p "world";} 2> /dev/null
+read -p
+[[ $REPLY == world ]] || err_exit "expected 'world' got '$REPLY'"
+kill $pid 2>/dev/null
+wait
+
+
+function cop
+{
+ read
+ print ok
+}
+exp=ok
+cop |&
+pid=$!
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
+)
+kill $pid 2>/dev/null
+wait
+
+tee=$(whence -p tee)
+ls -l |&
+pid=$!
+$tee -a /dev/null <&p > /dev/null
+wait $pid
+x=$?
+[[ $x == 0 ]] || err_exit "coprocess exitval should be 0, not $x"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/cubetype.sh b/src/cmd/ksh93/tests/cubetype.sh
new file mode 100755
index 0000000..dbe4e8b
--- /dev/null
+++ b/src/cmd/ksh93/tests/cubetype.sh
@@ -0,0 +1,213 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+integer n=2
+
+typeset -T Box_t=(
+ float -h 'height in inches' x=2
+ float -h 'width in inches' y=4
+ comvar=(top=8 bottom=9)
+ integer -S count=0
+ items=(foo bar)
+ colors=([wall]=blue [floor]=red)
+ typeset name=unknown
+ typeset -L6 status=INIT
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ (( _.count++))
+ }
+ typeset -fh 'distance from the origin' len
+ depth()
+ {
+ print 0
+ }
+ float x=3
+)
+
+for ((i=0; i < n; i++))
+do
+Box_t b=(name=box1)
+exp=3 got=${b.x}
+[[ "$got" == "$exp" ]] || err_exit "\${b.x} incorrect for iteration $i -- expected $exp, got '$got'"
+exp=5 got=$(( b.len ))
+(( got == exp )) || err_exit "b.len incorrect for iteration $i -- expected $exp, got '$got = sqrt(${b.x}*${b.x}+${b.y}*${b.y})'"
+exp=5 got=${b.len}
+[[ "$got" == "$exp" ]] || err_exit "\${b.len} incorrect for iteration $i -- expected $exp, got '$got = sqrt(${b.x}*${b.x}+${b.y}*${b.y})'"
+exp=box1 got=${b.name}
+[[ "$got" == "${exp}" ]] || err_exit "\${b.name} incorrect for iteration $i -- expected $exp, got '$got'"
+exp=2 got=$(( b.count ))
+(( got == exp )) || err_exit "b.count incorrect for iteration $i -- expected $exp, got '$got'"
+exp=2 got=${b.count}
+[[ "$got" == "$exp" ]] || err_exit "\${b.ccount} incorrect for iteration $i -- expected $exp, got '$got'"
+b.colors[wall]=green
+b.colors[door]=white
+exp=3 got=${#b.colors[@]}
+[[ "$got" == "$exp" ]] || err_exit "\${#b.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+b.comvar.bottom=11
+b.items[1]=bam
+b.items[2]=extra
+exp=3 got=${#b.items[@]}
+[[ ${#b.items[@]} == 3 ]] || err_exit "\${#b.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+Box_t bb=b
+bb.colors[desk]=orange
+exp=4 got=${#b.colors[@]}
+[[ ${#bb.colors[@]} == 4 ]] || err_exit "\${#bb.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset b.colors
+exp=2 got=${#b.colors[@]}
+[[ ${#b.colors[@]} == 2 ]] || err_exit "\${#b.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset b.items
+exp=2 got=${#b.items[@]}
+[[ ${#b.items[@]} == 2 ]] || err_exit "\${#b.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset bb.colors
+exp=2 got=${#bb.colors[@]}
+[[ ${#bb.colors[@]} == 2 ]] || err_exit "\${#bb.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset bb.items
+exp=2 got=${#bb.items[@]}
+[[ ${#bb.items[@]} == 2 ]] || err_exit "\${#bb.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+[[ $b == "$bb" ]] || err_exit "\$b='$b' != \$bb='$bb'"
+b.count=0
+unset b bb
+done
+
+typeset -T Cube_t=(
+ Box_t _=(y=5)
+ float z=1
+ depth()
+ {
+ print -r -- $((_.z))
+ }
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ (( _.count++))
+ }
+ float x=8
+ fun()
+ {
+ print 'hello world'
+ }
+)
+
+
+for ((i=0; i < n; i++))
+do
+Box_t b=(name=box2)
+[[ ${b.name} == box2 ]] || err_exit "\${b.name} incorrect -- expected box2, got '${b.name}'"
+(( b.len == 5 )) || err_exit "b.len incorrect for box2 -- expected 5, got '$(( b.len ))'"
+(( b.count == 1 )) || err_exit "b.count incorrect -- expected 1, got '$(( b.count ))'"
+Cube_t c=(name=cube1)
+[[ $c == $'(\n\ttypeset -l -E x=8\n\ttypeset -l -E y=5\n\tcomvar=(\n\t\ttop=8\n\t\tbottom=9\n\t)\n\ttypeset -S -l -i count=1\n\ttypeset -a items=(\n\t\tfoo\n\t\tbar\n\t)\n\ttypeset -A colors=(\n\t\t[floor]=red\n\t\t[wall]=blue\n\t)\n\tname=cube1\n\ttypeset -L 6 status=INIT\n\ttypeset -l -E z=1\n)' ]] || err_exit '$c not correct'
+[[ ${c.x} == 8 ]] || err_exit '${c.x} != 8'
+[[ ${c.depth} == 1 ]] || err_exit '${c.depth} != 1'
+[[ ${c.name} == cube1 ]] || err_exit '${c.name} != cube1 '
+[[ $(c.fun) == 'hello world' ]] || err_exit '$(c.fun) != "hello world"'
+[[ ${c.fun} == 'hello world' ]] || err_exit '${c.fun} != "hello world"'
+(( abs(c.len - sqrt(90)) < 1e-10 )) || err_exit 'c.len != sqrt(90)'
+(( c.count == 2 )) || err_exit 'c.count != 2'
+(( c.count == b.count )) || err_exit 'c.count != b.count'
+c.count=0
+Cube_t d=c
+[[ $d == "$c" ]] || err_exit '$d != $c'
+eval "Cube_t zzz=$c"
+[[ $zzz == "$c" ]] || err_exit '$zzz != $c'
+Cube_t zzz=c
+[[ $zzz == "$c" ]] || err_exit '$zzz != $c without eval'
+xxx=$(typeset -p c)
+eval "${xxx/c=/ccc=}"
+[[ $ccc == "$c" ]] || err_exit '$ccc != $c'
+unset b c d zzz xxx ccc
+done
+for ((i=0; i < n; i++))
+do
+Cube_t cc
+cc[2]=(x=2 y=3 name=two colors+=([table]=white) items+=(pencil) z=6)
+[[ ${cc[0].x} == 8 ]] || err_exit 'cc[0].x !=8'
+[[ ${cc[2].y} == 3 ]] || err_exit '${cc[2].y} != 3'
+(( cc[2].y == 3 )) || err_exit '(( cc[2].y != 3))'
+[[ ${cc[2].colors[table]} == white ]] || err_exit '${cc[2].colors[table]} != white'
+[[ ${cc[2].items[2]} == pencil ]] || err_exit '${cc[2].items[2]} != pencil'
+(( cc[2].len == 7 )) || err_exit '(( cc[2].len != 7 ))'
+[[ $(cc[2].len) == 7 ]] || err_exit '$(cc[2].len) != 7 ))'
+[[ ${cc[2].len} == 7 ]] || err_exit '${cc[2].len} != 7 ))'
+(( cc[2].count == 2 )) || err_exit 'cc[2].count != 2'
+unset cc[2].x cc[2].y cc[2].z
+(( cc[2].len == cc[0].len )) || err_exit 'cc[2].len != cc[0].len'
+(( cc[2].len == cc.len )) || err_exit 'cc[2].len != cc.len'
+(( cc[2].count == 6 )) || err_exit 'cc[2].count != 6'
+unset cc[2].name cc[2].colors cc[2].items
+[[ $cc == "${cc[2]}" ]] || err_exit '$cc != ${cc[2]}'
+cc.count=0
+unset cc
+Cube_t -A cc
+cc[two]=(x=2 y=3 name=two colors+=([table]=white) items+=(pencil) z=6)
+Cube_t cc[one]
+[[ ${#cc[@]} == 2 ]] || err_exit '${#cc[@]} != 2'
+[[ ${cc[two].y} == 3 ]] || err_exit '${cc[two].y} != 3'
+(( cc[two].y == 3 )) || err_exit '(( cc[two].y != 3))'
+[[ ${cc[two].colors[table]} == white ]] || err_exit '${cc[two].colors[table]} != white'
+[[ ${cc[two].items[2]} == pencil ]] || err_exit '${cc[two].items[2]} != pencil'
+(( cc[two].len == 7 )) || err_exit '(( cc[two].len != 7 ))'
+[[ $(cc[two].len) == 7 ]] || err_exit '$(cc[two].len) != 7 ))'
+[[ ${cc[two].len} == 7 ]] || err_exit '${cc[two].len} != 7 ))'
+(( cc[two].count == 2 )) || err_exit 'cc[two].count != 2'
+unset cc[two].x cc[two].y cc[two].z
+(( cc[two].len == cc[one].len )) || err_exit 'cc[two].len != cc[one].len'
+(( cc[two].count == 4 )) || err_exit 'cc[two].count != 4'
+unset cc[two].name unset cc[two].colors cc[two].items
+[[ ${cc[one]} == "${cc[two]}" ]] || err_exit '${cc[one]} != ${cc[two]}'
+cc[two].count=0
+unset cc
+Cube_t cc=(
+ [one]=
+ [two]=(x=2 y=3 name=two colors+=([table]=white) z=6)
+)
+[[ ${#cc[@]} == 2 ]] || err_exit '${#cc[@]} != 2'
+[[ ${cc[two].y} == 3 ]] || err_exit '${cc[two].y} != 3'
+(( cc[two].y == 3 )) || err_exit '(( cc[two].y != 3))'
+[[ ${cc[two].colors[table]} == white ]] || err_exit '${cc[two].colors[table]} != white'
+(( cc[two].len == 7 )) || err_exit '(( cc[two].len != 7 ))'
+[[ $(cc[two].len) == 7 ]] || err_exit '$(cc[two].len) != 7 ))'
+[[ ${cc[two].len} == 7 ]] || err_exit '${cc[two].len} != 7 ))'
+(( cc[two].count == 2 )) || err_exit 'cc[two].count != 2'
+unset cc[two].x cc[two].y cc[two].z
+(( cc[two].len == cc[one].len )) || err_exit 'cc[two].len != cc[one].len'
+(( cc[two].count == 4 )) || err_exit 'cc[two].count != 4'
+cc[three]=cc[two]
+[[ ${cc[two]} == "${cc[three]}" ]] || err_exit "\${cc[two]}='${cc[two]}' != \${cc[three]}='${cc[three]}'"
+[[ $cc[two] == "${cc[three]}" ]] || err_exit "\$cc[two]='${cc[two]}' != \${cc[three]}='${cc[three]}'"
+exp=3
+got=${#cc[@]}
+[[ $got == $exp ]] || err_exit "\${#cc[@]} failed -- expected '$exp', got '$got'"
+unset cc[two].name unset cc[two].colors
+cc[two].count=0
+unset cc
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/enum.sh b/src/cmd/ksh93/tests/enum.sh
new file mode 100755
index 0000000..134a0a3
--- /dev/null
+++ b/src/cmd/ksh93/tests/enum.sh
@@ -0,0 +1,68 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+enum Color_t=(red green blue orange yellow)
+enum -i Sex_t=(Male Female)
+for ((i=0; i < 1000; i++))
+do
+Color_t x
+[[ $x == red ]] || err_exit 'Color_t does not default to red'
+x=orange
+[[ $x == orange ]] || err_exit '$x should be orange'
+( x=violet) 2> /dev/null && err_exit 'x=violet should fail'
+x[2]=green
+[[ ${x[2]} == green ]] || err_exit '${x[2]} should be green'
+(( x[2] == 1 )) || err_exit '((x[2]!=1))'
+[[ $((x[2])) == 1 ]] || err_exit '$((x[2]))!=1'
+[[ $x == orange ]] || err_exit '$x is no longer orange'
+Color_t -A y
+y[foo]=yellow
+[[ ${y[foo]} == yellow ]] || err_exit '${y[foo]} != yellow'
+(( y[foo] == 4 )) || err_exit '(( y[foo] != 4))'
+unset y
+typeset -a [Color_t] z
+z[green]=xyz
+[[ ${z[green]} == xyz ]] || err_exit '${z[green]} should be xyz'
+[[ ${z[1]} == xyz ]] || err_exit '${z[1]} should be xyz'
+z[orange]=bam
+[[ ${!z[@]} == 'green orange' ]] || err_exit '${!z[@]} == "green orange"'
+unset x
+Sex_t x
+[[ $x == Male ]] || err_exit 'Sex_t not defaulting to Male'
+x=female
+[[ $x == Female ]] || err_exit 'Sex_t not case sensitive'
+unset x y z
+done
+(
+typeset -T X_t=( typeset name=aha )
+typeset -a[X_t] arr
+) 2> /dev/null
+[[ $? == 1 ]] || err_exit 'typeset -a[X_t] should generate an error message when X-t is not an enumeriation type'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/exit.sh b/src/cmd/ksh93/tests/exit.sh
new file mode 100755
index 0000000..d2b91b7
--- /dev/null
+++ b/src/cmd/ksh93/tests/exit.sh
@@ -0,0 +1,80 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function abspath
+{
+ base=$(basename $SHELL)
+ cd ${SHELL%/$base}
+ newdir=$(pwd)
+ cd ~-
+ print $newdir/$base
+}
+#test for proper exit of shell
+builtin getconf
+ABSHELL=$(abspath)
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+print exit 0 >.profile
+${ABSHELL} <<!
+HOME=$PWD \
+PATH=$PATH \
+SHELL=$ABSSHELL \
+$(
+ v=$(getconf LIBPATH)
+ for v in ${v//,/ }
+ do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && eval print -n \" \"\$v=\"\$$v\"
+ done
+) \
+exec -c -a -ksh ${ABSHELL} -c "exit 1" 1>/dev/null 2>&1
+!
+status=$(echo $?)
+if [[ -o noprivileged && $status != 0 ]]
+then err_exit 'exit in .profile is ignored'
+elif [[ -o privileged && $status == 0 ]]
+then err_exit 'privileged .profile not ignored'
+fi
+if [[ $(trap 'code=$?; echo $code; trap 0; exit $code' 0; exit 123) != 123 ]]
+then err_exit 'exit not setting $?'
+fi
+cat > run.sh <<- "EOF"
+ trap 'code=$?; echo $code; trap 0; exit $code' 0
+ ( trap 0; exit 123 )
+EOF
+if [[ $($SHELL ./run.sh) != 123 ]]
+then err_exit 'subshell trap on exit overwrites parent trap'
+fi
+cd ~- || err_exit "cd back failed"
+$SHELL -c 'builtin -f cmd getconf; getconf --"?-version"; exit 0' >/dev/null 2>&1 || err_exit 'ksh plugin exit failed -- was ksh built with CCFLAGS+=$(CC.EXPORT.DYNAMIC)?'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/expand.sh b/src/cmd/ksh93/tests/expand.sh
new file mode 100755
index 0000000..2547be8
--- /dev/null
+++ b/src/cmd/ksh93/tests/expand.sh
@@ -0,0 +1,126 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$Line]: "$@"
+ ((Errors++))
+}
+
+integer Errors=0
+Command=${0##*/}
+
+# {...} expansion tests -- ignore if not supported
+
+[[ $(print a{0,1}z) == "a0z a1z" ]] || exit 0
+
+integer Line=$LINENO+1
+set -- \
+ 'ff{c,b,a}' 'ffc ffb ffa' \
+ 'f{d,e,f}g' 'fdg feg ffg' \
+ '{l,n,m}xyz' 'lxyz nxyz mxyz' \
+ '{abc\,def}' '{abc,def}' \
+ '{"abc,def"}' '{abc,def}' \
+ "{'abc,def'}" '{abc,def}' \
+ '{abc}' '{abc}' \
+ '\{a,b,c,d,e}' '{a,b,c,d,e}' \
+ '{x,y,\{a,b,c}}' 'x} y} {a} b} c}' \
+ '{x\,y,\{abc\},trie}' 'x,y {abc} trie' \
+ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}' '/usr/ucb/ex /usr/ucb/edit /usr/lib/ex /usr/lib/how_ex' \
+ 'XXXX\{a,b,c\}' 'XXXX{a,b,c}' \
+ '{}' '{}' \
+ '{ }' '{ }' \
+ '}' '}' \
+ '{' '{' \
+ 'abcd{efgh' 'abcd{efgh' \
+ 'foo {1,2} bar' 'foo 1 2 bar' \
+ '`print -r -- foo {1,2} bar`' 'foo 1 2 bar' \
+ '$(print -r -- foo {1,2} bar)' 'foo 1 2 bar' \
+ '{1..10}' '1 2 3 4 5 6 7 8 9 10' \
+ '{0..10,braces}' '0..10 braces' \
+ '{{0..10},braces}' '0 1 2 3 4 5 6 7 8 9 10 braces' \
+ 'x{{0..10},braces}y' 'x0y x1y x2y x3y x4y x5y x6y x7y x8y x9y x10y xbracesy' \
+ '{3..3}' '3' \
+ 'x{3..3}y' 'x3y' \
+ '{10..1}' '10 9 8 7 6 5 4 3 2 1' \
+ '{10..1}y' '10y 9y 8y 7y 6y 5y 4y 3y 2y 1y' \
+ 'x{10..1}y' 'x10y x9y x8y x7y x6y x5y x4y x3y x2y x1y' \
+ '{a..f}' 'a b c d e f' \
+ '{f..a}' 'f e d c b a' \
+ '{a..A}' '{a..A}' \
+ '{A..a}' '{A..a}' \
+ '{f..f}' 'f' \
+ '{1..f}' '{1..f}' \
+ '{f..1}' '{f..1}' \
+ '0{1..9} {10..20}' '01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20' \
+ '{-1..-10}' '-1 -2 -3 -4 -5 -6 -7 -8 -9 -10' \
+ '{-19..0}' '-19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0' \
+ '{0..10}' '0 1 2 3 4 5 6 7 8 9 10' \
+ '{0..10..1}' '0 1 2 3 4 5 6 7 8 9 10' \
+ '{0..10..2}' '0 2 4 6 8 10' \
+ '{0..10..3}' '0 3 6 9' \
+ '{0..10..0}' '{0..10..0}' \
+ '{0..10..-1}' '0' \
+ '{10..0}' '10 9 8 7 6 5 4 3 2 1 0' \
+ '{10..0..-1}' '10 9 8 7 6 5 4 3 2 1 0' \
+ '{10..0..-2}' '10 8 6 4 2 0' \
+ '{10..0..-3}' '10 7 4 1' \
+ '{10..0..0}' '{10..0..0}' \
+ '{10..0..1}' '10' \
+ '{a..z..2}' 'a c e g i k m o q s u w y' \
+ '{y..b..-3}' 'y v s p m j g d' \
+ '{0..0x1000..0x200}' '0 512 1024 1536 2048 2560 3072 3584 4096' \
+ '{a,b}{0..2}{z,y}' 'a0z a0y a1z a1y a2z a2y b0z b0y b1z b1y b2z b2y' \
+ '{0..0100..8%03o}' '000 010 020 030 040 050 060 070 100' \
+ '{0..0100..040%020o}' '00000000000000000000 00000000000000000040 00000000000000000100' \
+ '{0..7%03..2u}' '000 001 010 011 100 101 110 111' \
+ '{0..10%llu}' '{0..10%llu}' \
+ '{0..10%s}' '{0..10%s}' \
+ '{0..10%dl}' '{0..10%dl}' \
+ '{a,b}{0..3%02..2u}{y,z}' 'a00y a00z a01y a01z a10y a10z a11y a11z b00y b00z b01y b01z b10y b10z b11y b11z' \
+
+while (($#>1))
+do ((Line++))
+ pattern=$1
+ shift
+ expected=$1
+ shift
+ got=$(eval print -r -- "$pattern")
+ [[ $got == $expected ]] || err_exit "'$pattern' failed -- expected '$expected' got '$got'"
+ #print -r -- " '$pattern' '$got' \\"
+done
+
+# ~(N) no expand glob pattern option
+set -- ~(N)/dev/null
+[[ $# == 1 && $1 == /dev/null ]] || err_exit "~(N)/dev/null not matching /dev/null"
+set -- ~(N)/dev/non_existant_file
+[[ $# == 0 ]] || err_exit "~(N)/dev/nonexistant not empty"
+set -- ""~(N)/dev/non_existant_file
+[[ $# == 1 && ! $1 ]] || err_exit '""~(N)/dev/nonexistant not null argument'
+set -- ~(N)/dev/non_existant_file""
+[[ $# == 1 && ! $1 ]] || err_exit '~(N)/dev/nonexistent"" not null argument'
+for i in ~(N)/dev/non_existent_file
+do err_exit "~(N)/dev/non_existent_file in for loop is $i"
+done
+for i in ""~(N)/dev/non_existent_file
+do [[ ! $i ]] || err_exit '""~(N)/dev/non_existent_file not null'
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/functions.sh b/src/cmd/ksh93/tests/functions.sh
new file mode 100755
index 0000000..fcf3755
--- /dev/null
+++ b/src/cmd/ksh93/tests/functions.sh
@@ -0,0 +1,1157 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+Command=${0##*/}
+
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+integer foo=33
+bar=bye
+# check for global variables and $0
+function foobar
+{
+ case $1 in
+ 1) print -r - "$foo" "$bar";;
+ 2) print -r - "$0";;
+ 3) typeset foo=foo
+ integer bar=10
+ print -r - "$foo" "$bar";;
+ 4) trap 'foo=36' EXIT
+ typeset foo=20;;
+ esac
+}
+function print
+{
+ command print hi
+}
+if [[ $(print) != hi ]]
+then err_exit "command print not working inside print function"
+fi
+unset -f print
+
+if [[ $(foobar 1) != '33 bye' ]]
+then err_exit 'global variables not correct'
+fi
+
+if [[ $(foobar 2) != 'foobar' ]]
+then err_exit '$0 not correct'
+fi
+
+if [[ $(bar=foo foobar 1) != '33 foo' ]]
+then err_exit 'environment override not correct'
+fi
+if [[ $bar == foo ]]
+then err_exit 'scoping error'
+fi
+
+if [[ $(foobar 3) != 'foo 10' ]]
+then err_exit non-local variables
+fi
+
+foobar 4
+if [[ $foo != 36 ]]
+then err_exit EXIT trap in wrong scope
+fi
+unset -f foobar || err_exit "cannot unset function foobar"
+typeset -f foobar>/dev/null && err_exit "typeset -f has incorrect exit status"
+
+function foobar
+{
+ (return 0)
+}
+> $tmp/test1
+{
+foobar
+if [ -r $tmp/test1 ]
+then rm -r $tmp/test1
+else err_exit 'return within subshell inside function error'
+fi
+}
+abc() print hi
+if [[ $(abc) != hi ]]
+then err_exit 'abc() print hi not working'
+fi
+( unset -f abc )
+if [[ $(abc 2>/dev/null) != hi ]]
+then err_exit 'abc() print hi not working after subshell unset'
+fi
+(
+ function f
+ {
+ exit 1
+ }
+ f
+ err_exit 'exit from function not working'
+)
+unset -f foo
+function foo
+{
+ x=2
+ (
+ x=3
+ cd $tmp
+ print bar
+ )
+ if [[ $x != 2 ]]
+ then err_exit 'value of x not restored after subshell inside function'
+ fi
+}
+x=1
+dir=$PWD
+if [[ $(foo) != bar ]]
+then err_exit 'cd inside nested subshell not working'
+fi
+if [[ $PWD != "$dir" ]]
+then err_exit 'cd inside nested subshell changes $PWD'
+fi
+fun() /bin/echo hello
+if [[ $(fun) != hello ]]
+then err_exit one line functions not working
+fi
+cat > $tmp/script <<-\!
+ print -r -- "$1"
+!
+chmod +x $tmp/script
+function passargs
+{
+ $tmp/script "$@"
+}
+if [[ $(passargs one) != one ]]
+then err_exit 'passing args from functions to scripts not working'
+fi
+cat > $tmp/script <<-\!
+ trap 'exit 0' EXIT
+ function foo
+ {
+ /tmp > /dev/null 2>&1
+ }
+ foo
+!
+if ! $tmp/script
+then err_exit 'exit trap incorrectly triggered'
+fi
+if ! $SHELL -c $tmp/script
+then err_exit 'exit trap incorrectly triggered when invoked with -c'
+fi
+$SHELL -c "trap 'rm $tmp/script' EXIT"
+if [[ -f $tmp/script ]]
+then err_exit 'exit trap not triggered when invoked with -c'
+fi
+cat > $tmp/script <<- \EOF
+ foobar()
+ {
+ return
+ }
+ shift
+ foobar
+ print -r -- "$1"
+EOF
+chmod +x $tmp/script
+if [[ $( $SHELL $tmp/script arg1 arg2) != arg2 ]]
+then err_exit 'arguments not restored by posix functions'
+fi
+function foo
+{
+ print hello
+}
+(
+ function foo
+ {
+ print bar
+ }
+ if [[ $(foo) != bar ]]
+ then err_exit 'function definitions inside subshells not working'
+ fi
+)
+if [[ $(foo) != hello ]]
+then err_exit 'function definitions inside subshells not restored'
+fi
+unset -f foo bar
+function bar
+{
+ print "$y"
+}
+
+function foo
+{
+ typeset x=3
+ y=$x bar
+}
+x=1
+if [[ $(foo) != 3 ]]
+then err_exit 'variable assignment list not using parent scope'
+fi
+unset -f foobar
+cat > $tmp/foobar <<!
+function foobar
+{
+ print foo
+}
+!
+chmod +x $tmp/foobar
+FPATH=$tmp
+autoload foobar
+if [[ $(foobar 2>/dev/null) != foo ]]
+then err_exit 'autoload not working'
+fi
+unset -f foobar
+function foobar
+{
+ typeset -r x=3
+ return 0
+}
+( foobar ) 2> /dev/null || err_exit "cannot unset readonly variable in function"
+if $SHELL -n 2> /dev/null <<-!
+ abc()
+ !
+then err_exit 'abc() without a function body is not a syntax error'
+fi
+function winpath
+{
+ usage='q pathname ...'
+ typeset var format=s
+ while getopts "$usage" var
+ do case $var in
+ q) format=q;;
+ esac
+ done
+ print done
+}
+if [[ $( (winpath --man 2>/dev/null); print ok) != ok ]]
+then err_exit 'getopts --man in functions not working'
+fi
+if [[ $( (winpath -z 2>/dev/null); print ok) != ok ]]
+then err_exit 'getopts with bad option in functions not working'
+fi
+unset -f x
+function x
+{
+ print "$@"
+}
+typeset -ft x
+if [[ $(x x=y 2>/dev/null) != x=y ]]
+then err_exit 'name=value pair args not passed to traced functions'
+fi
+function bad
+{
+ false
+}
+trap 'val=false' ERR
+val=true
+bad
+if [[ $val != false ]]
+then err_exit 'set -e not working for functions'
+fi
+function bad
+{
+ false
+ return 0
+}
+val=true
+bad
+if [[ $val != true ]]
+then err_exit 'set -e not disabled for functions'
+fi
+bad()
+{
+ false
+ return 0
+}
+val=true
+bad
+if [[ $val != false ]]
+then err_exit 'set -e not inherited for posix functions'
+fi
+trap - ERR
+
+function myexport
+{
+ nameref var=$1
+ if (( $# > 1 ))
+ then export $1=$2
+ fi
+ if (( $# > 2 ))
+ then print $(myexport "$1" "$3" )
+ return
+ fi
+ typeset val
+ val=$(export | grep "^$1=")
+ print ${val#"$1="}
+}
+export dgk=base
+val=$(myexport dgk fun)
+if [[ $val != fun ]]
+then err_exit "export inside function not working -- expected 'fun', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored after function call -- expected 'base', got '$val'"
+fi
+val=$(myexport dgk fun fun2)
+if [[ $val != fun2 ]]
+then err_exit "export inside function not working with recursive function -- expected 'fun2', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored after recursive function call -- expected 'base', got '$val'"
+fi
+val=$(dgk=try3 myexport dgk)
+if [[ $val != try3 ]]
+then err_exit "name=value not added to export list with function call -- expected 'try3', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored name=value function call -- expected 'base', got '$val'"
+fi
+unset zzz
+val=$(myexport zzz fun)
+if [[ $val != fun ]]
+then err_exit "export inside function not working -- expected 'fun', got '$val'"
+fi
+val=$(export | sed -e '/^zzz=/!d' -e 's/^zzz=//')
+if [[ $val ]]
+then err_exit "unset varaible exported after function call -- expected '', got '$val'"
+fi
+
+unset zzz
+typeset -u zzz
+function foo
+{
+ zzz=abc
+ print $zzz
+}
+if [[ $(foo)$(foo) != ABCABC ]]
+then err_exit 'attributes on unset variables not saved/restored'
+fi
+function xpd {
+ typeset i j=$1
+ for i
+ do print i=$i j=$j
+ [[ $i == a ]] && xpd b
+ done
+ }
+if [[ $(xpd a c) != $'i=a j=a\ni=b j=b\ni=c j=a' ]]
+then err_exit 'for loop function optimization error'
+fi
+
+typeset -A visited
+integer level=0
+function closure
+{
+ (( $# > 5 )) && return 1
+ ((level < 2)) && ((level++))
+ typeset tmp r=0
+ visited[$1]=1
+
+ for tmp in $level _$level
+ do
+ [[ ${visited[$tmp]} == 1 ]] && continue
+ closure $tmp $* || r=1
+ done
+ return $r
+}
+closure 0 || err_exit -u2 'for loop function optimization bug2'
+dir=$tmp/dir
+mkdir $dir
+cd $dir || { err_exit "cd $dir failed"; exit 1; }
+
+(
+ function a {
+ print a
+ }
+ function b {
+ print 1
+ a
+ print 2
+ } > /dev/null
+ typeset -ft a b
+ PS4=X
+ b
+) > file 2>&1
+[[ $(<file) == *'Xprint 2'* ]] || err_exit 'function trace disabled by function call'
+rm -f file
+
+print 'false' > try
+chmod +x try
+cat > tst <<- EOF
+ function ignore
+ {
+ ./try
+ return 0
+ }
+ trap "print error; exit 1" ERR
+ ignore
+EOF
+if [[ $($SHELL < tst) == error ]]
+then err_exit 'ERR trap not cleared'
+fi
+FPATH=$dir
+print ': This does nothing' > foobar
+chmod +x foobar
+unset -f foobar
+{ foobar; } 2>/dev/null
+got=$?
+exp=126
+if [[ $got != $exp ]]
+then err_exit "function file without function definition processes wrong error -- expected '$exp', got '$got'"
+fi
+print 'set a b c' > dotscript
+[[ $(PATH=$PATH: $SHELL -c '. dotscript;print $#') == 3 ]] || err_exit 'positional parameters not preserved with . script without arguments'
+cd ~- || err_exit "cd back failed"
+function errcheck
+{
+ trap 'print ERR; return 1' ERR
+ false
+ print ok
+}
+err=$(errcheck)
+[[ $err == ERR ]] || err_exit 'trap on ERR not working in a function'
+x="$(
+ function foobar
+ {
+ print ok
+ }
+ typeset -f foobar
+)"
+eval "$x" || err_exit 'typeset -f generates syntax error'
+[[ $(foobar) != ok ]] && err_exit 'typeset -f not generating function'
+unset -f a b c
+a()
+{
+ b
+ b
+ print ${.sh.fun}
+}
+b() { : ;}
+[[ $(a) == a ]] || err_exit '.sh.fun not set correctly in a function'
+print $'a(){\ndate\n}' | $SHELL 2> /dev/null || err_exit 'parser error in a(){;date;}'
+cat > $tmp/data1 << '++EOF'
+ 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 4 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 8 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 12 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 14 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 15 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 17 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 18 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 20 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+++EOF
+cat > $tmp/script << '++EOF'
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+f()
+{
+cat <<\M
+++EOF
+cat $tmp/data1 >> $tmp/script
+printf 'M\n}\n\nf\n\n' >> $tmp/script
+$SHELL -c $tmp/script > $tmp/data2
+cmp -s $tmp/data[12] || err_exit 'error with long functions'
+v=1
+function f
+{
+ typeset i
+ for i in 0 1
+ do typeset v
+ v=$i
+ [[ $v == $i ]] || return 1
+ done
+}
+f || err_exit "typeset optimization bug"
+function f
+{
+ print -r -- "$foo$bar"
+}
+function g
+{
+ print -r -- $(bar=bam f)
+}
+unset foo bar
+[[ $(foo=hello g) == hellobam ]] || err_exit 'function exports not passed on'
+[[ $(bar=hello g) == bam ]] || err_exit 'function exports not overridden'
+unset -f foo
+function foo
+{
+ typeset line=$1
+ set +n
+ while [[ $line ]]
+ do if [[ ! $varname ]]
+ then varname=${line%% *}
+ line=${line##"$varname"?( )}
+ [[ $line ]] && continue
+ else print ok
+ return
+ fi
+ varname=
+ done
+}
+[[ $(foo 'NUMBERED RECORDSIZE') == ok ]] || err_exit 'optimization error with undefined variable'
+unset x
+x=$(
+ set -e
+ integer count=0
+ function err_f
+ {
+ if ((count++==3))
+ then print failed
+ else false
+ fi
+ }
+ trap 'err_f' ERR
+ false
+)
+[[ $x == failed ]] && err_exit 'ERR trap executed multiple times'
+export environment
+typeset global
+function f
+{
+ typeset i t local
+
+ for i
+ do case $i in
+ [-+]*) set "$@"
+ continue
+ ;;
+ local) local=f
+ t=$(typeset +f $local)
+ ;;
+ global) global=f
+ t=$(typeset +f $global)
+ ;;
+ environment)
+ environment=f
+ t=$(typeset +f $environment)
+ ;;
+ literal)t=$(typeset +f f)
+ ;;
+ positional)
+ set -- f
+ t=$(typeset +f $1)
+ ;;
+ esac
+ [[ $t ]] || err_exit "typeset +f \$$i failed"
+ done
+}
+f local global environment literal positional
+$SHELL -c '
+ print exit 0 > '$tmp'/script
+ chmod +x '$tmp'/script
+ unset var
+ var=( ident=1 )
+ function fun
+ {
+ PATH='$tmp' script
+ }
+ fun
+' || err_exit "compound variable cleanup before script exec failed"
+( $SHELL << \++EOF++
+function main
+{
+ typeset key
+ typeset -A entry
+ entry[a]=( value=aaa )
+}
+main
+++EOF++
+) 2> /dev/null || err_exit 'function main fails'
+optind=$OPTIND
+sub()
+{
+ (
+ OPTIND=1
+ while getopts :abc OPTION "$@"
+ do print OPTIND=$OPTIND
+ done
+ )
+}
+[[ $(sub -a) == OPTIND=2 ]] || err_exit 'OPTIND should be 2'
+[[ $(sub -a) == OPTIND=2 ]] || err_exit 'OPTIND should be 2 again'
+[[ $OPTIND == "$optind" ]] || err_exit 'OPTIND should be 1'
+
+function bar
+{
+ [[ -o nounset ]] && err_exit 'nounset option should not be inherited'
+}
+function foo
+{
+ set -o nounset
+ bar
+}
+set +o nounset
+foo
+function red
+{
+ integer -S d=0
+ printf 'red_one %d\n' d
+ (( d++ ))
+ return 0
+}
+[[ ${ red } != 'red_one 0' ]] && err_exit 'expected red_one 0'
+[[ ${ red } != 'red_one 1' ]] && err_exit 'expected red_one 1'
+xyz=$0
+function traceback
+{
+ integer .level=.sh.level
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ [[ $xyz == "$0" ]] || err_exit "\$xyz=$xyz does not match $0 on level ${.level}"
+ [[ ${.sh.lineno} == "$1" ]] || err_exit "\${.sh.lineno}=${.sh.lineno} does not match $1 on level ${.level}"
+ done
+}
+
+function foo
+{
+ typeset xyz=foo
+ set -- $((LINENO+1))
+ bar $LINENO "$1"
+}
+
+function bar
+{
+ typeset xyz=bar
+ set -- $((LINENO+2))
+ trap 'traceback $LINENO' DEBUG
+ : $LINENO "$1"
+}
+
+set -- $((LINENO+1))
+foo $LINENO
+function .sh.fun.set
+{
+ print -r -- "${.sh.value}"
+}
+function abc
+{
+ :
+}
+def()
+{
+ :
+}
+[[ $(abc) == abc ]] || err_exit '.sh.fun.set not capturing function name'
+[[ $(def) == def ]] || err_exit '.sh.fun.set not capturing name()'
+unset -f .sh.fun.set
+
+# tests for debug functions
+basefile=${.sh.file}
+integer baseline
+cat > $tmp/debug << \+++
+ : line 1
+
+ : line 3
++++
+# Print one line in a call stack
+function _Dbg_print_frame
+{
+ typeset -i pos=$1
+ typeset fn=$2
+ typeset filename="$3"
+ typeset -i line=$4
+ typeset arg=$5
+ shift 5
+ if ((pos==0))
+ then [[ $filename == "$basefile" ]] || err_exit "filename for level 0 is $filename not $basename"
+ [[ $arg == DEBUG ]] && ((baseline++))
+ [[ $line == "$baseline" ]] || err_exit "line number for level 0 is $line not $baseline"
+ elif ((pos==1))
+ then [[ $filename == "$tmp/debug" ]] || err_exit "filename for level 1 is $filename not $tmp/debug"
+ [[ $* == 'foo bar' ]] || err_exit "args are '$*', not 'foo bar'"
+ [[ $line == $arg ]] || err_exit "line number for level 1 is $line not $arg"
+ else err_exit "level should be 0 or 1 but is $pos"
+ fi
+}
+
+function _Dbg_debug_trap_handler
+{
+
+ integer .level=.sh.level .max=.sh.level-1
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ _Dbg_print_frame "${.level}" "$0" "${.sh.file}" "${.sh.lineno}" "${.sh.command##* }" "$@"
+ done
+}
+
+((baseline=LINENO+2))
+trap '_Dbg_debug_trap_handler' DEBUG
+. $tmp/debug foo bar
+trap '' DEBUG
+
+caller() {
+ integer .level=.sh.level .max=.sh.level-1
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ print -r -- "${.sh.lineno}"
+ done
+}
+bar() { caller;}
+set -- $(bar)
+[[ $1 == $2 ]] && err_exit ".sh.inline optimization bug"
+( $SHELL -c ' function foo { typeset x=$1;print $1;};z=();z=($(foo bar)) ') 2> /dev/null || err_exit 'using a function to set an array in a command sub fails'
+
+{
+got=$(
+s=$(ulimit -s)
+if [[ $s == +([[:digit:]]) ]] && (( s < 16384 ))
+then ulimit -s 16384 2>/dev/null
+fi
+$SHELL << \+++
+f()
+{
+ if (($1>1))
+ then x=$(f $(($1-1))) || exit 1
+ fi
+ return 0
+}
+f 257 && print ok
++++
+)
+} 2>/dev/null
+[[ $got == ok ]] || err_exit 'cannot handle comsub depth > 256 in function'
+
+tmp1=$tmp/job.1
+tmp2=$tmp/job.2
+cat > $tmp1 << +++
+#! $SHELL
+print \$\$
++++
+chmod +x $tmp1
+function foo
+{
+ typeset pid
+ $tmp1 > $tmp2 & pid=$!
+ wait $!
+ [[ $(< $tmp2) == $pid ]] || err_exit 'wrong pid for & job in function'
+}
+foo
+# make sure compiled functions work
+[[ $(tmp=$tmp $SHELL <<- \++++
+ cat > $tmp/functions <<- \EOF
+ function bar
+ {
+ print foo
+ }
+ function foobar
+ {
+ bar
+ }
+ EOF
+ ${SHCOMP:-${SHELL%/*}/shcomp} $tmp/functions > $tmp/foobar
+ rm -f "$tmp/functions"
+ chmod +x $tmp/foobar
+ rm $tmp/!(dir|foobar)
+ FPATH=$tmp
+ PATH=$FPATH:$PATH
+ foobar
+++++
+) == foo ]] > /dev/null || err_exit 'functions compiled with shcomp not working'
+# tests for compiled . scripts
+print $'print hello\nprint world' > $tmp/foo
+${SHCOMP:-${SHELL%/*}/shcomp} $tmp/foo > $tmp/foo.sh
+val=$(. $tmp/foo.sh)
+[[ $val == $'hello\nworld' ]] || err_exit "processing compiled dot files not working correctly val=$val"
+# test for functions in shell having side effects.
+unset -f foo foobar bar
+cd "$tmp"
+FPATH=$PWD
+PATH=$FPATH:$PATH
+cat > foo <<- \EOF
+ function bar
+ {
+ print foobar
+ }
+ function foo
+ {
+ bar
+ }
+EOF
+chmod +x foo
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effect of function foo'
+unset -f foo bar
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effects of function foo after reload'
+[[ $(typeset +f) == *bar* ]] && err_exit 'function in subshell leaving side effects of function bar after reload'
+
+unset -f foo
+typeset -A bar
+function foo
+{
+ typeset -i bar[$1].x
+ bar[$1].x=5
+}
+foo sub
+[[ ${!bar[@]} == sub ]] || err_exit 'scoping problem with compound array variables'
+
+function A
+{
+ trap "> /dev/null;print TRAP A" EXIT
+ # (( stderr )) && print >&2
+}
+
+function B
+{
+ trap "> /dev/null;print TRAP B" EXIT
+ A
+}
+
+x=$(B)
+[[ $x == $'TRAP A\nTRAP B' ]] || err_exit "trap from functions in subshells fails got" $x
+
+function foo
+{
+ typeset bar=abc
+ unset bar
+# [[ $bar == bam ]] || err_exit 'unsetting local variable does not expose global variable'
+ [[ $bar ]] && err_exit 'unsetting local variable exposes global variable'
+}
+bar=bam
+foo
+
+sleep=$(whence -p sleep)
+function gosleep
+{
+ $sleep 4
+}
+x=$(
+ (sleep 2; pid=; ps | grep sleep | read pid extra; [[ $pid ]] && kill -- $pid) &
+ gosleep 2> /dev/null
+ print ok
+)
+[[ $x == ok ]] || err_exit 'TERM signal sent to last process of function kills the script'
+
+# verify that $0 does not change with functions defined as fun()
+func1()
+{
+ [[ $0 == "$dol0" ]] || err_exit "\$0 changed in func1() to $0"
+}
+function func2
+{
+ [[ $0 == func2 ]] || err_exit "\$0 changed in func2() to $0"
+ dol0=func2
+ func1
+}
+func2
+
+{ $SHELL <<- \EOF
+ function foo
+ {
+ typeset rc=0
+ unset -f foo
+ return $rc;
+ }
+ foo
+EOF
+} 2> /dev/null || err_exit 'problem with unset -f foo within function foo'
+
+val=$($SHELL 2> /dev/null <<- \EOF
+ .sh.fun.set() { set -x; }
+ function f1 { print -n ${.sh.fun}; set -o | grep xtrace;}
+ function f2 { print -n ${.sh.fun}; set -o | grep xtrace;}
+ f1
+ set -o | grep xtrace
+ f2
+EOF)
+[[ $val == f1xtrace*on*off*f2xtrace*on* ]] || err_exit "'.sh.fun.set() { set -x; }' not tracing all functions"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/glob.sh b/src/cmd/ksh93/tests/glob.sh
new file mode 100755
index 0000000..5b7930e
--- /dev/null
+++ b/src/cmd/ksh93/tests/glob.sh
@@ -0,0 +1,374 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -r $'\t'"${Command}[$1] ${@:2}"
+ ((Errors++))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer aware=0 contrary=0 Errors=0 ignorant=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function test_glob
+{
+ typeset lineno expected drop arg got sep op val add del
+ lineno=$1
+ shift
+ if [[ $1 == --* ]]
+ then del=${1#--}
+ shift
+ fi
+ if [[ $1 == ++* ]]
+ then add=${1#++}
+ shift
+ fi
+ expected=$1
+ shift
+ if (( contrary ))
+ then if [[ $expected == "<Beware> "* ]]
+ then expected=${expected#"<Beware> "}
+ expected="$expected <Beware>"
+ fi
+ if [[ $expected == *"<aXb> <abd>"* ]]
+ then expected=${expected/"<aXb> <abd>"/"<abd> <aXb>"}
+ fi
+ fi
+ for arg
+ do got="$got$sep<$arg>"
+ sep=" "
+ done
+ if (( ignorant && aware ))
+ then if [[ $del ]]
+ then got="<$del> $got"
+ fi
+ if [[ $add ]]
+ then expected="<$add> $expected"
+ fi
+ fi
+ if [[ $got != "$expected" ]]
+ then 'err_exit' $lineno "glob -- expected '$expected', got '$got'"
+ fi
+}
+alias test_glob='test_glob $LINENO'
+
+function test_case
+{
+ typeset lineno expected subject pattern got
+ lineno=$1 expected=$2 subject=$3 pattern=$4
+ eval "
+ case $subject in
+ $pattern) got='<match>' ;;
+ *) got='<nomatch>' ;;
+ esac
+ "
+ if [[ $got != "$expected" ]]
+ then 'err_exit' $lineno "case $subject in $pattern) -- expected '$expected', got '$got'"
+ fi
+}
+alias test_case='test_case $LINENO'
+
+unset undefined
+
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+
+export LC_COLLATE=C
+touch B b
+set -- *
+case $* in
+'b B') contrary=1 ;;
+b|B) ignorant=1 ;;
+esac
+set -- $(LC_ALL=C /bin/sh -c 'echo [a-c]')
+case $* in
+B) aware=1 ;;
+esac
+rm -rf *
+
+touch a b c d abc abd abe bb bcd ca cb dd de Beware
+mkdir bdir
+
+test_glob '<a> <abc> <abd> <abe> <X*>' a* X*
+test_glob '<a> <abc> <abd> <abe>' \a*
+
+if ( set --nullglob ) 2>/dev/null
+then
+ set --nullglob
+
+ test_glob '<a> <abc> <abd> <abe>' a* X*
+
+ set --nonullglob
+fi
+
+if ( set --failglob ) 2>/dev/null
+then
+ set --failglob
+ mkdir tmp
+ touch tmp/l1 tmp/l2 tmp/l3
+
+ test_glob '' tmp/l[12] tmp/*4 tmp/*3
+ test_glob '' tmp/l[12] tmp/*4 tmp/*3
+
+ rm -r tmp
+ set --nofailglob
+fi
+
+test_glob '<bdir/>' b*/
+test_glob '<*>' \*
+test_glob '<a*>' 'a*'
+test_glob '<a*>' a\*
+test_glob '<c> <ca> <cb> <a*> <*q*>' c* a\* *q*
+test_glob '<**>' "*"*
+test_glob '<**>' \**
+test_glob '<\.\./*/>' "\.\./*/"
+test_glob '<s/\..*//>' 's/\..*//'
+test_glob '</^root:/{s/^[!:]*:[!:]*:\([!:]*\).*$/\1/>' "/^root:/{s/^[!:]*:[!:]*:\([!:]*\).*"'$'"/\1/"
+test_glob '<abc> <abd> <abe> <bb> <cb>' [a-c]b*
+test_glob ++Beware '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' [a-y]*[!c]
+test_glob '<abd> <abe>' a*[!c]
+
+touch a-b aXb
+
+test_glob '<a-b> <aXb>' a[X-]b
+
+touch .x .y
+
+test_glob --Beware '<Beware> <d> <dd> <de>' [!a-c]*
+
+if mkdir a\*b 2>/dev/null
+then
+ touch a\*b/ooo
+
+ test_glob '<a*b/ooo>' a\*b/*
+ test_glob '<a*b/ooo>' a\*?/*
+ test_case '<match>' '!7' '*\!*'
+ test_case '<match>' 'r.*' '*.\*'
+ test_glob '<abc>' a[b]c
+ test_glob '<abc>' a["b"]c
+ test_glob '<abc>' a[\b]c
+ test_glob '<abc>' a?c
+ test_case '<match>' 'abc' 'a"b"c'
+ test_case '<match>' 'abc' 'a*c'
+ test_case '<nomatch>' 'abc' '"a?c"'
+ test_case '<nomatch>' 'abc' 'a\*c'
+ test_case '<nomatch>' 'abc' 'a\[b]c'
+ test_case '<match>' '"$undefined"' '""'
+ test_case '<match>' 'abc' 'a["\b"]c'
+
+ rm -rf mkdir a\*b
+fi
+
+mkdir man
+mkdir man/man1
+touch man/man1/sh.1
+
+test_glob '<man/man1/sh.1>' */man*/sh.*
+test_glob '<man/man1/sh.1>' $(echo */man*/sh.*)
+test_glob '<man/man1/sh.1>' "$(echo */man*/sh.*)"
+
+test_case '<match>' 'abc' 'a***c'
+test_case '<match>' 'abc' 'a*****?c'
+test_case '<match>' 'abc' '?*****??'
+test_case '<match>' 'abc' '*****??'
+test_case '<match>' 'abc' '*****??c'
+test_case '<match>' 'abc' '?*****?c'
+test_case '<match>' 'abc' '?***?****c'
+test_case '<match>' 'abc' '?***?****?'
+test_case '<match>' 'abc' '?***?****'
+test_case '<match>' 'abc' '*******c'
+test_case '<match>' 'abc' '*******?'
+test_case '<match>' 'abcdecdhjk' 'a*cd**?**??k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k***'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k**'
+test_case '<match>' 'abcdecdhjk' 'a****c**?**??*****'
+test_case '<match>' "'-'" '[-abc]'
+test_case '<match>' "'-'" '[abc-]'
+test_case '<match>' "'\\'" '\\'
+test_case '<match>' "'\\'" '[\\]'
+test_case '<match>' "'\\'" "'\\'"
+test_case '<match>' "'['" '[[]'
+test_case '<match>' '[' '[[]'
+test_case '<match>' "'['" '['
+test_case '<match>' '[' '['
+test_case '<match>' "'[abc'" "'['*"
+test_case '<nomatch>' "'[abc'" '[*'
+test_case '<match>' '[abc' "'['*"
+test_case '<nomatch>' '[abc' '[*'
+test_case '<match>' 'abd' "a[b/c]d"
+test_case '<match>' 'a/d' "a[b/c]d"
+test_case '<match>' 'acd' "a[b/c]d"
+test_case '<match>' "']'" '[]]'
+test_case '<match>' "'-'" '[]-]'
+test_case '<match>' 'p' '[a-\z]'
+test_case '<match>' '"/tmp"' '[/\\]*'
+test_case '<nomatch>' 'abc' '??**********?****?'
+test_case '<nomatch>' 'abc' '??**********?****c'
+test_case '<nomatch>' 'abc' '?************c****?****'
+test_case '<nomatch>' 'abc' '*c*?**'
+test_case '<nomatch>' 'abc' 'a*****c*?**'
+test_case '<nomatch>' 'abc' 'a********???*******'
+test_case '<nomatch>' "'a'" '[]'
+test_case '<nomatch>' 'a' '[]'
+test_case '<nomatch>' "'['" '[abc'
+test_case '<nomatch>' '[' '[abc'
+
+test_glob ++Beware '<b> <bb> <bcd> <bdir>' b*
+test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
+
+if ( set --nocaseglob ) 2>/dev/null
+then
+ set --nocaseglob
+
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' b*
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' [b]*
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
+
+ set --nonocaseglob
+fi
+
+if ( set -f ) 2>/dev/null
+then
+ set -f
+
+ test_glob '<*>' *
+
+ set +f
+fi
+
+if ( set --noglob ) 2>/dev/null
+then
+ set --noglob
+
+ test_glob '<*>' *
+
+ set --glob
+fi
+
+FIGNORE='@(.*|*)'
+test_glob '<*>' *
+
+FIGNORE='@(.*|*c|*e|?)'
+test_glob '<a-b> <aXb> <abd> <bb> <bcd> <bdir> <ca> <cb> <dd> <man>' *
+
+FIGNORE='@(.*|*b|*d|?)'
+test_glob '<Beware> <abc> <abe> <bdir> <ca> <de> <man>' *
+
+FIGNORE=
+test_glob '<man/man1/sh.1>' */man*/sh.*
+
+unset FIGNORE
+test_glob '<bb> <ca> <cb> <dd> <de>' ??
+test_glob '<man/man1/sh.1>' */man*/sh.*
+
+GLOBIGNORE='.*:*'
+set -- *
+if [[ $1 == '*' ]]
+then
+ GLOBIGNORE='.*:*c:*e:?'
+ test_glob '<>' *
+
+ GLOBIGNORE='.*:*b:*d:?'
+ test_glob '<>' *
+
+ unset GLOBIGNORE
+ test_glob '<>' *
+ test_glob '<man/man1/sh.1>' */man*/sh.*
+
+ GLOBIGNORE=
+ test_glob '<man/man1/sh.1>' */man*/sh.*
+fi
+unset GLOBIGNORE
+
+function test_sub
+{
+ x='${subject'$2'}'
+ eval g=$x
+ if [[ "$g" != "$3" ]]
+ then 'err_exit' $1 subject="'$subject' $x failed, expected '$3', got '$g'"
+ fi
+}
+alias test_sub='test_sub $LINENO'
+
+set --noglob --nobraceexpand
+
+subject='A regular expressions test'
+
+test_sub '/e/#' 'A r#gular expressions test'
+test_sub '//e/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/[^e]/#' '# regular expressions test'
+test_sub '//[^e]/#' '###e######e###e########e##'
+test_sub '/+(e)/#' 'A r#gular expressions test'
+test_sub '//+(e)/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/@-(e)/#' 'A r#gular expressions test'
+test_sub '//@-(e)/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/?(e)/#' '#A regular expressions test'
+test_sub '//?(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
+test_sub '/*(e)/#' '#A regular expressions test'
+test_sub '//*(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
+test_sub '//@(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//+(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//+-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@(+(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@(+-(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//-(e)/#' 'A regular expressions test'
+test_sub '//--(e)/#' 'A regular expressions test'
+test_sub '//?(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//{0,1}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//*(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//{0,}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@(?(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@({0,1}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@(*(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@({0,}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '/?-(e)/#' '#A regular expressions test'
+test_sub '/@(?-(e))/[\1]' '[]A regular expressions test'
+test_sub '/!(e)/#' '#'
+test_sub '//!(e)/#' '#'
+test_sub '/@(!(e))/[\1]' '[A regular expressions test]'
+test_sub '//@(!(e))/[\1]' '[A regular expressions test]'
+
+subject='e'
+
+test_sub '/!(e)/#' '#e'
+test_sub '//!(e)/#' '#e#'
+test_sub '/!(e)/[\1]' '[]e'
+test_sub '//!(e)/[\1]' '[]e[]'
+test_sub '/@(!(e))/[\1]' '[]e'
+test_sub '//@(!(e))/[\1]' '[]e[]'
+
+subject='a'
+
+test_sub '/@(!(a))/[\1]' '[]a'
+test_sub '//@(!(a))/[\1]' '[]a[]'
+
+subject='aha'
+
+test_sub '/@(!(a))/[\1]' '[aha]'
+test_sub '//@(!(a))/[\1]' '[aha]'
+test_sub '/@(!(aha))/[\1]' '[ah]a'
+test_sub '//@(!(aha))/[\1]' '[ah][a]'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/grep.sh b/src/cmd/ksh93/tests/grep.sh
new file mode 100755
index 0000000..480f823
--- /dev/null
+++ b/src/cmd/ksh93/tests/grep.sh
@@ -0,0 +1,105 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function grep
+{
+ #
+ # SHELL VERSION OF GREP
+ #
+ vflag= xflag= cflag= lflag= nflag=
+ set -f
+ while ((1)) # look for grep options
+ do case "$1" in
+ -v*) vflag=1;;
+ -x*) xflag=1;;
+ -c*) cflag=1;;
+ -l*) lflag=1;;
+ -n*) nflag=1;;
+ -b*) print 'b option not supported';;
+ -e*) shift;expr="$1";;
+ -f*) shift;expr=$(< $1);;
+ -*) print $0: 'unknown flag';return 2;;
+ *)
+ if test "$expr" = ''
+ then expr="$1";shift
+ fi
+ test "$xflag" || expr="*${expr}*"
+ break;;
+ esac
+ shift # next argument
+ done
+ noprint=$vflag$cflag$lflag # don't print if these flags are set
+ integer n=0 c=0 tc=0 nargs=$# # initialize counters
+ for i in "$@" # go thru the files
+ do if ((nargs<=1))
+ then fname=''
+ else fname="$i":
+ fi
+ test "$i" && exec 0< $i # open file if necessary
+ while read -r line # read in a line
+ do let n=n+1
+ case "$line" in
+ $expr) # line matches pattern
+ test "$noprint" || print -r -- "$fname${nflag:+$n:}$line"
+ let c=c+1 ;;
+ *) # not a match
+ if test "$vflag"
+ then print -r -- "$fname${nflag:+$n:}$line"
+ fi;;
+ esac
+ done
+ if test "$lflag" && ((c))
+ then print -r -- "$i"
+ fi
+ let tc=tc+c n=0 c=0
+ done
+ test "$cflag" && print $tc # print count if cflag is set
+ let tc # set the return value
+}
+
+cat > $tmp/grep <<\!
+this is a food bar test
+to see how many lines find both foo and bar.
+Some line contain foo only,
+and some lines contain bar only.
+However, many lines contain both foo and also bar.
+A line containing foobar should also be counted.
+There should be six lines with foo and bar.
+There are only two line with out foo but with bar.
+!
+
+if (( $(grep -c 'foo*bar' $tmp/grep ) != 6))
+then err_exit
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/heredoc.sh b/src/cmd/ksh93/tests/heredoc.sh
new file mode 100755
index 0000000..a8d8a72
--- /dev/null
+++ b/src/cmd/ksh93/tests/heredoc.sh
@@ -0,0 +1,496 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+f=$tmp/here1
+g=$tmp/here2
+cat > $f <<!
+hello world
+!
+if [[ $(<$f) != 'hello world' ]]
+then err_exit "'hello world' here doc not working"
+fi
+cat > $g <<\!
+hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' quoted here doc not working"
+cat > $g <<- !
+ hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' tabbed here doc not working"
+cat > $g <<- \!
+ hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' quoted tabbed here doc not working"
+x=hello
+cat > $g <<!
+$x world
+!
+cmp $f $g 2> /dev/null || err_exit "'$x world' here doc not working"
+cat > $g <<!
+$(print hello) world
+!
+cmp $f $g 2> /dev/null || err_exit "'$(print hello) world' here doc not working"
+cat > $f <<\!!
+!@#$%%^^&*()_+~"::~;'`<>?/.,{}[]
+!!
+if [[ $(<$f) != '!@#$%%^^&*()_+~"::~;'\''`<>?/.,{}[]' ]]
+then err_exit "'hello world' here doc not working"
+fi
+cat > $g <<!!
+!@#\$%%^^&*()_+~"::~;'\`<>?/.,{}[]
+!!
+cmp $f $g 2> /dev/null || err_exit "unquoted here doc not working"
+exec 3<<!
+ foo
+!
+if [[ $(<&3) != ' foo' ]]
+then err_exit "leading tabs stripped with <<!"
+fi
+$SHELL -c "
+eval `echo 'cat <<x'` "|| err_exit "eval `echo 'cat <<x'` core dumps"
+cat > /dev/null <<EOF # comments should not cause core dumps
+abc
+EOF
+cat >$g << :
+:
+:
+cmp /dev/null $g 2> /dev/null || err_exit "empty here doc not working"
+x=$(print $( cat <<HUP
+hello
+HUP
+)
+)
+if [[ $x != hello ]]
+then err_exit "here doc inside command sub not working"
+fi
+y=$(cat <<!
+${x:+${x}}
+!
+)
+if [[ $y != "${x:+${x}}" ]]
+then err_exit '${x:+${x}} not working in here document'
+fi
+$SHELL -c '
+x=0
+while (( x < 100 ))
+do ((x = x+1))
+ cat << EOF
+EOF
+done
+' 2> /dev/null || err_exit '100 empty here docs fails'
+{
+ print 'builtin -d cat
+ cat <<- EOF'
+ for ((i=0; i < 100; i++))
+ do print XXXXXXXXXXXXXXXXXXXX
+ done
+ print ' XXX$(date)XXXX
+ EOF'
+} > $f
+chmod +x "$f"
+$SHELL "$f" > /dev/null || err_exit "large here-doc with command substitution fails"
+x=$(/bin/cat <<!
+$0
+!
+)
+[[ "$x" == "$0" ]] || err_exit '$0 not correct inside here documents'
+$SHELL -c 'x=$(
+cat << EOF
+EOF)' 2> /dev/null || err_exit 'here-doc cannot be terminated by )'
+if [[ $( IFS=:;cat <<-!
+ $IFS$(print hi)$IFS
+ !) != :hi: ]]
+then err_exit '$IFS unset by command substitution in here docs'
+fi
+if x=$($SHELL -c 'cat <<< "hello world"' 2> /dev/null)
+then [[ $x == 'hello world' ]] || err_exit '<<< documents not working'
+ x=$($SHELL -c 'v="hello world";cat <<< $v' 2> /dev/null)
+ [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working'
+ x=$($SHELL -c 'v="hello world";cat <<< "$v"' 2> /dev/null)
+ [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working'
+else err_exit '<<< syntax not supported'
+fi
+if [[ $(cat << EOF #testing
+#abc
+abc
+EOF) != $'#abc\nabc' ]]
+then err_exit 'comments not preserved in here-documents'
+fi
+cat > "$f" <<- '!!!!'
+ builtin cat
+ : << EOF
+ $PWD
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ EOF
+ command exec 3>&- 4>&- 5>&- 6>&- 7>&- 8>&- 9>&-
+ x=abc
+ cat << EOF
+ $x
+ EOF
+!!!!
+chmod 755 "$f"
+if [[ $($SHELL "$f") != abc ]]
+then err_exit 'here document descritor was closed'
+fi
+cat > "$f" <<- '!!!!'
+ exec 0<&-
+ foobar()
+ {
+ /bin/cat <<- !
+ foobar
+ !
+ }
+ : << EOF
+ $PWD
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ EOF
+ print -r -- "$(foobar)"
+!!!!
+if [[ $($SHELL "$f") != foobar ]]
+then err_exit 'here document with stdin closed failed'
+fi
+printf $'cat <<# \\!!!\n\thello\n\t\tworld\n!!!' > $f
+[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for quoted here documents"
+printf $'w=world;cat <<# !!!\n\thello\n\t\t$w\n!!!' > $f
+[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for non-quoted here documents"
+[[ $( $SHELL <<- \++++
+ S=( typeset a )
+ function S.a.get
+ {
+ .sh.value=$__a
+ }
+ __a=1234
+ cat <<-EOF
+ ${S.a}
+ EOF
+++++
+) == 1234 ]] 2> /dev/null || err_exit 'here document with get discipline failed'
+[[ $($SHELL -c 'g(){ print ok;}; cat <<- EOF
+ ${ g;}
+ EOF
+ ' 2> /dev/null) == ok ]] || err_exit '${ command;} not working in heredoc'
+script=$f
+{
+for ((i=0; i < 406; i++))
+do print ': 23456789012345678'
+done
+print : 123456789123
+cat <<- \EOF
+eval "$(
+ { cat ; } <<MARKER
+ print hello
+ MARKER
+)"
+EOF
+} > $script
+chmod +x $script
+[[ $($SHELL $script) == hello ]] 2> /dev/null || err_exit 'heredoc embeded in command substitution fails at buffer boundary'
+
+got=$( cat << EOF
+\
+abc
+EOF)
+[[ $got == abc ]] || err_exit 'line continuation at start of buffer not working'
+
+tmpfile1=$tmp/file1
+tmpfile2=$tmp/file2
+function gendata
+{
+ typeset -RZ3 i
+ for ((i=0; i < 500; i++))
+ do print -r -- "=====================This is line $i============="
+ done
+}
+
+cat > $tmpfile1 <<- +++
+ function foobar
+ {
+ cat << XXX
+ $(gendata)
+ XXX
+ }
+ cat > $tmpfile2 <<- EOF
+ \$(foobar)
+ $(gendata)
+EOF
++++
+chmod +x $tmpfile1
+$SHELL $tmpfile1
+set -- $(wc < $tmpfile2)
+(( $1 == 1000 )) || err_exit "heredoc $1 lines, should be 1000 lines"
+(( $2 == 4000 )) || err_exit "heredoc $2 words, should be 4000 words"
+
+# comment with here document looses line number count
+integer line=$((LINENO+5))
+function tst
+{
+ [[ $1 == $2 ]] || echo expected $1, got $2
+}
+tst $line $LINENO <<"!" # this comment affects LINENO #
+1
+!
+(( (line+=3) == LINENO )) || err_exit "line number=$LINENO should be $line"
+
+[[ $($SHELL -c 'wc -c <<< ""' 2> /dev/null) == *1 ]] || err_exit '<<< with empty string not working'
+
+mkdir $tmp/functions
+cat > $tmp/functions/t2 <<\!!!
+function t2
+{
+cat <<EOF | sed 's/1234567890/qwertyuiopasdfghj/'
+${1}
+EOF
+}
+!!!
+
+FPATH=$tmp/functions
+foo=${
+cat <<EOF
+1 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111 1
+
+2 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222 2
+
+3 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333 3
+
+4 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444 4
+
+5 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555 5
+
+6 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666 6
+
+7 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777 7
+
+8 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888 8
+
+9 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999 9
+
+10 4567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+1010101010101010101010101010101010101010101010101010101010 END
+
+EOF
+}
+[[ ${#foo} == 10238 ]] || err_exit 'large here docs containing command subs of dynamically loaded functions fails'
+
+{
+ print $'FOO=1\nBAR=foobarbaz'
+ print -- 'cat <<#EOF'
+ integer i
+ for ((i=0; i < 50000; i++))
+ do print -r -- ' $(($FOO + 1))'
+ print -r -- ' $BAR meep'
+ done
+ print EOF
+} > $f
+$SHELL $f > $g
+[[ $(grep meep $g | grep -v foobar) != '' ]] && err_exit 'here-doc loosing $var expansions on boundaries in rare cases'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh
new file mode 100755
index 0000000..bed0fd4
--- /dev/null
+++ b/src/cmd/ksh93/tests/io.sh
@@ -0,0 +1,484 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+unset HISTFILE
+
+function fun
+{
+ while command exec 3>&1
+ do break
+ done 2> /dev/null
+ print -u3 good
+}
+print 'read -r a; print -r -u$1 -- "$a"' > $tmp/mycat
+chmod 755 $tmp/mycat
+for ((i=3; i < 10; i++))
+do
+ eval "a=\$(print foo | $tmp/mycat" $i $i'>&1 > /dev/null |cat)' 2> /dev/null
+ [[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script"
+done
+exec 3> /dev/null
+[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes'
+exec 3>&-
+cd $tmp || { err_exit "cd $tmp failed"; exit ; }
+print foo > file1
+print bar >> file1
+if [[ $(<file1) != $'foo\nbar' ]]
+then err_exit 'append (>>) not working'
+fi
+set -o noclobber
+exec 3<> file1
+read -u3 line
+exp=foo
+if [[ $line != $exp ]]
+then err_exit "read on <> fd failed -- expected '$exp', got '$line'"
+fi
+if ( 4> file1 ) 2> /dev/null
+then err_exit 'noclobber not causing exclusive open'
+fi
+set +o noclobber
+
+FDFS=(
+ ( dir=/proc/self/fd semantics='open' )
+ ( dir=/proc/$$/fd semantics='open' )
+ ( dir=/dev/fd semantics='open|dup' )
+ ( dir=/dev/fd semantics='dup' )
+)
+for ((fdfs=0; fdfs<${#FDFS[@]}-1; fdfs++))
+do [[ -e ${FDFS[fdfs].dir} ]] && { command : > ${FDFS[fdfs].dir}/1; } 2>/dev/null >&2 && break
+done
+
+exec 3<> file1
+if command exec 4< ${FDFS[fdfs].dir}/3
+then read -u3 got
+ read -u4 got
+ exp='foo|bar'
+ case $got in
+ foo) semantics='open' ;;
+ bar) semantics='dup' ;;
+ *) semantics='failed' ;;
+ esac
+ [[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "'4< ${FDFS[fdfs].dir}/3' $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
+fi
+
+# 2004-11-25 ancient /dev/fd/N redirection bug fix
+got=$(
+ {
+ print -n 1
+ print -n 2 > ${FDFS[fdfs].dir}/2
+ print -n 3
+ print -n 4 > ${FDFS[fdfs].dir}/2
+ } 2>&1
+)
+exp='1234|4'
+case $got in
+1234) semantics='dup' ;;
+4) semantics='open' ;;
+*) semantics='failed' ;;
+esac
+[[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "${FDFS[fdfs].dir}/N $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
+
+cat > close0 <<\!
+exec 0<&-
+echo $(./close1)
+!
+print "echo abc" > close1
+chmod +x close0 close1
+x=$(./close0)
+if [[ $x != "abc" ]]
+then err_exit "picked up file descriptor zero for opening script file"
+fi
+cat > close0 <<\!
+ for ((i=0; i < 1100; i++))
+ do exec 4< /dev/null
+ read -u4
+ done
+ exit 0
+!
+./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
+$SHELL -c '
+ trap "rm -f in out" EXIT
+ for ((i = 0; i < 1000; i++))
+ do print -r -- "This is a test"
+ done > in
+ > out
+ exec 1<> out
+ builtin cat
+ print -r -- "$(<in)"
+ cmp -s in out' 2> /dev/null
+[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
+cat >| script <<-\!
+print hello
+( exec 3<&- 4<&-)
+exec 3<&- 4<&-
+print world
+!
+chmod +x script
+[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail'
+cd ~- || err_exit "cd back failed"
+( exec > '' ) 2> /dev/null && err_exit '> "" does not fail'
+unset x
+( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail'
+exec <<!
+foo
+bar
+!
+( exec 0< /dev/null)
+read line
+if [[ $line != foo ]]
+then err_exit 'file descriptor not restored after exec in subshell'
+fi
+exec 3>&- 4>&-
+[[ $( {
+ read -r line; print -r -- "$line"
+ (
+ read -r line; print -r -- "$line"
+ ) & wait
+ while read -r line
+ do print -r -- "$line"
+ done
+ } << !
+line 1
+line 2
+line 3
+!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells'
+# 2004-05-11 bug fix
+cat > $tmp/1 <<- ++EOF++
+ script=$tmp/2
+ trap "rm -f \$script" EXIT
+ exec 9> \$script
+ for ((i=3; i<9; i++))
+ do eval "while read -u\$i; do : ; done \$i</dev/null"
+ print -u9 "exec \$i< /dev/null"
+ done
+ for ((i=0; i < 60; i++))
+ do print -u9 -f "%.80c\n" ' '
+ done
+ print -u9 'print ok'
+ exec 9<&-
+ chmod +x \$script
+ \$script
+++EOF++
+chmod +x $tmp/1
+[[ $($SHELL $tmp/1) == ok ]] || err_exit "parent i/o causes child script to fail"
+# 2004-12-20 redirection loss bug fix
+cat > $tmp/1 <<- \++EOF++
+ function a
+ {
+ trap 'print ok' EXIT
+ : > /dev/null
+ }
+ a
+++EOF++
+chmod +x $tmp/1
+[[ $($tmp/1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
+print > /dev/null {n}> $tmp/1
+[[ ! -s $tmp/1 ]] && newio=1
+if [[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]]
+then err_exit "{n}<&0 not working with for loop"
+fi
+[[ $({ read -r; read -u3 3<&0; print -- "$REPLY" ;} <<!
+hello
+world
+!) == world ]] || err_exit 'I/O not synchronized with <&'
+x="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890"
+for ((i=0; i < 62; i++))
+do printf "%.39c\n" ${x:i:1}
+done > $tmp/seek
+if command exec 3<> $tmp/seek
+then (( $(3<#) == 0 )) || err_exit "not at position 0"
+ (( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file"
+ command exec 3<# ((40*8)) || err_exit "absolute seek fails"
+ read -u3
+ [[ $REPLY == +(i) ]] || err_exit "expected iiii..., got $REPLY"
+ [[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
+ command exec 3<# ((CUR+80))
+ read -u3
+ [[ $REPLY == {39}(l) ]] || err_exit "expected lll..., got $REPLY"
+ command exec 3<# ((EOF-80))
+ read -u3
+ [[ $REPLY == +(9) ]] || err_exit "expected 999..., got $REPLY"
+ command exec 3># ((80))
+ print -u3 -f "%.39c\n" @
+ command exec 3># ((80))
+ read -u3
+ [[ $REPLY == +(@) ]] || err_exit "expected @@@..., got $REPLY"
+ read -u3
+ [[ $REPLY == +(d) ]] || err_exit "expected ddd..., got $REPLY"
+ command exec 3># ((EOF))
+ print -u3 -f "%.39c\n" ^
+ (( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file"
+ command exec 3<# ((40*62))
+ read -u3
+ [[ $REPLY == +(^) ]] || err_exit "expected ddd..., got $REPLY"
+ command exec 3<# ((0))
+ command exec 3<# *jjjj*
+ read -u3
+ [[ $REPLY == {39}(j) ]] || err_exit "<# pattern failed"
+ [[ $(command exec 3<## *llll*) == {39}(k) ]] || err_exit "<## pattern not saving standard output"
+ read -u3
+ [[ $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position"
+ command exec 3<# *abc*
+ read -u3 && err_exit "not found pattern not positioning at eof"
+ cat $tmp/seek | read -r <# *WWW*
+ [[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
+ { < $tmp/seek <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
+else err_exit "$tmp/seek: cannot open for reading"
+fi
+command exec 3<&- || 'cannot close 3'
+for ((i=0; i < 62; i++))
+do printf "%.39c\n" ${x:i:1}
+done > $tmp/seek
+if command exec {n}<> $tmp/seek
+then { command exec {n}<#((EOF)) ;} 2> /dev/null || err_exit '{n}<# not working'
+ if $SHELL -c '{n}</dev/null' 2> /dev/null
+ then (( $({n}<#) == 40*62)) || err_exit '$({n}<#) not working'
+ else err_exit 'not able to parse {n}</dev/null'
+ fi
+fi
+$SHELL -ic '
+{
+ print -u2 || exit 2
+ print -u3 || exit 3
+ print -u4 || exit 4
+ print -u5 || exit 5
+ print -u6 || exit 6
+ print -u7 || exit 7
+ print -u8 || exit 8
+ print -u9 || exit 9
+} 3> /dev/null 4> /dev/null 5> /dev/null 6> /dev/null 7> /dev/null 8> /dev/null 9> /dev/null' > /dev/null 2>&1
+exitval=$?
+(( exitval )) && err_exit "print to unit $exitval failed"
+$SHELL -c "{ > $tmp/1 ; date;} >&- 2> /dev/null" > $tmp/2
+[[ -s $tmp/1 || -s $tmp/2 ]] && err_exit 'commands with standard output closed produce output'
+$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell'
+[[ $(cat <<- \EOF | $SHELL
+ do_it_all()
+ {
+ dd 2>/dev/null # not a ksh93 buildin
+ return $?
+ }
+ do_it_all ; exit $?
+ hello world
+EOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin'
+$SHELL -c 'exec 3>; /dev/null' 2> /dev/null && err_exit '>; with exec should be an error'
+$SHELL -c ': 3>; /dev/null' 2> /dev/null || err_exit '>; not working with at all'
+print hello > $tmp/1
+if ! $SHELL -c "false >; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '>; not preserving file on failure'
+fi
+if ! $SHELL -c "sed -e 's/hello/hello world/' $tmp/1" >; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == 'hello world' ]] || err_exit '>; not updating file on success'
+fi
+
+$SHELL -c 'exec 3<>; /dev/null' 2> /dev/null && err_exit '<>; with exec should be an error'
+$SHELL -c ': 3<>; /dev/null' 2> /dev/null || err_exit '<>; not working with at all'
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c "false <>; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == $'hello\nworld' ]] || err_exit '<>; not preserving file on failure'
+fi
+if ! $SHELL -c "head -1 $tmp/1" <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '<>; not truncating file on success of head'
+fi
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c head < $tmp/1 <#((6)) <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == world ]] || err_exit '<>; not truncating file on success of behead'
+fi
+
+unset y
+read -n1 y <<!
+abc
+!
+if [[ $y != a ]]
+then err_exit 'read -n1 not working'
+fi
+unset a
+{ read -N3 a; read -N1 b;} <<!
+abcdefg
+!
+[[ $a == abc ]] || err_exit 'read -N3 here-document not working'
+[[ $b == d ]] || err_exit 'read -N1 here-document not working'
+read -n3 a <<!
+abcdefg
+!
+[[ $a == abc ]] || err_exit 'read -n3 here-document not working'
+(print -n a; sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
+[[ $a == abc ]] || err_exit 'read -N3 from pipe not working'
+[[ $b == d ]] || err_exit 'read -N1 from pipe not working'
+(print -n a; sleep 1; print -n bcde) |read -n3 a
+[[ $a == a ]] || err_exit 'read -n3 from pipe not working'
+if mkfifo $tmp/fifo 2> /dev/null
+then (print -n a; sleep 2; print -n bcde) > $tmp/fifo &
+ {
+ read -u5 -n3 -t3 a || err_exit 'read -n3 from fifo timed out'
+ read -u5 -n1 -t3 b || err_exit 'read -n1 from fifo timed out'
+ } 5< $tmp/fifo
+ exp=a
+ got=$a
+ [[ $got == "$exp" ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$got'"
+ exp=b
+ got=$b
+ [[ $got == "$exp" ]] || err_exit "read -n1 from fifo failed -- expected '$exp', got '$got'"
+ rm -f $tmp/fifo
+ wait
+ mkfifo $tmp/fifo 2> /dev/null
+ (print -n a; sleep 2; print -n bcde) > $tmp/fifo &
+ {
+ read -u5 -N3 -t3 a || err_exit 'read -N3 from fifo timed out'
+ read -u5 -N1 -t3 b || err_exit 'read -N1 from fifo timed out'
+ } 5< $tmp/fifo
+ exp=abc
+ got=$a
+ [[ $got == "$exp" ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$got'"
+ exp=d
+ got=$b
+ [[ $got == "$exp" ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$got'"
+ wait
+fi
+(
+ print -n 'prompt1: '
+ sleep .1
+ print line2
+ sleep .1
+ print -n 'prompt2: '
+ sleep .1
+) | {
+ read -t2 -n 1000 line1
+ read -t2 -n 1000 line2
+ read -t2 -n 1000 line3
+ read -t2 -n 1000 line4
+}
+[[ $? == 0 ]] && err_exit 'should have timed out'
+[[ $line1 == 'prompt1: ' ]] || err_exit "line1 should be 'prompt1: '"
+[[ $line2 == line2 ]] || err_exit "line2 should be line2"
+[[ $line3 == 'prompt2: ' ]] || err_exit "line3 should be 'prompt2: '"
+[[ ! $line4 ]] || err_exit "line4 should be empty"
+
+if $SHELL -c "export LC_ALL=C.UTF-8; c=$'\342\202\254'; [[ \${#c} == 1 ]]" 2>/dev/null
+then lc_utf8=C.UTF-8
+else lc_utf8=''
+fi
+
+typeset -a e o=(-n2 -N2)
+integer i
+set -- \
+ 'a' 'bcd' 'a bcd' 'ab cd' \
+ 'ab' 'cd' 'ab cd' 'ab cd' \
+ 'abc' 'd' 'ab cd' 'ab cd' \
+ 'abcd' '' 'ab cd' 'ab cd'
+while (( $# >= 3 ))
+do a=$1
+ b=$2
+ e[0]=$3
+ e[1]=$4
+ shift 4
+ for ((i = 0; i < 2; i++))
+ do for lc_all in C $lc_utf8
+ do g=$(LC_ALL=$lc_all $SHELL -c "{ print -n '$a'; sleep 0.2; print -n '$b'; sleep 0.2; } | { read ${o[i]} a; print -n \$a; read a; print -n \ \$a; }")
+ [[ $g == "${e[i]}" ]] || err_exit "LC_ALL=$lc_all read ${o[i]} from pipe '$a $b' failed -- expected '${e[i]}', got '$g'"
+ done
+ done
+done
+
+if [[ $lc_utf8 ]]
+then export LC_ALL=$lc_utf8
+ typeset -a c=( '' 'A' $'\303\274' $'\342\202\254' )
+ integer i w
+ typeset o
+ if (( ${#c[2]} == 1 && ${#c[3]} == 1 ))
+ then for i in 1 2 3
+ do for o in n N
+ do for w in 1 2 3
+ do print -nr "${c[w]}" | read -${o}${i} g
+ if [[ $o == N ]] && (( i > 1 ))
+ then e=''
+ else e=${c[w]}
+ fi
+ [[ $g == "$e" ]] || err_exit "read -${o}${i} failed for '${c[w]}' -- expected '$e', got '$g'"
+ done
+ done
+ done
+ fi
+fi
+
+exec 3<&2
+file=$tmp/file
+redirect 5>$file 2>&5
+print -u5 -f 'This is a test\n'
+print -u2 OK
+exec 2<&3
+exp=$'This is a test\nOK'
+got=$(< $file)
+[[ $got == $exp ]] || err_exit "output garbled when stderr is duped -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+print 'hello world' > $file
+1<>; $file 1># ((5))
+(( $(wc -c < $file) == 5 )) || err_exit "$file was not truncate to 5 bytes"
+
+$SHELL -c "PS4=':2:'
+ exec 1> $tmp/21.out 2> $tmp/22.out
+ set -x
+ printf ':1:A:'
+ print \$(:)
+ print :1:Z:" 1> $tmp/11.out 2> $tmp/12.out
+[[ -s $tmp/11.out ]] && err_exit "standard output leaked past redirection"
+[[ -s $tmp/12.out ]] && err_exit "standard error leaked past redirection"
+exp=$':1:A:\n:1:Z:'
+got=$(<$tmp/21.out)
+[[ $exp == "$got" ]] || err_exit "standard output garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+exp=$':2:printf :1:A:\n:2::\n:2:print\n:2:print :1:Z:'
+got=$(<$tmp/22.out)
+[[ $exp == "$got" ]] || err_exit "standard error garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
+tmp=$tmp $SHELL 2> /dev/null -c 'exec 3<&1 ; exec 1<&- ; exec > $tmp/outfile;print foobar' || err_exit 'exec 1<&- causes failure'
+[[ $(<$tmp/outfile) == foobar ]] || err_exit 'outfile does not contain foobar'
+
+print hello there world > $tmp/foobar
+sed -e 's/there //' $tmp/foobar >; $tmp/foobar
+[[ $(<$tmp/foobar) == 'hello world' ]] || err_exit '>; redirection not working on simple command'
+print hello there world > $tmp/foobar
+{ sed -e 's/there //' $tmp/foobar;print done;} >; $tmp/foobar
+[[ $(<$tmp/foobar) == $'hello world\ndone' ]] || err_exit '>; redirection not working for compound command'
+print hello there world > $tmp/foobar
+$SHELL -c "sed -e 's/there //' $tmp/foobar >; $tmp/foobar"
+[[ $(<$tmp/foobar) == 'hello world' ]] || err_exit '>; redirection not working with -c on a simple command'
+
+rm -f "$tmp/junk"
+for (( i=1; i < 50; i++ ))
+do out=$(/bin/ls "$tmp/junk" 2>/dev/null)
+ if (( $? == 0 ))
+ then err_exit 'wrong error code with redirection'
+ break
+ fi
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/leaks.sh b/src/cmd/ksh93/tests/leaks.sh
new file mode 100755
index 0000000..8d89b05
--- /dev/null
+++ b/src/cmd/ksh93/tests/leaks.sh
@@ -0,0 +1,68 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+builtin vmstate 2>/dev/null || exit 0
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+# test for variable reset leak #
+
+function test_reset
+{
+ integer i n=$1
+
+ for ((i = 0; i < n; i++))
+ do u=$i
+ done
+}
+
+n=1000
+
+# one round to get to steady state -- sensitive to -x
+
+test_reset $n
+a=0$(vmstate --format='+%(size)u')
+b=0$(vmstate --format='+%(size)u')
+
+test_reset $n
+a=0$(vmstate --format='+%(size)u')
+test_reset $n
+b=0$(vmstate --format='+%(size)u')
+
+if (( b > a ))
+then err_exit "variable value reset memory leak -- $((b-a)) bytes after $n iterations"
+fi
+
+# buffer boundary tests
+
+for exp in 65535 65536
+do got=$($SHELL -c 'x=$(printf "%.*c" '$exp' x); print ${#x}' 2>&1)
+ [[ $got == $exp ]] || err_exit "large command substitution failed -- expected $exp, got $got"
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/locale.sh b/src/cmd/ksh93/tests/locale.sh
new file mode 100755
index 0000000..60209dc
--- /dev/null
+++ b/src/cmd/ksh93/tests/locale.sh
@@ -0,0 +1,319 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+unset LANG ${!LC_*}
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+cd $tmp || exit
+
+a=$($SHELL -c '/' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+b=$($SHELL -c '(LC_ALL=debug / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
+b=$($SHELL -c '(LC_ALL=debug; / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
+
+# test shift-jis \x81\x40 ... \x81\x7E encodings
+# (shift char followed by 7 bit ascii)
+
+typeset -i16 chr
+for locale in $(PATH=/bin:/usr/bin locale -a 2>/dev/null | grep -i jis)
+do export LC_ALL=$locale
+ for ((chr=0x40; chr<=0x7E; chr++))
+ do c=${chr#16#}
+ for s in \\x81\\x$c \\x$c
+ do b="$(printf "$s")"
+ eval n=\$\'$s\'
+ [[ $b == "$n" ]] || err_exit "LC_ALL=$locale printf difference for \"$s\" -- expected '$n', got '$b'"
+ u=$(print -- $b)
+ q=$(print -- "$b")
+ [[ $u == "$q" ]] || err_exit "LC_ALL=$locale quoted print difference for \"$s\" -- $b => '$u' vs \"$b\" => '$q'"
+ done
+ done
+done
+
+# this locale is supported by ast on all platforms
+# EU for { decimal_point="," thousands_sep="." }
+
+locale=C_EU.UTF-8
+
+export LC_ALL=C
+
+# test multibyte value/trace format -- $'\303\274' is UTF-8 u-umlaut
+
+c=$(LC_ALL=C $SHELL -c "printf $':%2s:\n' $'\303\274'")
+u=$(LC_ALL=$locale $SHELL -c "printf $':%2s:\n' $'\303\274'" 2>/dev/null)
+if [[ "$c" != "$u" ]]
+then LC_ALL=$locale
+ x=$'+2+ typeset item.text\
++3+ item.text=\303\274\
++4+ print -- \303\274\
+\303\274\
++5+ eval $\'arr[0]=(\\n\\ttext=\\303\\274\\n)\'
++2+ arr[0].text=ü\
++6+ print -- \303\274\
+ü\
++7+ eval txt=$\'(\\n\\ttext=\\303\\274\\n)\'
++2+ txt.text=\303\274\
++8+ print -- \'(\' text=$\'\\303\\274\' \')\'\
+( text=\303\274 )'
+ u=$(LC_ALL=$locale PS4='+$LINENO+ ' $SHELL -x -c "
+ item=(typeset text)
+ item.text=$'\303\274'
+ print -- \"\${item.text}\"
+ eval \"arr[0]=\$item\"
+ print -- \"\${arr[0].text}\"
+ eval \"txt=\${arr[0]}\"
+ print -- \$txt
+ " 2>&1)
+ [[ "$u" == "$x" ]] || err_exit LC_ALL=$locale multibyte value/trace format failed
+
+ x=$'00fc\n20ac'
+ u=$(LC_ALL=$locale $SHELL -c $'printf "%04x\n" \$\'\"\303\274\"\' \$\'\"\xE2\x82\xAC\"\'')
+ [[ $u == $x ]] || err_exit LC_ALL=$locale multibyte %04x printf format failed
+fi
+
+if (( $($SHELL -c $'export LC_ALL='$locale$'; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ))
+then LC_ALL=$locale $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly'
+fi
+
+#$SHELL -c 'export LANG='$locale'; printf "\u[20ac]\u[20ac]" > $tmp/two_euro_chars.txt'
+printf $'\342\202\254\342\202\254' > $tmp/two_euro_chars.txt
+exp="6 2 6"
+set -- $($SHELL -c "
+ unset LC_CTYPE
+ export LANG=$locale
+ export LC_ALL=C
+ command wc -C < $tmp/two_euro_chars.txt
+ unset LC_ALL
+ command wc -C < $tmp/two_euro_chars.txt
+ export LC_ALL=C
+ command wc -C < $tmp/two_euro_chars.txt
+")
+got=$*
+[[ $got == $exp ]] || err_exit "command wc LC_ALL default failed -- expected '$exp', got '$got'"
+set -- $($SHELL -c "
+ if builtin wc 2>/dev/null || builtin -f cmd wc 2>/dev/null
+ then unset LC_CTYPE
+ export LANG=$locale
+ export LC_ALL=C
+ wc -C < $tmp/two_euro_chars.txt
+ unset LC_ALL
+ wc -C < $tmp/two_euro_chars.txt
+ export LC_ALL=C
+ wc -C < $tmp/two_euro_chars.txt
+ fi
+")
+got=$*
+[[ $got == $exp ]] || err_exit "builtin wc LC_ALL default failed -- expected '$exp', got '$got'"
+
+# multibyte char straddling buffer boundary
+
+{
+ unset i
+ integer i
+ for ((i = 0; i < 163; i++))
+ do print "#234567890123456789012345678901234567890123456789"
+ done
+ printf $'%-.*c\n' 15 '#'
+ for ((i = 0; i < 2; i++))
+ do print $': "\xe5\xae\x9f\xe8\xa1\x8c\xe6\xa9\x9f\xe8\x83\xbd\xe3\x82\x92\xe8\xa1\xa8\xe7\xa4\xba\xe3\x81\x97\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82" :'
+ done
+} > ko.dat
+
+LC_ALL=$locale $SHELL < ko.dat 2> /dev/null || err_exit "script with multibyte char straddling buffer boundary fails"
+
+# exp LC_ALL LC_NUMERIC LANG
+set -- \
+ 2,5 $locale C '' \
+ 2.5 C $locale '' \
+ 2,5 $locale '' C \
+ 2,5 '' $locale C \
+ 2.5 C '' $locale \
+ 2.5 '' C $locale \
+
+unset a b c
+unset LC_ALL LC_NUMERIC LANG
+integer a b c
+while (( $# >= 4 ))
+do exp=$1
+ unset H V
+ typeset -A H
+ typeset -a V
+ [[ $2 ]] && V[0]="export LC_ALL=$2;"
+ [[ $3 ]] && V[1]="export LC_NUMERIC=$3;"
+ [[ $4 ]] && V[2]="export LANG=$4;"
+ for ((a = 0; a < 3; a++))
+ do for ((b = 0; b < 3; b++))
+ do if (( b != a ))
+ then for ((c = 0; c < 3; c++))
+ do if (( c != a && c != b ))
+ then T=${V[$a]}${V[$b]}${V[$c]}
+ if [[ ! ${H[$T]} ]]
+ then H[$T]=1
+ got=$($SHELL -c "${T}print \$(( $exp ))" 2>&1)
+ [[ $got == $exp ]] || err_exit "${T} sequence failed -- expected '$exp', got '$got'"
+ fi
+ fi
+ done
+ fi
+ done
+ done
+ shift 4
+done
+
+# setocale(LC_ALL,"") after setlocale() initialization
+
+printf 'f1\357\274\240f2\n' > input1
+printf 't2\357\274\240f1\n' > input2
+printf '\357\274\240\n' > delim
+print "export LC_ALL=$locale
+join -j1 1 -j2 2 -o 1.1 -t \$(cat delim) input1 input2 > out" > script
+$SHELL -c 'unset LANG ${!LC_*}; $SHELL ./script' ||
+err_exit "join test script failed -- exit code $?"
+exp="f1"
+got="$(<out)"
+[[ $got == "$exp" ]] || err_exit "LC_ALL test script failed -- expected '$exp', got '$got'"
+
+# multibyte identifiers
+
+exp=OK
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]=OK; print ${\u[5929]}' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte variable definition/expansion failed -- expected '$exp', got '$got'"
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'function \u[5929]\n{\nprint OK;\n}; \u[5929]' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte ksh function definition/execution failed -- expected '$exp', got '$got'"
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]()\n{\nprint OK;\n}; \u[5929]' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte posix function definition/execution failed -- expected '$exp', got '$got'"
+
+# this locale is supported by ast on all platforms
+# mainly used to debug multibyte and message translation code
+# however wctype is not supported but that's ok for these tests
+
+locale=debug
+
+if [[ "$(LC_ALL=$locale $SHELL <<- \+EOF+
+ x=a<1z>b<2yx>c
+ print ${#x}
+ +EOF+)" != 5
+ ]]
+then err_exit '${#x} not working with multibyte locales'
+fi
+
+dir=_not_found_
+exp=2
+for cmd in \
+ "cd $dir; export LC_ALL=debug; cd $dir" \
+ "cd $dir; LC_ALL=debug cd $dir" \
+
+do got=$($SHELL -c "$cmd" 2>&1 | sort -u | wc -l)
+ (( ${got:-0} == $exp )) || err_exit "'$cmd' sequence failed -- error message not localized"
+done
+exp=121
+for lc in LANG LC_MESSAGES LC_ALL
+do for cmd in "($lc=$locale;cd $dir)" "$lc=$locale;cd $dir;unset $lc" "function tst { typeset $lc=$locale;cd $dir; }; tst"
+ do tst="$lc=C;cd $dir;$cmd;cd $dir;:"
+ $SHELL -c "unset LANG \${!LC_*}; $SHELL -c '$tst'" > out 2>&1 ||
+ err_exit "'$tst' failed -- exit status $?"
+ integer id=0
+ unset msg
+ typeset -A msg
+ got=
+ while read -r line
+ do line=${line##*:}
+ if [[ ! ${msg[$line]} ]]
+ then msg[$line]=$((++id))
+ fi
+ got+=${msg[$line]}
+ done < out
+ [[ $got == $exp ]] || err_exit "'$tst' failed -- expected '$exp', got '$got'"
+ done
+done
+
+exp=123
+got=$(LC_ALL=debug $SHELL -c "a<2A@>z=$exp; print \$a<2A@>z")
+[[ $got == $exp ]] || err_exit "multibyte debug locale \$a<2A@>z failed -- expected '$exp', got '$got'"
+
+unset LC_ALL LC_MESSAGES
+export LANG=debug
+function message
+{
+ print -r $"An error occurred."
+}
+exp=$'(libshell,3,46)\nAn error occurred.\n(libshell,3,46)'
+alt=$'(debug,message,libshell,An error occurred.)\nAn error occurred.\n(debug,message,libshell,An error occurred.)'
+got=$(message; LANG=C message; message)
+[[ $got == "$exp" || $got == "$alt" ]] || {
+ EXP=$(printf %q "$exp")
+ ALT=$(printf %q "$alt")
+ GOT=$(printf %q "$got")
+ err_exit "LANG change not seen by function -- expected $EXP or $ALT, got $GOT"
+}
+
+a_thing=fish
+got=$(print -r aa$"\\ahello \" /\\${a_thing}/\\"zz)
+exp='aa(debug,'$Command',libshell,\ahello " /\fish/\)zz'
+[[ $got == "$exp" ]] || err_exit "$\"...\" containing expansions fails: expected $exp, got $got"
+
+exp='(debug,'$Command',libshell,This is a string\n)'
+typeset got=$"This is a string\n"
+[[ $got == "$exp" ]] || err_exit "$\"...\" in assignment expansion fails: expected $exp got $got"
+
+unset LANG
+
+LC_ALL=C
+x=$"hello"
+[[ $x == hello ]] || err_exit 'assignment of message strings not working'
+
+# tests for multibyte characteer at buffer boundary
+{
+ print 'cat << \\EOF'
+ for ((i=1; i < 164; i++))
+ do print 123456789+123456789+123456789+123456789+123456789
+ done
+ print $'next character is multibyte<2b|>c<3d|\>foo'
+ for ((i=1; i < 10; i++))
+ do print 123456789+123456789+123456789+123456789+123456789
+ done
+ print EOF
+} > script$$.1
+chmod +x script$$.1
+x=$( LC_ALL=debug $SHELL ./script$$.1)
+[[ ${#x} == 8641 ]] || err_exit 'here doc contains wrong number of chars with multibyte locale'
+[[ $x == *$'next character is multibyte<2b|>c<3d|\>foo'* ]] || err_exit "here_doc doesn't contain line with multibyte chars"
+
+
+x=$(LC_ALL=debug $SHELL -c 'x="a<2b|>c";print -r -- ${#x}')
+(( x == 3 )) || err_exit 'character length of multibyte character should be 3'
+x=$(LC_ALL=debug $SHELL -c 'typeset -R10 x="a<2b|>c";print -r -- "${x}"')
+[[ $x == ' a<2b|>c' ]] || err_exit 'typeset -R10 should begin with three spaces'
+x=$(LC_ALL=debug $SHELL -c 'typeset -L10 x="a<2b|>c";print -r -- "${x}"')
+[[ $x == 'a<2b|>c ' ]] || err_exit 'typeset -L10 should end in three spaces'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/math.sh b/src/cmd/ksh93/tests/math.sh
new file mode 100644
index 0000000..59884f5
--- /dev/null
+++ b/src/cmd/ksh93/tests/math.sh
@@ -0,0 +1,202 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors < 127 && Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+set -o nounset
+
+typeset tmp
+
+# create temporary test directory
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+cd $tmp || exit
+
+function test_arithmetric_expression_accesss_array_element_through_nameref
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound -r -a tests=(
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1][3]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3][5]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3][5]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1][3][5]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3][5]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3][5]=90 ; function x { nameref nz=${1}[$2][$3][$4] ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@ 1 3 5' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -A @@VAR@@ ; @@VAR@@[1]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -A @@VAR@@=( [1]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ )
+
+ typeset testname
+ integer i
+ typeset mode
+ typeset cmd
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ # fixme: This list should include "typeset -lX" and "typeset -X" but ast-ksh.2010-03-09 fails like this:
+ # 'typeset -X -a z ; z[1][3]=90 ; function x { nameref nz=$1 ; print " $(( nz ))==$(( $nz ))" ; } ; x z[1][3]'
+ # + typeset -X -a z
+ # + z[1][3]=90
+ # + x 'z[1][3]'
+ # /home/test001/bin/ksh[1]: x: line 1: x1.68000000000000000000000000000000p: no parent
+ for ty in \
+ 'typeset' \
+ 'integer' \
+ 'float' \
+ 'typeset -i' \
+ 'typeset -si' \
+ 'typeset -li' \
+ 'typeset -E' \
+ 'typeset -F' \
+ 'typeset -X' \
+ 'typeset -lE' \
+ 'typeset -lX' \
+ 'typeset -lF' ; do
+ for mode in \
+ 'plain' \
+ 'in_compound' \
+ 'in_indexed_compound_array' \
+ 'in_2d_indexed_compound_array' \
+ 'in_4d_indexed_compound_array' \
+ 'in_associative_compound_array' \
+ 'in_compound_nameref' \
+ 'in_indexed_compound_array_nameref' \
+ 'in_2d_indexed_compound_array_nameref' \
+ 'in_4d_indexed_compound_array_nameref' \
+ 'in_associative_compound_array_nameref' \
+ ; do
+ nameref tst=tests[i]
+
+ cmd="${tst.cmd//@@TYPE@@/${ty}}"
+
+ case "${mode}" in
+ 'plain')
+ cmd="${cmd//@@VAR@@/z}"
+ ;;
+
+ 'in_compound')
+ cmd="compound c ; ${cmd//@@VAR@@/c.z}"
+ ;;
+ 'in_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[11].z}"
+ ;;
+ 'in_2d_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[17][19].z}"
+ ;;
+ 'in_4d_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[17][19][23][27].z}"
+ ;;
+ 'in_associative_compound_array')
+ cmd="compound -A c ; ${cmd//@@VAR@@/c[info].z}"
+ ;;
+
+ 'in_compound_nameref')
+ cmd="compound c ; nameref ncr=c.z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[11].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_2d_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[17][19].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_4d_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[17][19][23][27].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_associative_compound_array_nameref')
+ cmd="compound -A c ; nameref ncr=c[info].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ *)
+ err_exit "Unexpected mode ${mode}"
+ ;;
+ esac
+
+ testname="${0}/${cmd}"
+#set -x
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+#set +x
+
+ [[ "${out.stdout}" == ${tst.stdoutpattern} ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "${tst.stdoutpattern}"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+ done
+ done
+
+ return 0
+}
+
+function test_has_iszero
+{
+ typeset str
+ integer i
+
+ typeset -r -a tests=(
+ '(( iszero(0) )) && print "OK"'
+ '(( iszero(0.) )) && print "OK"'
+ '(( iszero(-0) )) && print "OK"'
+ '(( iszero(-0.) )) && print "OK"'
+ 'float n=0. ; (( iszero(n) )) && print "OK"'
+ 'float n=+0. ; (( iszero(n) )) && print "OK"'
+ 'float n=-0. ; (( iszero(n) )) && print "OK"'
+ 'float n=1. ; (( iszero(n) )) || print "OK"'
+ 'float n=1. ; (( iszero(n-1.) )) && print "OK"'
+ 'float n=-1. ; (( iszero(n+1.) )) && print "OK"'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ str="$( ${SHELL} -o errexit -c "${tests[i]}" 2>&1 )" || err_exit "test $i: returned non-zero exit code $?"
+ [[ "${str}" == 'OK' ]] || err_exit "test $i: expected 'OK', got '${str}'"
+ done
+
+ return 0
+}
+
+# run tests
+test_arithmetric_expression_accesss_array_element_through_nameref
+test_has_iszero
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/nameref.sh b/src/cmd/ksh93/tests/nameref.sh
new file mode 100755
index 0000000..7eb0b21
--- /dev/null
+++ b/src/cmd/ksh93/tests/nameref.sh
@@ -0,0 +1,658 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function checkref
+{
+ nameref foo=$1 bar=$2
+ if [[ $foo != $bar ]]
+ then err_exit "foo=$foo != bar=$bar"
+ fi
+ foo=hello
+ if [[ $foo != $bar ]]
+ then err_exit "foo=$foo != bar=$bar"
+ fi
+ foo.child=child
+ if [[ ${foo.child} != ${bar.child} ]]
+ then err_exit "foo.child=${foo.child} != bar=${bar.child}"
+ fi
+}
+
+name=first
+checkref name name
+name.child=second
+checkref name name
+.foo=top
+.foo.bar=next
+checkref .foo.bar .foo.bar
+if [[ ${.foo.bar} != hello ]]
+then err_exit ".foo.bar=${.foo.bar} != hello"
+fi
+if [[ ${.foo.bar.child} != child ]]
+then err_exit ".foo.bar.child=${.foo.bar.child} != child"
+fi
+function func1
+{
+ nameref color=$1
+ func2 color
+}
+
+function func2
+{
+ nameref color=$1
+ set -s -- ${!color[@]}
+ print -r -- "$@"
+}
+
+typeset -A color
+color[apple]=red
+color[grape]=purple
+color[banana]=yellow
+if [[ $(func1 color) != 'apple banana grape' ]]
+then err_exit "nameref or nameref not working"
+fi
+nameref x=.foo.bar
+if [[ ${!x} != .foo.bar ]]
+then err_exit "${!x} not working"
+fi
+typeset +n x $(typeset +n)
+unset x
+nameref x=.foo.bar
+function x.set
+{
+ [[ ${.sh.value} ]] && print hello
+}
+if [[ $(.foo.bar.set) != $(x.set) ]]
+then err_exit "function references not working"
+fi
+if [[ $(typeset +n) != x ]]
+then err_exit "typeset +n doesn't list names of reference variables"
+fi
+if [[ $(typeset -n) != x=.foo.bar ]]
+then err_exit "typeset +n doesn't list values of reference variables"
+fi
+file=$tmp/test
+typeset +n foo bar 2> /dev/null
+unset foo bar
+export bar=foo
+nameref foo=bar
+if [[ $foo != foo ]]
+then err_exit "value of nameref foo != $foo"
+fi
+cat > $file <<\!
+print -r -- $foo
+!
+chmod +x "$file"
+y=$( $file)
+if [[ $y != '' ]]
+then err_exit "reference variable not cleared"
+fi
+{
+ command nameref xx=yy
+ command nameref yy=xx
+} 2> /dev/null && err_exit "self reference not detected"
+typeset +n foo bar
+unset foo bar
+set foo
+nameref bar=$1
+foo=hello
+if [[ $bar != hello ]]
+then err_exit 'nameref of positional paramters outside of function not working'
+fi
+unset foo bar
+bar=123
+function foobar
+{
+ typeset -n foo=bar
+ typeset -n foo=bar
+}
+foobar 2> /dev/null || err_exit 'nameref not unsetting previous reference'
+(
+ nameref short=verylong
+ short=( A=a B=b )
+ if [[ ${verylong.A} != a ]]
+ then err_exit 'nameref short to longname compound assignment error'
+ fi
+) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error'
+unset x
+if [[ $(var1=1 var2=2
+ for i in var1 var2
+ do nameref x=$i
+ print $x
+ done) != $'1\n2' ]]
+then err_exit 'for loop nameref optimization error'
+fi
+if [[ $(typeset -A var1 var2
+ var1[sub1]=1 var2[sub2]=1
+ for i in var1 var2
+ do
+ typeset -n array=$i
+ print ${!array[*]}
+ done) != $'sub1\nsub2' ]]
+then err_exit 'for loop nameref optimization test2 error'
+fi
+
+unset -n x foo bar
+if [[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]]
+then err_exit 'for loop optimization with namerefs not working'
+fi
+if [[ $(
+ p=(x=(r=3) y=(r=4))
+ for i in x y
+ do nameref x=p.$i
+ print ${x.r}
+ done
+) != $'3\n4' ]]
+then err_exit 'nameref optimization error'
+fi
+[[ $(
+unset x y var
+var=(foo=bar)
+for i in y var
+do typeset -n x=$i
+ if [[ ${!x.@} ]]
+ then print ok
+ fi
+ typeset +n x
+done) != ok ]] && err_exit 'invalid for loop optimization of name references'
+function setval # name value
+{
+ nameref arg=$1
+ nameref var=arg.bar
+ var=$2
+}
+foo=( integer bar=0)
+setval foo 5
+(( foo.bar == 5)) || err_exit 'nested nameref not working'
+function selfref
+{
+ typeset -n ps=$1
+ print -r -- "${ps}"
+}
+ps=(a=1 b=2)
+[[ $(selfref ps) == *a=1* ]] || err_exit 'local nameref cannot reference global variable of the same name'
+function subref
+{
+ typeset -n foo=$1
+ print -r -- ${foo.a}
+}
+[[ $(subref ps) == 1 ]] || err_exit 'local nameref cannot reference global variable child'
+
+function local
+{
+ typeset ps=(typeset -i a=3 b=4)
+ [[ $(subref ps) == 3 ]] || err_exit 'local nameref cannot reference caller compound variable'
+}
+local
+unset -f local
+function local
+{
+ qs=(integer a=3; integer b=4)
+}
+local 2> /dev/null || err_exit 'function local has non-zero exit status'
+[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
+unset fun i
+foo=(x=hi)
+function fun
+{
+ nameref i=$1
+ print -r -- "${i.x}"
+}
+i=foo
+[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails'
+unset -n foo bar
+typeset -A foo
+foo[x.y]=(x=3 y=4)
+nameref bar=foo[x.y]
+[[ ${bar.x} == 3 ]] || err_exit 'nameref to subscript containing . fails'
+[[ ${!bar} == 'foo[x.y]' ]] || err_exit '${!var} not correct for nameref to an array instance'
+typeset +n bar
+nameref bar=foo
+[[ ${!bar} == foo ]] || err_exit '${!var} not correct for nameref to array variable'
+$SHELL -c 'function bar { nameref x=foo[++];};typeset -A foo;bar' 2> /dev/null ||err_exit 'nameref of associative array tries to evaluate subscript'
+i=$($SHELL -c 'nameref foo=bar; bar[2]=(x=3 y=4); nameref x=foo[2].y;print -r -- $x' 2> /dev/null)
+[[ $i == 4 ]] || err_exit 'creating reference from subscripted variable whose name is a reference failed'
+[[ $($SHELL 2> /dev/null <<- '+++EOF'
+ function bar
+ {
+ nameref x=$1
+ print -r -- "$x"
+ }
+ function foo
+ {
+ typeset var=( foo=hello)
+ bar var
+ }
+ foo
++++EOF
+) == *foo=hello* ]] || err_exit 'unable to display compound variable from name reference of local variable'
+#set -x
+for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
+do [[ $($SHELL 2> /dev/null <<- ++EOF++
+ i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x"
+ ++EOF++
+) != foo ]] && err_exit 'nameref x=a[$c] '"not working for c=$c"
+done
+for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
+do [[ $($SHELL 2> /dev/null <<- ++EOF++
+ i=\\$c;typeset -A a; a[\$i]=foo;b=a[\$i];typeset -n x=\$b; print "\$x"
+ ++EOF++
+) != foo ]] && err_exit 'nameref x=$b with b=a[$c] '"not working for c=$c"
+done
+
+unset -n foo x
+unset foo x
+typeset -A foo
+nameref x=foo[xyz]
+foo[xyz]=ok
+[[ $x == ok ]] || err_exit 'nameref to unset subscript not working'
+function function2
+{
+ nameref v=$1
+ v.x=19 v.y=20
+}
+function function1
+{
+ typeset compound_var=()
+ function2 compound_var
+ printf "x=%d, y=%d\n" compound_var.x compound_var.y
+}
+x="$(function1)"
+[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'"
+typeset +n bar
+unset foo bar
+[[ $(function a
+{
+ for i in foo bar
+ do typeset -n v=$i
+ print $v
+ done | cat
+}
+foo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken'
+function a
+{
+ typeset -n v=vars.data._1
+ print "${v.a} ${v.b}"
+}
+vars=(data=())
+vars.data._1.a=a.1
+vars.data._1.b=b.1
+[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- '
+typeset +n bam zip foo
+unset bam zip foo
+typeset -A foo
+foo[2]=bar
+typeset -n bam=foo[2]
+typeset -n zip=bam
+[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails'
+[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference'
+[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference'
+[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set'
+[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set'
+[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference'
+[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set'
+
+unset ref x
+typeset -n ref
+x=3
+function foobar
+{
+ typeset xxx=3
+ ref=xxx
+ return 0
+}
+foobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail'
+[[ -v ref ]] && err_exit '$ref should be unset'
+ref=x
+[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3"
+function foobar
+{
+ typeset fvar=()
+ typeset -n ref=fvar.foo
+ ref=ok
+ print -r $ref
+}
+[[ $(foobar) == ok ]] 2> /dev/null || err_exit 'nameref in function not creating variable in proper scope'
+function foobar
+{
+ nameref doc=docs
+ nameref bar=doc.num
+ [[ $bar == 2 ]] || err_exit 'nameref scoping error'
+}
+
+docs=(num=2)
+foobar
+
+typeset +n x y
+unset x y
+typeset -A x
+x[a]=(b=c)
+typeset -n y=x[a]
+[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}'
+
+typeset +n v
+v=()
+k=a.b.c/d
+command typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment'
+
+typeset _n sp
+nameref sp=addrsp
+sp[14]=( size=1 )
+[[ -v sp[19] ]] && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set'
+
+function fun2
+{
+ nameref var=$1
+ var.foo=bar
+}
+
+function fun1
+{
+ compound -S container
+ fun2 container
+ [[ $container == *foo=bar* ]] || err_exit 'name references to static compound variables in parent scope not working'
+}
+fun1
+
+function fun2
+{
+ nameref var=$1
+ var.foo=bar
+}
+
+typeset -T container_t=(
+ typeset foo
+)
+
+function fun1
+{
+ container_t -S container
+ fun2 container
+ [[ $container == *foo=bar* ]] || err_exit 'name references to static type variables in parent scope not working'
+}
+fun1
+
+function fun2
+{
+ nameref var=$1
+ nameref node=var.foo
+ node=bar
+}
+function fun3
+{
+ fun2 container #2> /dev/null
+}
+compound container
+fun3
+[[ $container == *foo=bar* ]] || err_exit 'name reference to a name reference variable in a function not working'
+
+typeset -A x=( [a]=1 )
+nameref c=x[h]
+[[ -v x[h] ]] && err_exit 'creating reference to non-existant associative array element causes element to get added'
+
+unset a
+function x
+{
+ nameref a=a
+ (( $# > 0 )) && typeset -A a
+ a[a b]=${1-99} # this was cauing a syntax on the second call
+}
+x 7
+x 2> /dev/null
+[[ ${a[a b]} == 99 ]] || err_exit 'nameref not handling subscript correctly'
+
+nameref sizes=baz
+typeset -A -i sizes
+sizes[bar]=1
+[[ ${sizes[*]} == 1 ]] || err_exit 'adding -Ai attribute to name referenced variable not working'
+
+$SHELL 2> /dev/null -c 'nameref foo=bar; typeset -A foo; (( (x=foo[a])==0 ))' || err_exit 'references inside arithmetic expressions not working'
+:
+
+unset ar z
+integer -a ar
+nameref z=ar[0]
+(( z[2]=3))
+[[ ${ar[0][2]} == 3 ]] || err_exit "\${ar[0][2]} is '${ar[0][2]}' but should be 3"
+(( ar[0][2] == 3 )) || err_exit "ar[0][2] is '${ar[0][2]}' but should be 3"
+
+unset c x
+typeset +n c x
+compound c=( typeset -a x )
+nameref x=c.x
+x[4]=1
+[[ ${ typeset -p c.x ;} == *-C* ]] && err_exit 'c.x should not have -C attributes'
+
+{ $SHELL 2> /dev/null <<- \EOF
+ typeset -T xxx_t=(
+ float x=1 y=2
+ typeset name=abc
+ )
+ xxx_t x
+ nameref r=x.y
+ [[ $r == 2 ]] || exit 1
+ unset x
+ [[ ${!r} == .deleted ]] || exit 2
+EOF
+} 2> /dev/null #|| print -u2 bad
+exitval=$?
+if [[ $(kill -l $exitval) == SEGV ]]
+then print -u2 'name reference to unset type instance causes segmentation violation'
+else if((exitval))
+ then print -u2 'name reference to unset type instance not redirected to .deleted'
+ fi
+fi
+
+typeset +n nr
+unset c nr
+compound c
+compound -A c.a
+nameref nr=c.a[hello]
+[[ ${!nr} == "c.a[hello]" ]] || err_exit 'name reference nr to unset associative array instance does not expand ${!nr} correctly.'
+
+typeset +n nr
+compound -a c.b
+nameref nr=c.b[2]
+[[ ${!nr} == "c.b[2]" ]] || err_exit 'name reference nr to unset indexed array instance does not expand ${!nr} correctly.'
+
+typeset +n a b
+unset a b
+typeset -n a=ls[0] b=ls[1]
+read line << \!
+3 4
+!
+set -A ls -- $line
+[[ $a == 3 ]] || err_exit 'name reference to ls[0] when ls is not an array fails'
+
+$SHELL 2> /dev/null <<-\EOF || err_exit 'nameref to array element fails'
+ set -o errexit
+ function bf {
+ nameref treename=$1
+ nodepath="treename" ;
+ nameref x="$nodepath"
+ compound -A x.nodes
+ nameref node=treename.nodes[4]
+ node=()
+ typeset +p node.elements
+ }
+ compound c
+ bf c
+EOF
+
+function add_compound
+{
+ nameref arr=$1
+ arr[34]+=( float val=1.1 )
+}
+compound -a rootcpv
+nameref mycpv=rootcpv[4][8][16][32][64]
+compound -a mycpv.myindexedcompoundarray
+add_compound mycpv.myindexedcompoundarray
+(( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit 'nameref scoping error'
+
+function add_file_to_tree
+{
+ nameref node=$1
+ compound -A node.elements
+ node.elements[/]=(filepath=foobar)
+}
+function main
+{
+ compound filetree
+ add_file_to_tree filetree
+}
+main 2> /dev/null
+[[ $? == 0 ]] || err_exit 'nameref binding to calling function compound variable failed'
+
+unset l
+typeset -a -C l
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6]
+exp=$(print -v l)
+unset l
+typeset -a -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4[6]
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working'
+unset l
+typeset -a -C l
+nameref l46=l[4][6]
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l46
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l46=l[4][6] not working'
+
+exp=$'(\n\t[4]=(\n\t\ttypeset -a ar=(\n\t\t\t1\n\t\t\t2\n\t\t)\n\t\tb=1\n\t)\n)'
+unset l
+typeset +n l4
+typeset -a -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with indexed array read'
+
+unset l
+typeset +n l4
+typeset -A -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with associative array read'
+
+exp=$'(\n\t[9]=(\n\t\tfish=4\n\t)\n)'
+function add_eval
+{
+ nameref pos=$1
+ source /dev/stdin <<<"$2"
+ typeset -m pos=addvar
+}
+function do_local_plain
+{
+ compound -A local_tree
+ add_eval local_tree[9].fish "typeset -i addvar=4"
+ [[ $(print -v local_tree) == "$exp" ]] || err_exit 'do_local_plain failed'
+}
+function do_global_throughnameref
+{
+ nameref tr=global_tree
+ add_eval tr[9].fish "typeset -i addvar=4"
+ [[ $(print -v tr) == "$exp" ]] || err_exit 'do_global_throughnameref failed'
+}
+function do_local_throughnameref
+{
+ compound -A local_tree
+ nameref tr=local_tree
+ add_eval tr[9].fish "typeset -i addvar=4"
+ [[ $(print -v tr) == "$exp" ]] || err_exit 'do_local_throughnameref failed'
+}
+compound -A global_tree
+do_global_throughnameref
+do_local_throughnameref
+do_local_plain
+
+unset ar
+compound -a ar
+function read_c
+{
+ nameref v=$1
+ read -C v
+}
+print "( typeset -i x=36 ) " | read_c ar[5][9][2]
+exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)'
+[[ $(print -v ar) == "$exp" ]] || err_exit 'read into nameref of global array instance from within a function fails'
+
+function read_c
+{
+ nameref v=$1
+ read -C v
+}
+function main
+{
+ compound -a ar
+ nameref nar=ar
+ print "( typeset -i x=36 ) " | read_c nar[5][9][2]
+ exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v nar) == "$exp" ]] || err_exit 'read from a nameref variable from calling scope fails'
+}
+main
+
+function rf2
+{
+ nameref val=$1
+ read -C val
+}
+function rf
+{
+ nameref val=$1
+ rf2 val
+}
+function main
+{
+ compound c
+ typeset -A -C c.l
+ nameref l4=c.l[4]
+ printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | rf l4
+ exp=$'(\n\ttypeset -C -A l=(\n\t\t[4]=(\n\t\t\ttypeset -a ar=(\n\t\t\t\t1\n\t\t\t\t2\n\t\t\t\t3\n\t\t\t)\n\t\t\tb=1\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || err_exit 'read -C with nameref to array element fails'
+}
+main
+
+# bug reported by ek
+cfg=( alarms=(type=3))
+function a
+{
+ typeset -n y=$1
+ print -- ${y.type}
+}
+function b
+{
+ a $1
+}
+[[ $(a cfg.alarms) == 3 ]] || err_exit "nameref scoping error in function"
+[[ $(b cfg.alarms) == 3 ]] || err_exit "nameref scoping error in nested function"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/options.sh b/src/cmd/ksh93/tests/options.sh
new file mode 100755
index 0000000..c5b4c2e
--- /dev/null
+++ b/src/cmd/ksh93/tests/options.sh
@@ -0,0 +1,544 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+unset HISTFILE
+export LC_ALL=C ENV=
+
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if [[ $( ${SHELL-ksh} -s hello<<-\!
+ print $1
+ !
+ ) != hello ]]
+then err_exit "${SHELL-ksh} -s not working"
+fi
+x=$(
+ set -e
+ false && print bad
+ print good
+)
+if [[ $x != good ]]
+then err_exit 'sh -e not working'
+fi
+[[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working'
+
+env=$tmp/.env
+print $'(print -u1 aha) &>/dev/null\n(print -u2 aha) &>/dev/null' > $env
+rc=$tmp/.kshrc
+print $'PS1=""\nfunction env_hit\n{\n\tprint OK\n}' > $rc
+
+export ENV=/.$env
+if [[ ! -o privileged ]]
+then
+ got=$($SHELL -E -c : 2>/dev/null)
+ if [[ $g ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stdout -- expected '', got $got"
+ fi
+ got=$($SHELL -E -c : 2>&1 >/dev/null)
+ if [[ $got != *nonstandard* || $got == *$'\n'* ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stderr -- expected one diagnostic line, got $got"
+ fi
+fi
+
+export ENV=/.$rc
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $ENV file'
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E reads $ENV file'
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $ENV file'
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc reads $ENV file'
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $ENV file'
+else
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $ENV file'
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] ||
+ err_exit '-E ignores $ENV file'
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $ENV file'
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] ||
+ err_exit '--rc ignores $ENV file'
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $ENV file'
+ [[ $(print env_hit | $SHELL -i 2>&1) == "OK" ]] ||
+ err_exit '-i ignores $ENV file'
+fi
+
+export ENV=
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $HOME/.kshrc file'
+else
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit '-E ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit '--rc ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $HOME/.kshrc file'
+fi
+
+unset ENV
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $HOME/.kshrc file'
+else
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] ||
+ err_exit '-E ignores $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] ||
+ err_exit '--rc ignores $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $HOME/.kshrc file'
+fi
+
+rm -rf $tmp/.kshrc
+
+if command set -G 2> /dev/null
+then cd $tmp
+ mkdir bar foo
+ > bar.c > bam.c
+ > bar/foo.c > bar/bam.c
+ > foo/bam.c
+ set -- **.c
+ expected='bam.c bar.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **.c failed -- expected '$expected', got '$*'"
+ set -- **
+ expected='bam.c bar bar.c bar/bam.c bar/foo.c foo foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G ** failed -- expected '$expected', got '$*'"
+ set -- **/*.c
+ expected='bam.c bar.c bar/bam.c bar/foo.c foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **/*.c failed -- expected '$expected', got '$*'"
+ set -- **/bam.c
+ expected='bam.c bar/bam.c foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **/bam.c failed -- expected '$expected', got '$*'"
+ cd ~-
+fi
+
+cd $tmp
+t="<$$>.profile.<$$>"
+echo "echo '$t'" > .profile
+cp $SHELL ./-ksh
+if [[ -o privileged ]]
+then
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged -l reads .profile'
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login reads .profile'
+ [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login-shell reads .profile'
+ [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login_shell reads .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged exec -a -ksh ksh reads .profile'
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged ./-ksh reads .profile'
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged ./-ksh -p reads .profile'
+else
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] ||
+ err_exit '-l ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login-shell ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login_shell ignores .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>/dev/null) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>/dev/null ignores .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>&1 ignores .profile'
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] ||
+ err_exit './-ksh ignores .profile'
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
+ err_exit './-ksh -p does not ignore .profile'
+fi
+cd ~-
+rm -rf $tmp/.profile
+
+# { exec interactive login_shell restricted xtrace } in the following test
+
+for opt in \
+ allexport all-export all_export \
+ bgnice bg-nice bg_nice \
+ clobber emacs \
+ errexit err-exit err_exit \
+ glob \
+ globstar glob-star glob_star \
+ gmacs \
+ ignoreeof ignore-eof ignore_eof \
+ keyword log markdirs monitor notify \
+ pipefail pipe-fail pipe_fail \
+ trackall track-all track_all \
+ unset verbose vi \
+ viraw vi-raw vi_raw
+do old=$opt
+ if [[ ! -o $opt ]]
+ then old=no$opt
+ fi
+
+ set --$opt || err_exit "set --$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ [[ -o no$opt ]] && err_exit "[[ -o no$opt ]] failed"
+ [[ -o no-$opt ]] && err_exit "[[ -o no-$opt ]] failed"
+ [[ -o no_$opt ]] && err_exit "[[ -o no_$opt ]] failed"
+ [[ -o ?$opt ]] || err_exit "[[ -o ?$opt ]] failed"
+ [[ -o ?no$opt ]] || err_exit "[[ -o ?no$opt ]] failed"
+ [[ -o ?no-$opt ]] || err_exit "[[ -o ?no-$opt ]] failed"
+ [[ -o ?no_$opt ]] || err_exit "[[ -o ?no_$opt ]] failed"
+
+ set --no$opt || err_exit "set --no$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set --no-$opt || err_exit "set --no-$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set --no_$opt || err_exit "set --no_$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set -o $opt || err_exit "set -o $opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set -o $opt=1 || err_exit "set -o $opt=1 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set -o no$opt=0 || err_exit "set -o no$opt=0 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set --$opt=1 || err_exit "set --$opt=1 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set --no$opt=0 || err_exit "set --no$opt=0 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set -o no$opt || err_exit "set -o no$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set -o $opt=0 || err_exit "set -o $opt=0 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set -o no$opt=1 || err_exit "set -o no$opt=1 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set --$opt=0 || err_exit "set --$opt=0 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set --no$opt=1 || err_exit "set --no$opt=1 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+
+ set -o no-$opt || err_exit "set -o no-$opt failed"
+ [[ -o no-$opt ]] || err_exit "[[ -o no-$opt ]] failed"
+
+ set -o no_$opt || err_exit "set -o no_$opt failed"
+ [[ -o no_$opt ]] || err_exit "[[ -o no_$opt ]] failed"
+
+ set +o $opt || err_exit "set +o $opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+
+ set +o no$opt || err_exit "set +o no$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set +o no-$opt || err_exit "set +o no-$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set +o no_$opt || err_exit "set +o no_$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set --$old
+done
+
+for opt in \
+ exec interactive login_shell login-shell logi privileged \
+ rc restricted xtrace
+do [[ -o $opt ]]
+ y=$?
+ [[ -o no$opt ]]
+ n=$?
+ case $y$n in
+ 10|01) ;;
+ *) err_exit "[[ -o $opt ]] == [[ -o no$opt ]]" ;;
+ esac
+done
+
+for opt in \
+ foo foo-bar foo_bar
+do if [[ -o ?$opt ]]
+ then err_exit "[[ -o ?$opt ]] should fail"
+ fi
+ if [[ -o ?no$opt ]]
+ then err_exit "[[ -o ?no$opt ]] should fail"
+ fi
+done
+
+[[ $(set +o) == $(set --state) ]] || err_exit "set --state different from set +o"
+set -- $(set --state)
+[[ $1 == set && $2 == --default ]] || err_exit "set --state failed -- expected 'set --default *', got '$1 $2 *'"
+shift
+restore=$*
+shift
+off=
+for opt
+do case $opt in
+ --not*) opt=${opt/--/--no} ;;
+ --no*) opt=${opt/--no/--} ;;
+ --*) opt=${opt/--/--no} ;;
+ esac
+ off="$off $opt"
+done
+set $off
+state=$(set --state)
+default=$(set --default --state)
+[[ $state == $default ]] || err_exit "set --state for default options failed: expected '$default', got '$state'"
+set $restore
+state=$(set --state)
+[[ $state == "set $restore" ]] || err_exit "set --state after restore failed: expected 'set $restore', got '$state'"
+
+typeset -a pipeline
+pipeline=(
+ ( nopipefail=0 pipefail=1 command='false|true|true' )
+ ( nopipefail=0 pipefail=1 command='true|false|true' )
+ ( nopipefail=1 pipefail=1 command='true|true|false' )
+ ( nopipefail=1 pipefail=1 command='false|false|false' )
+ ( nopipefail=0 pipefail=0 command='true|true|true' )
+ ( nopipefail=0 pipefail=0 command='print hi|(sleep 1;/bin/cat)>/dev/null' )
+)
+set --nopipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].nopipefail}
+ [[ $status == $expected ]] ||
+ err_exit "--nopipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+done
+ftt=0
+set --pipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].pipefail}
+ if [[ $status != $expected ]]
+ then err_exit "--pipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+ (( i == 0 )) && ftt=1
+ fi
+done
+if (( ! ftt ))
+then exp=10
+ got=$(for((n=1;n<exp;n++))do $SHELL --pipefail -c '(sleep 0.1;false)|true|true' && break; done; print $n)
+ [[ $got == $exp ]] || err_exit "--pipefail -c '(sleep 0.1;false)|true|true' fails with exit status 0 (after $got/$exp iterations)"
+fi
+
+echo=$(whence -p echo)
+for ((i=0; i < 20; i++))
+do if ! x=$(true | $echo 123)
+ then err_exit 'command substitution with wrong exit status with pipefai'
+ break
+ fi
+done
+(
+ set -o pipefail
+ false | true
+ (( $? )) || err_exit 'pipe not failing in subshell with pipefail'
+) | wc >/dev/null
+$SHELL -c 'set -o pipefail; false | $(whence -p true);' && err_exit 'pipefail not returning failure with sh -c'
+exp='1212 or 1221'
+got=$(
+ set --pipefail
+ pipe() { date | cat > /dev/null ;}
+ print $'1\n2' |
+ while read i
+ do if pipe $tmp
+ then { print -n $i; sleep 2; print -n $i; } &
+ fi
+ done
+ wait
+)
+[[ $got == @((12|21)(12|21)) ]] || err_exit "& job delayed by --pipefail, expected '$exp', got '$got'"
+$SHELL -c '[[ $- == *c* ]]' || err_exit 'option c not in $-'
+> $tmp/.profile
+for i in i l r s D E a b e f h k n t u v x B C G H
+do HOME=$tmp ENV= $SHELL -$i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not in \$-"
+ [[ \$- == *$i* ]] || exit 1
+ ++EOF++
+done
+letters=ilrabefhknuvxBCGE
+integer j=0
+for i in interactive login restricted allexport notify errexit \
+ noglob trackall keyword noexec nounset verbose xtrace braceexpand \
+ noclobber globstar rc
+do HOME=$tmp ENV= $SHELL -o $i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not equivalent to ${letters:j:1}"
+ [[ \$- == *${letters:j:1}* ]] || exit 1
+ ++EOF++
+ ((j++))
+done
+
+export ENV= PS1="(:$$:)"
+histfile=$tmp/history
+exp=$(HISTFILE=$histfile $SHELL -c $'function foo\n{\ncat\n}\ntype foo')
+for var in HISTSIZE HISTFILE
+do got=$( ( HISTFILE=$histfile $SHELL +E -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ) 2>&1 )
+ got=${got##*"$PS1"}
+ [[ $got == "$exp" ]] || err_exit "function definition inside (...) with $var unset fails -- got '$got', expected '$exp'"
+ got=$( { HISTFILE=$histfile $SHELL +E -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ;} 2>&1 )
+ got=${got##*"$PS1"}
+ [[ $got == "$exp" ]] || err_exit "function definition inside {...;} with $var unset fails -- got '$got', expected '$exp'"
+done
+( unset HISTFILE; $SHELL -ic "HISTFILE=$histfile" 2>/dev/null ) || err_exit "setting HISTFILE when not in environment fails"
+
+# the next tests loop on all combinations of
+# { SUB PAR CMD ADD }
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+PAR=(
+ ( BEG='( ' END=' )' )
+ ( BEG='{ ' END='; }' )
+)
+CMD=( command-kill script-kill )
+ADD=( '' '; :' )
+
+cd $tmp
+print $'#!'$SHELL$'\nkill -KILL $$' > command-kill
+print $'kill -KILL $$' > script-kill
+chmod +x command-kill script-kill
+export PATH=.:$PATH
+exp='Killed'
+for ((S=0; S<${#SUB[@]}; S++))
+do for ((P=0; P<${#PAR[@]}; P++))
+ do for ((C=0; C<${#CMD[@]}; C++))
+ do for ((A=0; A<${#ADD[@]}; A++))
+ do cmd="${SUB[S].BEG}${PAR[P].BEG}${CMD[C]}${PAR[P].END} 2>&1${ADD[A]}${SUB[S].END}"
+ eval got="$cmd"
+ got=${got##*': '}
+ got=${got%%'('*}
+ [[ $got == "$exp" ]] || err_exit "$cmd failed -- got '$got', expected '$exp'"
+ done
+ done
+ done
+done
+
+$SHELL 2> /dev/null -c '{; true ;}' || err_exit 'leading ; causes syntax error in brace group'
+$SHELL 2> /dev/null -c '(; true ;)' || err_exit 'leading ; causes syntax error in parenthesis group'
+
+print 'for ((i = 0; i < ${1:-10000}; i++ )); do printf "%.*c\n" 15 x; done' > pipefail
+chmod +x pipefail
+$SHELL --pipefail -c './pipefail 10000 | sed 1q' >/dev/null 2>&1 &
+tst=$!
+{ sleep 4; kill $tst; } 2>/dev/null &
+spy=$!
+wait $tst 2>/dev/null
+status=$?
+if [[ $status == 0 || $(kill -l $status) == PIPE ]]
+then kill $spy 2>/dev/null
+else err_exit "pipefail pipeline bypasses SIGPIPE and hangs"
+fi
+wait
+
+[[ $($SHELL -uc '[[ "${d1.u[z asd].revents}" ]]' 2>&1) == *'d1.u[z asd].revents'* ]] || err_exit 'name of unset parameter not in error message'
+
+[[ $($SHELL 2> /dev/null -xc $'set --showme\nprint 1\n; print 2') == 1 ]] || err_exit 'showme option with xtrace not working correctly'
+
+$SHELL -uc 'var=foo;unset var;: ${var%foo}' >/dev/null 2>&1 && err_exit '${var%foo} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${!var}' >/dev/null 2>&1 && err_exit '${!var} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${#var}' >/dev/null 2>&1 && err_exit '${#var} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${var-OK}' >/dev/null 2>&1 || err_exit '${var-OK} should not fail with set -u'
+$SHELL -uc 'var=foo;nset var;: ${var:-OK}' >/dev/null 2>&1 || err_exit '${var:-OK} should not fail with set -u'
+
+z=$($SHELL 2>&1 -uc 'print ${X23456789012345}')
+[[ $z == *X23456789012345:* ]] || err_exit "error message garbled with set -u got $z"
+
+# pipe hang bug fixed 2011-03-15
+float start=SECONDS toolong=3
+( $SHELL <<-EOF
+ set -o pipefail
+ (sleep $toolong;kill \$\$> /dev/null) &
+ cat $SHELL | for ((i=0; i < 5; i++))
+ do
+ date | wc > /dev/null
+ $SHELL -c 'read -N1'
+ done
+EOF
+) 2> /dev/null
+(( (SECONDS-start) > (toolong-0.5) )) && err_exit "pipefail causes script to hang"
+
+# showme with arithmetic for loops
+$SHELL -n -c $'for((;1;))\ndo ; nothing\ndone' 2>/dev/null || err_exit 'showme commands give syntax error inside arithmetic for loops'
+
+#set -x
+float t1=SECONDS
+set -o pipefail
+print | while read
+do if { date | true;} ; true
+ then sleep 2 &
+ fi
+done
+(( (SECONDS-t1) > .5 )) && err_exit 'pipefail should not wait for background processes'
+
+# process source files from profiles as profile files
+print '. ./dotfile' > envfile
+print $'alias print=:\nprint foobar' > dotfile
+[[ $(ENV=$PWD/envfile $SHELL -i -c : 2>/dev/null) == foobar ]] && err_exit 'files source from profile does not process aliases correctly'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/path.sh b/src/cmd/ksh93/tests/path.sh
new file mode 100755
index 0000000..3fd16e9
--- /dev/null
+++ b/src/cmd/ksh93/tests/path.sh
@@ -0,0 +1,375 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || exit
+type /xxxxxx > out1 2> out2
+[[ -s out1 ]] && err_exit 'type should not write on stdout for not found case'
+[[ -s out2 ]] || err_exit 'type should write on stderr for not found case'
+mkdir dir1 dir2
+cat > dir1/foobar << '+++'
+foobar() { print foobar1;}
+function dir1 { print dir1;}
++++
+cat > dir2/foobar << '+++'
+foobar() { print foobar2;}
+function dir2 { print dir2;}
++++
+chmod +x dir[12]/foobar
+p=$PATH
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ $( foobar) == foobar1 ]] || err_exit 'foobar should output foobar1'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ $(foobar) == foobar2 ]] || err_exit 'foobar should output foobar2'
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ $(foobar) == foobar1 ]] || err_exit 'foobar should output foobar1 again'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${}'
+[[ ${ dir2;} == dir2 ]] || err_exit 'should be dir2'
+[[ ${ dir1;} == dir1 ]] 2> /dev/null && err_exit 'should not be be dir1'
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar1 ]] || err_exit 'foobar should output foobar1 with ${}'
+[[ ${ dir1;} == dir1 ]] || err_exit 'should be dir1'
+[[ ${ dir2;} == dir2 ]] 2> /dev/null && err_exit 'should not be be dir2'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${} again'
+PATH=$p
+(PATH="/bin")
+[[ $($SHELL -c 'print -r -- "$PATH"') == "$PATH" ]] || err_exit 'export PATH lost in subshell'
+cat > bug1 <<- EOF
+ print print ok > $tmp/ok
+ /bin/chmod 755 $tmp/ok
+ function a
+ {
+ typeset -x PATH=$tmp
+ ok
+ }
+ path=\$PATH
+ unset PATH
+ a
+ PATH=\$path
+}
+EOF
+[[ $($SHELL ./bug1 2>/dev/null) == ok ]] || err_exit "PATH in function not working"
+cat > bug1 <<- \EOF
+ function lock_unlock
+ {
+ typeset PATH=/usr/bin
+ typeset -x PATH=''
+ }
+
+ PATH=/usr/bin
+ : $(PATH=/usr/bin getconf PATH)
+ typeset -ft lock_unlock
+ lock_unlock
+EOF
+($SHELL ./bug1) 2> /dev/null || err_exit "path_delete bug"
+mkdir tdir
+if $SHELL tdir > /dev/null 2>&1
+then err_exit 'not an error to run ksh on a directory'
+fi
+
+print 'print hi' > ls
+if [[ $($SHELL ls 2> /dev/null) != hi ]]
+then err_exit "$SHELL name not executing version in current directory"
+fi
+if [[ $(ls -d . 2>/dev/null) == . && $(PATH=/bin:/usr/bin:$PATH ls -d . 2>/dev/null) != . ]]
+then err_exit 'PATH export in command substitution not working'
+fi
+pwd=$PWD
+# get rid of leading and trailing : and trailing :.
+PATH=${PATH%.}
+PATH=${PATH%:}
+PATH=${PATH#.}
+PATH=${PATH#:}
+path=$PATH
+var=$(whence date)
+dir=$(basename "$var")
+for i in 1 2 3 4 5 6 7 8 9 0
+do if ! whence notfound$i 2> /dev/null
+ then cmd=notfound$i
+ break
+ fi
+done
+print 'print hello' > date
+chmod +x date
+print 'print notfound' > $cmd
+chmod +x "$cmd"
+> foo
+chmod 755 foo
+for PATH in $path :$path $path: .:$path $path: $path:. $PWD::$path $PWD:.:$path $path:$PWD $path:.:$PWD
+do
+# print path=$PATH $(whence date)
+# print path=$PATH $(whence "$cmd")
+ date
+ "$cmd"
+done > /dev/null 2>&1
+builtin -d date 2> /dev/null
+if [[ $(PATH=:/usr/bin; date) != 'hello' ]]
+then err_exit "leading : in path not working"
+fi
+(
+ PATH=$PWD:
+ builtin chmod
+ print 'print cannot execute' > noexec
+ chmod 644 noexec
+ if [[ ! -x noexec ]]
+ then noexec > /dev/null 2>&1
+ else exit 126
+ fi
+)
+status=$?
+[[ $status == 126 ]] || err_exit "exit status of non-executable is $status -- 126 expected"
+builtin -d rm 2> /dev/null
+chmod=$(whence chmod)
+rm=$(whence rm)
+d=$(dirname "$rm")
+
+chmod=$(whence chmod)
+
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence $cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+
+exp=''
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence ./notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence $PWD/notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
+unset FPATH
+PATH=/dev/null
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($cmd 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($cmd 2>&1; :)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence ./$cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+exp=''
+got=$(whence ./notfound)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$(whence $PWD/notfound)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
+PATH=$d:
+cp "$rm" kshrm
+if [[ $(whence kshrm) != $PWD/kshrm ]]
+then err_exit 'trailing : in pathname not working'
+fi
+cp "$rm" rm
+PATH=:$d
+if [[ $(whence rm) != $PWD/rm ]]
+then err_exit 'leading : in pathname not working'
+fi
+PATH=$d: whence rm > /dev/null
+if [[ $(whence rm) != $PWD/rm ]]
+then err_exit 'pathname not restored after scoping'
+fi
+mkdir bin
+print 'print ok' > bin/tst
+chmod +x bin/tst
+if [[ $(PATH=$PWD/bin tst 2>/dev/null) != ok ]]
+then err_exit '(PATH=$PWD/bin foo) does not find $PWD/bin/foo'
+fi
+cd /
+if whence ls > /dev/null
+then PATH=
+ if [[ $(whence rm) ]]
+ then err_exit 'setting PATH to Null not working'
+ fi
+ unset PATH
+ if [[ $(whence rm) != /*rm ]]
+ then err_exit 'unsetting path not working'
+ fi
+fi
+PATH=/dev:$tmp
+x=$(whence rm)
+typeset foo=$(PATH=/xyz:/abc :)
+y=$(whence rm)
+[[ $x != "$y" ]] && err_exit 'PATH not restored after command substitution'
+whence getconf > /dev/null && err_exit 'getconf should not be found'
+builtin /bin/getconf
+PATH=/bin
+PATH=$(getconf PATH)
+x=$(whence ls)
+PATH=.:$PWD:${x%/ls}
+[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when .:$PWD in path'
+PATH=$PWD:.:${x%/ls}
+[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when :$PWD:. in path'
+cd "${x%/ls}"
+[[ $(whence ls) == /* ]] || err_exit 'whence not generating absolute pathname'
+status=$($SHELL -c $'trap \'print $?\' EXIT;/xxx/a/b/c/d/e 2> /dev/null')
+[[ $status == 127 ]] || err_exit "not found command exit status $status -- expected 127"
+status=$($SHELL -c $'trap \'print $?\' EXIT;/dev/null 2> /dev/null')
+[[ $status == 126 ]] || err_exit "non executable command exit status $status -- expected 126"
+status=$($SHELL -c $'trap \'print $?\' ERR;/xxx/a/b/c/d/e 2> /dev/null')
+[[ $status == 127 ]] || err_exit "not found command with ERR trap exit status $status -- expected 127"
+status=$($SHELL -c $'trap \'print $?\' ERR;/dev/null 2> /dev/null')
+[[ $status == 126 ]] || err_exit "non executable command ERR trap exit status $status -- expected 126"
+
+# universe via PATH
+
+builtin getconf
+getconf UNIVERSE - att # override sticky default 'UNIVERSE = foo'
+
+[[ $(PATH=/usr/ucb/bin:/usr/bin echo -n ucb) == 'ucb' ]] || err_exit "ucb universe echo ignores -n option"
+[[ $(PATH=/usr/xpg/bin:/usr/bin echo -n att) == '-n att' ]] || err_exit "att universe echo does not ignore -n option"
+
+PATH=$path
+
+scr=$tmp/script
+exp=126
+
+: > $scr
+chmod a=x $scr
+{ got=$($scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "unreadable empty script should fail -- expected $exp, got $got"
+{ got=$(command $scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "command of unreadable empty script should fail -- expected $exp, got $got"
+[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable empty script in [[ ... ]] should fail -- expected $exp"
+[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable empty script in [[ ... ]] should fail -- expected $exp"
+got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable empty script should fail -- expected $exp, got" $got
+got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable empty script should fail -- expected $exp, got" $got
+
+rm -f $scr
+print : > $scr
+chmod a=x $scr
+{ got=$($scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "unreadable non-empty script should fail -- expected $exp, got $got"
+{ got=$(command $scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "command of unreadable non-empty script should fail -- expected $exp, got $got"
+[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
+[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
+got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable non-empty script should fail -- expected $exp, got" $got
+got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable non-empty script should fail -- expected $exp, got" $got
+
+# whence -a bug fix
+cd "$tmp"
+ifs=$IFS
+IFS=$'\n'
+PATH=$PATH:
+> ls
+chmod +x ls
+ok=
+for i in $(whence -a ls)
+do if [[ $i == *"$PWD/ls" ]]
+ then ok=1
+ break;
+ fi
+done
+[[ $ok ]] || err_exit 'whence -a not finding all executables'
+rm -f ls
+PATH=${PATH%:}
+
+#whence -p bug fix
+function foo
+{
+ :
+}
+[[ $(whence -p foo) == foo ]] && err_exit 'whence -p foo should not find function foo'
+
+# whence -q bug fix
+$SHELL -c 'whence -q cat' & pid=$!
+sleep 3
+kill $! 2> /dev/null && err_exit 'whence -q appears to be hung'
+
+FPATH=$PWD
+print 'function foobar { :;}' > foobar
+autoload foobar;
+exec {m}< /dev/null
+for ((i=0; i < 25; i++))
+do ( foobar )
+done
+exec {m}<& -
+exec {n}< /dev/null
+(( n > m )) && err_exit 'autoload function in subshell leaves file open'
+
+# whence -a bug fix
+rmdir=rmdir
+if mkdir "$rmdir"
+then rm=${ whence rm;}
+ cp "$rm" "$rmdir"
+ { PATH=:${rm%/rm} $SHELL -c "cd \"$rmdir\";whence -a rm";} > /dev/null 2>&1
+ exitval=$?
+ (( exitval==0 )) || err_exit "whence -a has exitval $exitval"
+fi
+
+[[ ! -d bin ]] && mkdir bin
+[[ ! -d fun ]] && mkdir fun
+print 'FPATH=../fun' > bin/.paths
+cat <<- \EOF > fun/myfun
+ function myfun
+ {
+ print myfun
+ }
+EOF
+x=$(FPATH= PATH=$PWD/bin $SHELL -c ': $(whence less);myfun') 2> /dev/null
+[[ $x == myfun ]] || err_exit 'function myfun not found'
+
+cp $(whence -p echo) user_to_group_relationship.hdr.query
+FPATH=/foobar:
+PATH=$FPATH:$PATH:.
+[[ $(user_to_group_relationship.hdr.query foobar) == foobar ]] 2> /dev/null || err_exit 'Cannot execute command with . in name when PATH and FPATH end in :.'
+
+exit $((Errors<125?Errors:125))
+
diff --git a/src/cmd/ksh93/tests/pointtype.sh b/src/cmd/ksh93/tests/pointtype.sh
new file mode 100755
index 0000000..b0a5333
--- /dev/null
+++ b/src/cmd/ksh93/tests/pointtype.sh
@@ -0,0 +1,138 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Pt_t=(
+ float x=1
+ float y=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+)
+
+for ((i=0; i < 100; i++))
+do
+Pt_t p
+[[ ${p.x} == 1 ]] || err_exit '${p[x]} is not 1'
+(( p.x == 1 )) || err_ext 'p[x] is not 1'
+[[ $(p.len) == 1 ]] || err_exit '$(p.len) != 1'
+[[ ${p.len} == 1 ]] || err_exit '${p.len} != 1'
+(( p.len == 1 )) || err_exit '((p.len != 1))'
+Pt_t q=(y=2)
+(( q.x == 1 )) || err_exit 'q.x is not 1'
+(( (q.len - sqrt(5)) < 10e-10 )) || err_exit 'q.len != sqrt(5)'
+q.len()
+{
+ print -r $((abs(_.x)+abs(_.y) ))
+}
+(( q.len == 3 )) || err_exit 'q.len is not 3'
+p=q
+[[ ${p.y} == 2 ]] || err_exit '${p[y]} is not 2'
+[[ ${@p} == Pt_t ]] || err_exit 'type of p is not Pt_t'
+[[ ${@q} == Pt_t ]] || err_exit 'type of q is not Pt_t'
+(( p.len == 3 )) || err_exit 'p.len is not 3'
+unset p q
+Pt_t pp=( ( x=3 y=4) ( x=5 y=12) (y=2) )
+(( pp[0].len == 5 )) || err_exit 'pp[0].len != 5'
+(( pp[1].len == 13 )) || err_exit 'pp[0].len != 12'
+(( (pp[2].len - sqrt(5)) < 10e-10 )) || err_exit 'pp[2].len != sqrt(5)'
+[[ ${pp[1]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[1] is not correct'
+[[ ${!pp[@]} == '0 1 2' ]] || err_exit '${pp[@] != "0 1 2"'
+pp+=( x=6 y=8)
+(( pp[3].len == 10 )) || err_exit 'pp[3].len != 10'
+[[ ${!pp[@]} == '0 1 2 3' ]] || err_exit '${pp[@] != "0 1 2 3"'
+pp[4]=pp[1]
+[[ ${pp[4]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[4] is not correct'
+unset pp
+Pt_t pp=( [one]=( x=3 y=4) [two]=( x=5 y=12) [three]=(y=2) )
+(( pp[one].len == 5 )) || err_exit 'pp[one].len != 5'
+(( pp[two].len == 13 )) || err_exit 'pp[two].len != 12'
+[[ ${pp[two]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[two] is not correct'
+[[ ${!pp[@]} == 'one three two' ]] || err_exit '${pp[@] != "one three two"'
+[[ ${@pp[1]} == Pt_t ]] || err_exit 'type of pp[1] is not Pt_t'
+unset pp
+done
+# redefinition of point
+typeset -T Pt_t=(
+ Pt_t _=(x=3 y=6)
+ float z=2
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ }
+)
+Pt_t p
+[[ ${p.y} == 6 ]] || err_exit '${p.y} != 6'
+(( p.len == 7 )) || err_exit '((p.len !=7))'
+
+z=()
+Pt_t -a z.p
+z.p[1]=(y=2)
+z.p[2]=(y=5)
+z.p[3]=(x=6 y=4)
+eval y="$z"
+[[ $y == "$z" ]] || err_exit 'expansion of indexed array of types is incorrect'
+eval "$(typeset -p y)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for indexed array of types is incorrect'
+unset z y
+z=()
+Pt_t -A z.p
+z.p[1]=(y=2)
+z.p[2]=(y=5)
+z.p[3]=(x=6 y=4)
+eval y="$z"
+[[ $y == "$z" ]] || err_exit 'expansion of associative array of types is incorrect'
+eval "$(typeset -p y)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for associative of types is incorrect'
+unset z y
+
+typeset -T A_t=(
+ Pt_t -a b
+)
+typeset -T B_t=(
+ Pt_t -A b
+)
+A_t r
+r.b[1]=(y=2)
+r.b[2]=(y=5)
+eval s="$r"
+[[ $r == "$s" ]] || err_exit 'expansion of type containing index array of types is incorrect'
+eval "$(typeset -p s)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for type containing index of types is incorrect'
+unset r s
+B_t r
+r.b[1]=(y=2)
+r.b[2]=(y=5)
+eval s="$r"
+[[ $r == "$s" ]] || err_exit 'expansion of type containing index array of types is incorrect'
+eval "$(typeset -p s)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for type containing index of types is incorrect'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh
new file mode 100755
index 0000000..71eaef5
--- /dev/null
+++ b/src/cmd/ksh93/tests/pty.sh
@@ -0,0 +1,442 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+: : generated by mkptytests from "posix-sh-*-c.pty" : :
+
+# the trickiest part of the tests is avoiding typeahead
+# in the pty dialogue
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+
+alias err_exit='err_exit $lineno'
+
+Command=${0##*/}
+integer Errors=0 lineno=1
+
+whence -q pty || { lineno=$LINENO; err_exit "pty command not found -- tests skipped"; exit 0; }
+
+bintrue=$(whence -p true)
+
+x=$( $SHELL <<- \EOF
+ trap 'exit 0' EXIT
+ bintrue=$(whence -p true)
+ set -o monitor
+ {
+ eval $'set -o vi\npty $bintrue'
+ } < /dev/null & pid=$!
+ #sleep 1
+ jobs
+ kill $$
+ EOF
+)
+[[ $x == *Stop* ]] && err_exit 'monitor mode enabled incorrectly causes job to stop'
+
+if [[ -o xtrace ]]
+then debug=--debug=1
+else debug=
+fi
+
+function tst
+{
+ integer lineno=$1 offset
+ typeset text
+
+ pty $debug --dialogue --messages='/dev/fd/1' $SHELL |
+ while read -r text
+ do if [[ $text == *debug* ]]
+ then print -u2 -r -- "$text"
+ else offset=${text/*: line +([[:digit:]]):*/\1}
+ err_exit "${text/: line $offset:/: line $(( lineno + offset)):}"
+ fi
+ done
+}
+
+export PS1=':test-!: ' PS2='> ' PS4=': ' ENV= EXINIT= HISTFILE= TERM=dumb VISUAL=vi LC_ALL=C
+
+if ! pty $bintrue < /dev/null
+then err_exit pty command hangs on $bintrue -- tests skipped
+ exit 0
+fi
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 026(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTSTP signal then the <state> field in the output message is set to
+# Stopped, Suspended, Stopped(SIGTSTP) or Suspended(SIGTSTP).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TSTP $!
+u (Stopped|Suspended)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 028(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTTIN signal then the <state> field in the output message is set to
+# Stopped(SIGTTIN) or Suspended(SIGTTIN).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TTIN $!
+u (Stopped|Suspended) \(SIGTTIN\)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 029(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTTOU signal then the <state> field in the output message is set to
+# Stopped(SIGTTOU) or Suspended(SIGTTOU).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TTOU $!
+u (Stopped|Suspended) \(SIGTTOU\)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 091(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an entered
+# character other than <newline>, erase, interrupt, kill, control-V,
+# control-W, backslash \ (followed by erase or kill), end-of-file and
+# <ESC> is inserted in the current command line.
+
+c echo h
+c ell
+w o
+u ^hello\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 093(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: After termination of a previous
+# command, sh is entered in insert mode.
+
+w echo hello
+u ^hello\r?\n$
+c echo goo
+c dby
+w e
+u ^goodbye\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 094(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an <ESC>
+# switches sh into command mode.
+
+c echo he\E
+s 400
+w allo
+u ^hello\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 096(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode the
+# interrupt character causes sh to terminate command line editing on
+# the current command line, re-issue the prompt on the next line of the
+# terminal and to reset the command history so that the command that
+# was interrupted is not entered in the history.
+
+I ^\r?\n$
+p :test-1:
+w echo first
+p :test-2:
+w stty intr ^C
+p :test-3:
+c echo bad\E
+s 400
+c \cC
+w echo scrambled
+p :test-4:
+w history
+u echo first
+r stty intr \^C
+r echo
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 097(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode a <newline>
+# causes the current command line to be executed.
+
+c echo ok\n
+u ^ok\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 099(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode the interrupt
+# character causes sh to terminate command line editing on the current
+# command line, re-issue the prompt on the next line of the terminal
+# and to reset the command history so that the command that was
+# interrupted is not entered in the history.
+
+I ^\r?\n$
+p :test-1:
+w echo first
+u ^first
+p :test-2:
+w stty intr ^C
+r
+p :test-3:
+c echo bad\cC
+w echo last
+p :test-4:
+w history
+u echo first
+r stty intr \^C
+r echo last
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 100(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode the kill
+# character clears all the characters from the input line.
+
+p :test-1:
+w stty kill ^X
+p :test-2:
+c echo bad\cX
+w echo ok
+u ^ok\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 101(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode a control-V
+# causes the next character to be inserted even in the case that the
+# character is a special insert mode character.
+# Testing Requirements: The assertion must be tested with at least the
+# following set of characters: <newline>, erase, interrupt, kill,
+# control-V, control-W, end-of-file, backslash \ (followed by erase or
+# kill) and <ESC>.
+
+d 10
+p :test-1:
+w stty erase ^H intr ^C kill ^X
+p :test-2:
+w echo erase=:\cV\cH:
+u ^erase=:\r?\n$
+p :test-3:
+w echo kill=:\cV\cX:
+u ^kill=:\cX:\r?\n$
+p :test-4:
+w echo control-V=:\cV\cV:
+u ^control-V=:\cV:\r?\n$
+p :test-5:
+w echo control-W:\cV\cW:
+u ^control-W:\cW:\r?\n$
+p :test-6:
+w echo EOF=:\cV\cD:
+u ^EOF=:\004:\r?\n$
+p :test-7:
+w echo backslash-erase=:\\\cH:
+u ^backslash-erase=:\r?\n$
+p :test-8:
+w echo backslash-kill=:\\\cX:
+u ^backslash-kill=:\cX:\r?\n$
+p :test-9:
+w echo ESC=:\cV\E:
+u ^ESC=:\E:\r?\n$
+p :test-10:
+w echo interrupt=:\cV\cC:
+u ^interrupt=:\cC:\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 104(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an
+# end-of-file at the beginning of an input line is interpreted as the
+# end of input.
+
+p :test-1:
+w trap 'echo done >&2' EXIT
+p :test-2:
+s 100
+c \cD
+u ^done\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 111(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, # inserts
+# the character # at the beginning of the command line and causes the
+# line to be treated as a comment and the line is entered in the
+# command history.
+
+p :test-1:
+c echo save\E
+s 400
+c #
+p :test-2:
+w history
+u #echo save
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 137(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, then v
+# invokes the vi editor to edit the current command line in a temporary
+# file. When the editor exits, the commands in the temporary file are
+# executed.
+
+p :test-1:
+c echo hello\E
+s 400
+c v
+u /tmp/
+c A world\E
+s 400
+w :wq
+u ^hello world\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 251(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, then the
+# command N repeats the most recent / or ? command, reversing the
+# direction of the search.
+
+p :test-1:
+w echo repeat-1
+u ^repeat-1\r?\n$
+p :test-2:
+w echo repeat-2
+u ^repeat-2\r?\n$
+p :test-3:
+s 100
+c \E
+s 400
+w /rep
+u echo repeat-2
+c n
+r echo repeat-1
+c N
+r echo repeat-2
+w dd
+p :test-3:
+w echo repeat-3
+u ^repeat-3\r?\n$
+p :test-4:
+s 100
+c \E
+s 400
+w ?rep
+r echo repeat-2
+c N
+r echo repeat-1
+c n
+r echo repeat-2
+c n
+r echo repeat-3
+!
+
+# err_exit #
+whence -q less &&
+TERM=vt100 tst $LINENO <<"!"
+L process/terminal group exercise
+
+w m=yes; while true; do echo $m-$m; done | less
+u :$|:\E|lines
+c \cZ
+r Stopped
+w fg
+u yes-yes
+!
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/quoting.sh b/src/cmd/ksh93/tests/quoting.sh
new file mode 100755
index 0000000..01aae0d
--- /dev/null
+++ b/src/cmd/ksh93/tests/quoting.sh
@@ -0,0 +1,369 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+if [[ 'hi there' != "hi there" ]]
+then err_exit "single quotes not the same as double quotes"
+fi
+x='hi there'
+if [[ $x != 'hi there' ]]
+then err_exit "$x not the same as 'hi there'"
+fi
+if [[ $x != "hi there" ]]
+then err_exit "$x not the same as \"hi there \""
+fi
+if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]]
+then err_exit " \\ differs from '' "
+fi
+if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]]
+then err_exit " \"\" differs from '' "
+fi
+if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - '')\" differs from ''"
+fi
+if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - "")\" differs from ''"
+fi
+if [[ $(print -r - $(print -r - 'abc*|" \')) != 'abc*|" \' ]]
+then err_exit "nested \$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]]
+then err_exit "\"nested \$(print -r - '')\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \"\$(print -r - '')\" differs from ''"
+fi
+unset x
+if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]]
+then err_exit "\${x-\$(print -r - '')} differs from ''"
+fi
+if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]]
+then err_exit "\${x-\$(print -r - '}')} differs from ''"
+fi
+x=$((echo foo)|(cat))
+if [[ $x != foo ]]
+then err_exit "((cmd)|(cmd)) failed"
+fi
+x=$(print -r -- "\"$HOME\"")
+if [[ $x != '"'$HOME'"' ]]
+then err_exit "nested double quotes failed"
+fi
+unset z
+: ${z="a{b}c"}
+if [[ $z != 'a{b}c' ]]
+then err_exit '${z="a{b}c"} not correct'
+fi
+unset z
+: "${z="a{b}c"}"
+if [[ $z != 'a{b}c' ]]
+then err_exit '"${z="a{b}c"}" not correct'
+fi
+if [[ $(print -r -- "a\*b") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b") differs from a\*b'
+fi
+unset x
+if [[ $(print -r -- "a\*b$x") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b$x") differs from a\*b'
+fi
+x=hello
+set -- ${x+foo bar bam}
+if (( $# !=3 ))
+then err_exit '${x+foo bar bam} does not yield three arguments'
+fi
+set -- ${x+foo "bar bam"}
+if (( $# !=2 ))
+then err_exit '${x+foo "bar bam"} does not yield two arguments'
+fi
+set -- ${x+foo 'bar bam'}
+if (( $# !=2 ))
+then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments'
+fi
+set -- ${x+foo $x bam}
+if (( $# !=3 ))
+then err_exit '${x+foo $x bam} does not yield three arguments'
+fi
+set -- ${x+foo "$x" bam}
+if (( $# !=3 ))
+then err_exit '${x+foo "$x" bam} does not yield three arguments'
+fi
+set -- ${x+"foo $x bam"}
+if (( $# !=1 ))
+then err_exit '${x+"foo $x bam"} does not yield one argument'
+fi
+set -- "${x+foo $x bam}"
+if (( $# !=1 ))
+then err_exit '"${x+foo $x bam}" does not yield one argument'
+fi
+set -- ${x+foo "$x "bam}
+if (( $# !=2 ))
+then err_exit '${x+foo "$x "bam} does not yield two arguments'
+fi
+x="ab$'cd"
+if [[ $x != 'ab$'"'cd" ]]
+then err_exit '$'"' inside double quotes not working"
+fi
+x=`print 'ab$'`
+if [[ $x != 'ab$' ]]
+then err_exit '$'"' inside `` quotes not working"
+fi
+unset a
+x=$(print -r -- "'\
+\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in double strings not working'
+fi
+x=$(print -r -- "'\
+$a\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in expanded double strings not working'
+fi
+x='\*'
+if [[ $(print -r -- $x) != '\*' ]]
+then err_exit 'x="\\*";$x != \*'
+fi
+x=' hello world '
+set -- $x
+if (( $# != 2 ))
+then err_exit 'field splitting error'
+fi
+x=$(print -r -- '1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890')
+if (( ${#x} != (15*73-3) ))
+then err_exit "length of x, ${#x}, is incorrect should be $((15*73-3))"
+fi
+x='$hi'
+if [[ $x\$ != '$hi$' ]]
+then err_exit ' $x\$, with x=$hi, does not expand to $hi$'
+fi
+if [[ $x$ != '$hi$' ]]
+then err_exit ' $x$, with x=$hi, does not expand to $hi$'
+fi
+set -- $(/bin/echo foo;sleep 1;/bin/echo bar)
+if [[ $# != 2 ]]
+then err_exit 'word splitting after command substitution not working'
+fi
+unset q
+if [[ "${q:+'}q${q:+'}" != q ]]
+then err_exit 'expansion of "{q:+'\''}" not correct when q unset'
+fi
+q=1
+if [[ "${q:+'}q${q:+'}" != "'q'" ]]
+then err_exit 'expansion of "{q:+'\''}" not correct when q set'
+fi
+x=$'x\' #y'
+if [[ $x != "x' #y" ]]
+then err_exit "$'x\' #y'" not working
+fi
+x=$q$'x\' #y'
+if [[ $x != "1x' #y" ]]
+then err_exit "$q$'x\' #y'" not working
+fi
+IFS=,
+x='a,b\,c,d'
+set -- $x
+if [[ $2 != 'b\' ]]
+then err_exit "field splitting of $x with IFS=$IFS not working"
+fi
+foo=bar
+bar=$(print -r -- ${foo+\\n\ })
+if [[ $bar != '\n ' ]]
+then err_exit '${foo+\\n\ } expansion error'
+fi
+unset bar
+bar=$(print -r -- ${foo+\\n\ $bar})
+if [[ $bar != '\n ' ]]
+then err_exit '${foo+\\n\ $bar} expansion error with bar unset'
+fi
+x='\\(..\\)|&\|\|\\&\\|'
+if [[ $(print -r -- $x) != "$x" ]]
+then err_exit '$x, where x=\\(..\\)|&\|\|\\&\\| not working'
+fi
+x='\\('
+if [[ $(print -r -- a${x}b) != a"${x}"b ]]
+then err_exit 'a${x}b, where x=\\( not working'
+fi
+x=
+if [[ $(print -r -- $x'\\1') != '\\1' ]]
+then err_exit 'backreference inside single quotes broken'
+fi
+set -- ''
+set -- "$@"
+if (( $# != 1 ))
+then err_exit '"$@" not preserving nulls'
+fi
+x=
+if [[ $(print -r s"!\2${x}\1\a!") != 's!\2\1\a!' ]]
+then err_exit 'print -r s"!\2${x}\1\a!" not equal s!\2\1\a!'
+fi
+if [[ $(print -r $'foo\n\n\n') != foo ]]
+then err_exit 'trailing newlines on comsubstitution not removed'
+fi
+unset x
+if [[ ${x:='//'} != '//' ]]
+then err_exit '${x:='//'} != "//"'
+fi
+if [[ $(print -r "\"hi$\"") != '"hi$"' ]]
+then err_exit '$\ not correct inside ""'
+fi
+unset x
+if [[ "${x-a\}b}" != 'a}b' ]]
+then err_exit '"${x-a\}b}" != "a}b"'
+fi
+if [[ "\}\]$x\*\{\[\\" != '\}\]\*\{\[\' ]]
+then err_exit '"\}\]$x\*\{\[\\" != "\}\]\*\{\[\"'
+fi
+foo=yes
+if [[ $(print -r -- {\$foo}) != '{$foo}' ]]
+then err_exit '{\$foo}' not expanded correctly
+fi
+[[ foo == $(
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+print foo) ]] || err_exit "command subsitution with long comments broken"
+subject='some/other/words'
+re='@(?*)/@(?*)/@(?*)'
+[[ ${subject/${re}/\3} != words ]] && err_exit 'string replacement with \3 not working'
+[[ ${subject/${re}/'\3'} != '\3' ]] && err_exit 'string replacement with '"'\3'"' not working'
+[[ ${subject/${re}/"\\3"} != '\3' ]] && err_exit 'string replacement with "\\3" not working'
+[[ ${subject/${re}/"\3"} != '\3' ]] && err_exit 'string replacement with "\3" not working'
+string='\3'
+[[ ${subject/${re}/${string}} != words ]] && err_exit 'string replacement with $string not working with string=\3'
+[[ $(print -r "${subject/${re}/${string}}") != words ]] && err_exit 'string replacement with $string not working with string=\3 using print'
+[[ ${subject/${re}/"${string}"} != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3'
+[[ $(print -r "${subject/${re}/"${string}"}") != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3 using print'
+string='\\3'
+[[ ${subject/${re}/${string}} != '\3' ]] && err_exit 'string replacement with $string not working with string=\\3'
+[[ ${subject/${re}/"${string}"} != '\\3' ]] && err_exit 'string replacement with "$string" not working with string=\\3'
+[[ ${subject/${re}/\4} != '\4' ]] && err_exit 'string replacement with \4 not working'
+[[ ${subject/${re}/'\4'} != '\4' ]] && err_exit 'string replacement with '\4' not working'
+string='\4'
+[[ ${subject/${re}/${string}} != '\4' ]] && err_exit 'string replacement with $string not working with string=\4'
+[[ ${subject/${re}/"${string}"} != '\4' ]] && err_exit 'string replacement with "$string" not working with string=\4'
+string='&foo'
+[[ ${subject/${re}/${string}} != '&foo' ]] && err_exit 'string replacement with $string not working with string=&foo'
+[[ ${subject/${re}/"${string}"} != '&foo' ]] && err_exit 'string replacement with "$string" not working with string=&foo'
+{
+x=x
+x=${x:-`id | sed 's/^[^(]*(\([^)]*\)).*/\1/'`}
+} 2> /dev/null || err_exit 'skipping over `` failed'
+[[ $x == x ]] || err_exit 'assignment ${x:=`...`} failed'
+[[ $($SHELL -c 'print a[') == 'a[' ]] || err_exit "unbalanced '[' in command arg fails"
+$SHELL -c $'false && (( `wc -l /dev/null | nawk \'{print $1}\'` > 2 )) && true;:' 2> /dev/null || err_exit 'syntax error with ` in arithmetic expression'
+{ $SHELL -c '(( 1`: "{ }"` ))' ;} 2> /dev/null || err_exit 'problem with ` inside (())'
+varname=foobarx
+x=`print '"\$'${varname}'"'`
+[[ $x == '"$foobarx"' ]] || err_exit $'\\$\' not handled correctly inside ``'
+
+copy1=5 copynum=1
+foo="`eval echo "$"{copy$copynum"-0}"`"
+[[ $foo == "$copy1" ]] || err_exit '$"..." not being ignored inside ``'
+
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd '') == 1 ]] || err_exit '${1+"$@"} with one empty argument fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd foo '') == 2 ]] || err_exit '${1+"$@"} with one non-empty and on empty argument fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd "" '') == 2 ]] || err_exit '${1+"$@"} with two empty arguments fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd "" '' '') == 3 ]] || err_exit '${1+"$@"} with three empty arguments fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd '') == 1 ]] || err_exit '"$@" with one empty argument fails'
+[[ $($SHELL -c 'set -- "${@:2}"; print $#' cmd '') == 0 ]] || err_exit '"$@" with one empty argument fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd foo '') == 2 ]] || err_exit '"$@" with one non-empty and on empty argument fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd "" '') == 2 ]] || err_exit '"$@" with two empty arguments fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd "" '' '') == 3 ]] || err_exit '"$@" with three empty arguments fails'
+args=('')
+set -- "${args[@]}"
+[[ $# == 1 ]] || err_exit '"${args[@]}"} with one empty argument fails'
+set -- ${1+"${args[@]}"}
+[[ $# == 1 ]] || err_exit '${1+"${args[@]}"} with one empty argument fails'
+args=(foo '')
+set -- "${args[@]}"
+[[ $# == 2 ]] || err_exit '"${args[@]}"} with one non-empty and one empty argument fails'
+set -- ${1+"${args[@]}"}
+[[ $# == 2 ]] || err_exit '${1+"${args[@]}"} with one non-empty and one empty argument fails'
+
+unset ARGS
+set --
+ARGS=("$@")
+set -- "${ARGS[@]}"
+(( $# )) && err_exit 'set -- "${ARGS[@]}" for empty array should not produce arguments'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/quoting2.sh b/src/cmd/ksh93/tests/quoting2.sh
new file mode 100755
index 0000000..bc7380d
--- /dev/null
+++ b/src/cmd/ksh93/tests/quoting2.sh
@@ -0,0 +1,215 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+set -o noglob
+if [[ 'hi there' != "hi there" ]]
+then err_exit "single quotes not the same as double quotes"
+fi
+x='hi there'
+if [[ $x != 'hi there' ]]
+then err_exit "$x not the same as 'hi there'"
+fi
+if [[ $x != "hi there" ]]
+then err_exit "$x not the same as \"hi there \""
+fi
+if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]]
+then err_exit " \\ differs from '' "
+fi
+if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]]
+then err_exit " \"\" differs from '' "
+fi
+if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - '')\" differs from ''"
+fi
+if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - "")\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]]
+then err_exit "\"nested \$(print -r - '')\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \"\$(print -r - '')\" differs from ''"
+fi
+unset x
+if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]]
+then err_exit "\${x-\$(print -r - '')} differs from ''"
+fi
+if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]]
+then err_exit "\${x-\$(print -r - '}')} differs from ''"
+fi
+x=$((echo foo)|(cat))
+if [[ $x != foo ]]
+then err_exit "((cmd)|(cmd)) failed"
+fi
+x=$(print -r -- "\"$HOME\"")
+if [[ $x != '"'$HOME'"' ]]
+then err_exit "nested double quotes failed"
+fi
+unset z
+: ${z="a{b}c"}
+if [[ $z != 'a{b}c' ]]
+then err_exit '${z="a{b}c"} not correct'
+fi
+unset z
+: "${z="a{b}c"}"
+if [[ $z != 'a{b}c' ]]
+then err_exit '"${z="a{b}c"}" not correct'
+fi
+if [[ $(print -r -- "a\*b") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b") differs from a\*b'
+fi
+unset x
+if [[ $(print -r -- "a\*b$x") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b$x") differs from a\*b'
+fi
+x=hello
+set -- ${x+foo bar bam}
+if (( $# !=3 ))
+then err_exit '${x+foo bar bam} does not yield three arguments'
+fi
+set -- ${x+foo "bar bam"}
+if (( $# !=2 ))
+then err_exit '${x+foo "bar bam"} does not yield two arguments'
+fi
+set -- ${x+foo 'bar bam'}
+if (( $# !=2 ))
+then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments'
+fi
+set -- ${x+foo $x bam}
+if (( $# !=3 ))
+then err_exit '${x+foo $x bam} does not yield three arguments'
+fi
+set -- ${x+foo "$x" bam}
+if (( $# !=3 ))
+then err_exit '${x+foo "$x" bam} does not yield three arguments'
+fi
+set -- ${x+"foo $x bam"}
+if (( $# !=1 ))
+then err_exit '${x+"foo $x bam"} does not yield one argument'
+fi
+set -- "${x+foo $x bam}"
+if (( $# !=1 ))
+then err_exit '"${x+foo $x bam}" does not yield one argument'
+fi
+set -- ${x+foo "$x "bam}
+if (( $# !=2 ))
+then err_exit '${x+foo "$x "bam} does not yield two arguments'
+fi
+x="ab$'cd"
+if [[ $x != 'ab$'"'cd" ]]
+then err_exit '$'"' inside double quotes not working"
+fi
+x=`print 'ab$'`
+if [[ $x != 'ab$' ]]
+then err_exit '$'"' inside `` quotes not working"
+fi
+unset a
+x=$(print -r -- "'\
+\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in double strings not working'
+fi
+x=$(print -r -- "'\
+$a\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in expanded double strings not working'
+fi
+x='\*'
+if [[ $(print -r -- $x) != '\*' ]]
+then err_exit 'x="\\*";$x != \*'
+fi
+if [[ $(print -r -- "\}" ) != '\}' ]]
+then err_exit '(print -r -- "\}"' not working
+fi
+if [[ $(print -r -- "\{" ) != '\{' ]]
+then err_exit 'print -r -- "\{"' not working
+fi
+# The following caused a syntax error on earlier versions
+foo=foo x=-
+if [[ `eval print \\${foo$x}` != foo* ]]
+then err_exit '`eval print \\${foo$x}`' not working
+fi
+if [[ "`eval print \\${foo$x}`" != foo* ]]
+then err_exit '"`eval print \\${foo$x}`"' not working
+fi
+if ( [[ $() != '' ]] )
+then err_exit '$() not working'
+fi
+x=a:b:c
+set -- $( IFS=:; print $x)
+if (( $# != 3))
+then err_exit 'IFS not working correctly with command substitution'
+fi
+$SHELL -n 2> /dev/null << \! || err_exit '$(...) bug with ( in comment'
+y=$(
+ # ( this line is a bug fix
+ print hi
+)
+!
+x=
+for j in glob noglob
+do for i in 'a\*b' 'a\ b' 'a\bc' 'a\*b' 'a\"b'
+ do eval [[ '$('print -r -- \'$i\'\$x')' != "'$i'" ]] && err_exit "quoting of $i\$x with $j enabled failed"
+ eval [[ '$('print -r -- \'$i\'\${x%*}')' != "'$i'" ]] && err_exit "quoting of $i\${x%*} with $j enabled failed"
+ if [[ $j == noglob ]]
+ then eval [[ '$('print -r -- \'$i\'\${x:-*}')' != "'$i''*'" ]] && err_exit "quoting of $i\${x:-*} with $j enabled failed"
+ fi
+ done
+ set -f
+done
+foo=foo
+[[ "$" == '$' ]] || err_exit '"$" != $'
+[[ "${foo}$" == 'foo$' ]] || err_exit 'foo=foo;"${foo}$" != foo$'
+[[ "${foo}${foo}$" == 'foofoo$' ]] || err_exit 'foo=foo;"${foo}${foo}$" != foofoo$'
+foo='$ '
+[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'$ \' not matching RE \\\\\\$|#\''
+[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'$ \' not matching RE \'\\$\'|#\''
+foo='# '
+[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'# \' not matching RE \\'\$|#\''
+[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'# \' not matching RE \'\\$\'|#\''
+[[ '\$' == '\$'* ]] || err_exit $'\'\\$\' not matching \'\\$\'*'
+[[ a+a == ~(E)a\+a ]] || err_exit '~(E)a\+a not matching a+a'
+[[ a+a =~ a\+a ]] || err_exit 'RE a\+a not matching a+a'
+
+exp='ac'
+got=$'a\0b'c
+[[ $got == "$exp" ]] || err_exit "\$'a\\0b'c expansion failed -- expected '$exp', got '$got'"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/readcsv.sh b/src/cmd/ksh93/tests/readcsv.sh
new file mode 100644
index 0000000..9dd6d9c
--- /dev/null
+++ b/src/cmd/ksh93/tests/readcsv.sh
@@ -0,0 +1,65 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+tmp1=$tmp/tmp1.csv
+tmp2=$tmp/tmp2.csv
+cat > $tmp1 <<- \EOF
+ CAT,"CVE CCODE","NECA OCN",ST,LATA,AP,"New InterState
+ Orig","New Inter""""State
+ Term","New IntraState
+ Orig","New IntraState
+ Term"
+ CLEC,XXXX,AAAA,RB,ABC,comp," 0.2 "," 0.4 "," 0.6 "," 0.8 "
+ CLEC,YYYY,QQQQ,SX,123,mmmm," 0.3 "," 0.5 "," 0.7 "," 0.9 "
+EOF
+integer count=0 nfields
+IFS=${2-,}
+typeset -a arr
+while read -A -S arr
+do ((nfields=${#arr[@]}))
+ if ((++count==1))
+ then ((nfields==10)) || err_exit 'first record should contain 10 fields'
+ [[ ${arr[7]} == $'New Inter""State\nTerm' ]] || err_exit $'7th field of record 1 should contain New Inter""State\nTerm'
+ fi
+ for ((i=0; i < nfields;i++))
+ do delim=$IFS
+ if ((i == nfields-1))
+ then delim=$'\r\n'
+ fi
+ printf "%#q%s" "${arr[i]}" "$delim"
+ done
+done < $tmp1 > $tmp2
+diff "$tmp1" "$tmp2" >/dev/null 2>&1 || err_exit "files $tmp1 and $tmp2 differ"
+
+exit $((Errors<125?Errors:125))
+
diff --git a/src/cmd/ksh93/tests/recttype.sh b/src/cmd/ksh93/tests/recttype.sh
new file mode 100755
index 0000000..9f41d92
--- /dev/null
+++ b/src/cmd/ksh93/tests/recttype.sh
@@ -0,0 +1,70 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Pt_t=(
+ float x=1
+ float y=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+)
+
+typeset -T Rect_t=(
+ Pt_t ll=(x=0 y=0)
+ Pt_t ur=(x=1 y=1)
+ area()
+ {
+ print -r $(( abs((_.ur.x-_.ll.x)*(_.ur.y-_.ll.y)) ))
+ }
+)
+
+for ((i=0; i < 100; i++))
+do
+Rect_t r
+[[ ${r.area} == 1 ]] || err_exit '${r.area} != 1'
+Rect_t s=(
+ Pt_t ur=(x=9 y=9)
+ Pt_t ll=(x=7 y=7)
+)
+[[ ${s.ur.x} == 9 ]] || err_exit ' ${s.ur.x} != 9'
+(( s.ur.x == 9 ))|| err_exit ' ((s.ur.x)) != 9'
+[[ ${s.ll.y} == 7 ]] || err_exit '${s.ll.y} != 7'
+(( s.area == 4 )) || err_exit 'area of s should be 4'
+[[ ${s.area} == 4 ]] || err_exit '${s.area} != 4'
+unset r s
+done
+Rect_t -A r
+r[one]=(ur=(x=4 y=4))
+(( r[one].area == 16 )) || err_exit 'area of r[one] should be 16'
+[[ ${r[one].area} == 16 ]] || err_exit '${r[one].area} should be 16'
+unset r
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/restricted.sh b/src/cmd/ksh93/tests/restricted.sh
new file mode 100755
index 0000000..5699105
--- /dev/null
+++ b/src/cmd/ksh93/tests/restricted.sh
@@ -0,0 +1,83 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test restricted shell
+pwd=$PWD
+case $SHELL in
+/*) ;;
+*/*) SHELL=$pwd/$SHELL;;
+*) SHELL=$(whence "$SHELL");;
+esac
+function check_restricted
+{
+ rm -f out
+ LC_MESSAGES=C rksh -c "$@" 2> out > /dev/null
+ grep restricted out > /dev/null 2>&1
+}
+
+[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
+cd $tmp || err_exit "cd $tmp failed"
+ln -s $SHELL rksh
+PATH=$PWD:$PATH
+rksh -c '[[ -o restricted ]]' || err_exit 'restricted option not set'
+[[ $(rksh -c 'print hello') == hello ]] || err_exit 'unable to run print'
+check_restricted /bin/echo || err_exit '/bin/echo not resticted'
+check_restricted ./echo || err_exit './echo not resticted'
+check_restricted 'SHELL=ksh' || err_exit 'SHELL asignment not resticted'
+check_restricted 'PATH=/bin' || err_exit 'PATH asignment not resticted'
+check_restricted 'FPATH=/bin' || err_exit 'FPATH asignment not resticted'
+check_restricted 'ENV=/bin' || err_exit 'ENV asignment not resticted'
+check_restricted 'print > file' || err_exit '> file not restricted'
+> empty
+check_restricted 'print <> empty' || err_exit '<> file not restricted'
+print 'echo hello' > script
+chmod +x ./script
+! check_restricted script || err_exit 'script without builtins should run in restricted mode'
+check_restricted ./script || err_exit 'script with / in name should not run in restricted mode'
+print '/bin/echo hello' > script
+! check_restricted script || err_exit 'script with pathnames should run in restricted mode'
+print 'echo hello> file' > script
+! check_restricted script || err_exit 'script with output redirection should run in restricted mode'
+print 'PATH=/bin' > script
+! check_restricted script || err_exit 'script with PATH assignment should run in restricted mode'
+cat > script <<!
+#! $SHELL
+print hello
+!
+! check_restricted 'script;:' || err_exit 'script with #! pathname should run in restricted mode'
+! check_restricted 'script' || err_exit 'script with #! pathname should run in restricted mode even if last command in script'
+for i in PATH ENV FPATH
+do check_restricted "function foo { typeset $i=foobar;};foo" || err_exit "$i can be changed in function by using typeset"
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/return.sh b/src/cmd/ksh93/tests/return.sh
new file mode 100755
index 0000000..8c243f5
--- /dev/null
+++ b/src/cmd/ksh93/tests/return.sh
@@ -0,0 +1,183 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+# test the behavior of return and exit with functions
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+unset HISTFILE
+
+foo=NOVAL bar=NOVAL
+file=$tmp/test
+function foo
+{
+ typeset foo=NOEXIT
+ trap "foo=EXIT;rm -f $file" EXIT
+ > $file
+ if (( $1 == 0 ))
+ then return $2
+ elif (( $1 == 1 ))
+ then exit $2
+ else bar "$@"
+ fi
+}
+
+function bar
+{
+ typeset bar=NOEXIT
+ trap 'bar=EXIT' EXIT
+ if (( $1 == 2 ))
+ then return $2
+ elif (( $1 == 3 ))
+ then exit $2
+ fi
+}
+
+function funcheck
+{
+ [[ $foo == EXIT ]] || err_exit "foo "$@" : exit trap not set"
+ if [[ -f $file ]]
+ then rm -r $file
+ err_exit "foo $@: doesn't remove $file"
+ fi
+ foo=NOVAL bar=NOVAL
+}
+
+(exit 0) || err_exit "exit 0 is not zero"
+(return 0) || err_exit "return 0 is not zero"
+(exit) || err_exit "default exit value is not zero"
+(return) || err_exit "default return value is not zero"
+(exit 35)
+ret=$?
+if (( $ret != 35 ))
+then err_exit "exit 35 is $ret not 35"
+fi
+(return 35)
+ret=$?
+if (( $ret != 35 ))
+then err_exit "return 35 is $ret not 35"
+fi
+
+foo 0 0 || err_exit "foo 0 0: incorrect return"
+funcheck 0 0
+foo 0 3
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 0 3: return is $ret not 3"
+fi
+funcheck 0 3
+foo 2 0 || err_exit "foo 2 0: incorrect return"
+[[ $bar == EXIT ]] || err_exit "foo 2 0: bar exit trap not set"
+funcheck 2 0
+foo 2 3
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 2 3: return is $ret not 3"
+fi
+[[ $bar == EXIT ]] || err_exit "foo 2 3: bar exit trap not set"
+funcheck 2 3
+(foo 3 3)
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 3 3: return is $ret not 3"
+fi
+foo=EXIT
+funcheck 3 3
+cat > $file <<!
+return 3
+exit 4
+!
+( . $file )
+ret=$?
+if (( $ret != 3 ))
+then err_exit "return in dot script is $ret should be 3"
+fi
+chmod 755 $file
+( $file )
+ret=$?
+if (( $ret != 3 ))
+then err_exit "return in script is $ret should be 3"
+fi
+cat > $file <<!
+: line 1
+# next line should fail and cause an exit
+: > /
+exit 4
+!
+( . $file ; exit 5 ) 2> /dev/null
+ret=$?
+if (( $ret != 1 ))
+then err_exit "error in dot script is $ret should be 1"
+fi
+( $file; exit 5 ) 2> /dev/null
+ret=$?
+if (( $ret != 5 ))
+then err_exit "error in script is $ret should be 5"
+fi
+cat > $file <<\!
+print -r -- "$0"
+!
+x=$( . $file)
+if [[ $x != $0 ]]
+then err_exit "\$0 in a dot script is $x. Should be $0"
+fi
+x=$($SHELL -i --norc 2> /dev/null <<\!
+typeset -i x=1/0
+print hello
+!
+)
+if [[ $x != hello ]]
+then err_exit "interactive shell terminates with error in bltin"
+fi
+x=$( set -e
+ false
+ print bad
+ )
+if [[ $x != '' ]]
+then err_exit "set -e doesn't terminate script on error"
+fi
+x=$( set -e
+ trap 'exit 0' EXIT
+ false
+ print bad
+ )
+if (( $? != 0 ))
+then err_exit "exit 0 in trap should doesn't set exit value to 0"
+fi
+$SHELL <<\!
+trap 'exit 8' EXIT
+exit 1
+!
+if (( $? != 8 ))
+then err_exit "exit 8 in trap should set exit value to 8"
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/select.sh b/src/cmd/ksh93/tests/select.sh
new file mode 100755
index 0000000..07d0bde
--- /dev/null
+++ b/src/cmd/ksh93/tests/select.sh
@@ -0,0 +1,67 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+PS3='ABC '
+
+cat > $tmp/1 <<\!
+1) foo
+2) bar
+3) bam
+!
+
+select i in foo bar bam
+do case $i in
+ foo) break;;
+ *) err_exit "select 1 not working"
+ break;;
+ esac
+done 2> /dev/null <<!
+1
+!
+
+unset i
+select i in foo bar bam
+do case $i in
+ foo) err_exit "select foo not working" 2>&3
+ break;;
+ *) if [[ $REPLY != foo ]]
+ then err_exit "select REPLY not correct" 2>&3
+ fi
+ ( set -u; : $i ) || err_exit "select: i not set to null" 2>&3
+ break;;
+ esac
+done 3>&2 2> $tmp/2 <<!
+foo
+!
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/shtests b/src/cmd/ksh93/tests/shtests
new file mode 100755
index 0000000..5815aab
--- /dev/null
+++ b/src/cmd/ksh93/tests/shtests
@@ -0,0 +1,235 @@
+: ksh regression test harness :
+
+USAGE_LICENSE="[-author?David Korn <dgk@research.att.com>][-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2000-2011 AT&T Intellectual Property][-license?http://www.opensource.org/licenses/cpl1.0.txt]"
+
+command=shtests
+
+setslocale='*@(locale).sh'
+timesensitive='*@(options|sigchld|subshell).sh'
+
+USAGE=$'
+[-s8?
+@(#)$Id: shtests (AT&T Research) 2011-08-08 $
+]
+'$USAGE_LICENSE$'
+[+NAME?shtests - ksh regression test harness]
+[+DESCRIPTION?\bshtests\b is the \bksh\b(1) regression test harness for
+ \b$SHELL\b or \bksh\b if \bSHELL\b is not defined and exported. If
+ none of the \b--posix --utf8 --compile\b options are specified then
+ all three are enabled.]
+[+INPUT FILES?\bshtests\b regression test files are shell scripts that
+ run in an environment controlled by \bshtests\b. An identification
+ message is printed before and after each test on the standard output.
+ The default environment settings are:]
+ {
+ [+unset LANG]
+ [+unset LC_ALL]
+ [+LC_NUMERIC=C?\b.\b radix point assumed by all test scripts.]
+ [+VMALLOC_OPTIONS=abort?\bvmalloc\b(1) arena checking enabled
+ with \babort(2)\b on error.]
+ }
+[c:compile?Run test scripts using \bshcomp\b(1).]
+[d:debug?Enable \bshtests\b execution trace.]
+[l:locale?Disable \b--utf8\b and run the \b--posix\b and \b--compile\b
+ tests, if enabled, in the locale of the caller. This may cause invalid
+ regressions, especially for locales where \b.\b is not the radix
+ point.]
+[p:posix?Run the test scripts in the posix/C locale.]
+[t!:time?Include the current date/time in the test identification
+ messages.]
+[u:utf8?Run the test scripts in the ast-specific C.UTF-8 locale.]
+[v!:vmalloc_options?Run tests with \bVMALLOC_OPTIONS=abort\b. Test
+ script names matching \b'$timesensitive$'\b are run with
+ \bVMALLOC_OPTIONS\b unset.]
+[x:trace?Enable script execution trace.]
+
+[ test.sh ... ] [ name=value ... ]
+
+[+SEE ALSO?\bksh\b(1), \bregress\b(1), \brt\b(1)]
+'
+
+function usage
+{
+ OPTIND=0
+ getopts -a $command "$USAGE" OPT '--??long'
+ exit 2
+}
+
+unset DISPLAY ENV FIGNORE HISTFILE
+trap + PIPE # unadvertized -- set SIGPIPE to SIG_DFL #
+
+integer compile=0 debug=0 locale=0 posix=0 time=1 utf8=0
+typeset vmalloc_options=abort trace=
+vmalloc_options= #XXX# until multi-region vmalloc trace fixed #XXX#
+
+while getopts -a $command "$USAGE" OPT
+do case $OPT in
+ c) if (( $OPTARG ))
+ then compile=2
+ else compile=0
+ fi
+ ;;
+ d) debug=$OPTARG
+ ;;
+ l) locale=$OPTARG
+ ;;
+ p) posix=$OPTARG
+ ;;
+ t) time=$OPTARG
+ ;;
+ u) utf8=$OPTARG
+ ;;
+ v) if (( OPTARG ))
+ then vmalloc_options=abort
+ else vmalloc_options=
+ fi
+ ;;
+ x) trace=-x
+ ;;
+ *) usage
+ ;;
+ esac
+done
+shift $OPTIND-1
+
+if (( debug )) || [[ $trace ]]
+then export PS4=':$LINENO: '
+ if (( debug ))
+ then set -x
+ fi
+fi
+
+while [[ $1 == *=* ]]
+do eval export "$1"
+ shift
+done
+
+if (( !compile && !posix && !utf8 ))
+then compile=1
+ posix=1
+ utf8=1
+fi
+if (( locale ))
+then utf8=0
+ if [[ $LC_ALL ]]
+ then export LANG=$LC_ALL
+ fi
+else unset LANG LC_ALL
+ export LC_NUMERIC=C
+fi
+if [[ $VMALLOC_OPTIONS ]]
+then vmalloc_options=$VMALLOC_OPTIONS
+else VMALLOC_OPTIONS=$vmalloc_options
+fi
+[[ $VMALLOC_OPTIONS ]] || timesensitive=.
+export PATH PWD SHCOMP SHELL VMALLOC_OPTIONS
+PWD=$(pwd)
+SHELL=${SHELL-ksh}
+case $0 in
+/*) d=$(dirname $0);;
+*/*) d=$PWD/$(dirname $0);;
+*) d=$PWD;;
+esac
+case $SHELL in
+/*) ;;
+*/*) SHELL=$d/$SHELL;;
+*) SHELL=$(whence $SHELL);;
+esac
+PATH=/bin:/usr/bin
+if [[ -d /usr/ucb ]]
+then PATH=$PATH:/usr/ucb
+fi
+PATH=$PATH:$d
+if [[ $INSTALLROOT && -r $INSTALLROOT/bin/.paths ]]
+then PATH=$INSTALLROOT/bin:$PATH
+fi
+if [[ ${SHELL%/*} != $INSTALLROOT/bin ]]
+then PATH=${SHELL%/*}:$PATH
+fi
+if [[ ! $SHCOMP ]]
+then s=${SHELL:##*sh}
+ s=${SHELL:%/*}/shcomp$s
+ if [[ -x $s ]]
+ then SHCOMP=$s
+ elif [[ -x ${s%-g} ]]
+ then SHCOMP=${s%-g}
+ else SHCOMP=shcomp
+ fi
+fi
+if (( compile ))
+then if whence $SHCOMP > /dev/null
+ then tmp=$(mktemp -dt) || { echo mktemp -dt failed >&2; exit 1; }
+ trap "cd /; rm -rf $tmp" EXIT
+ elif (( compile > 1 ))
+ then echo $0: --compile: $SHCOMP not found >&2
+ exit 1
+ else compile=0
+ fi
+fi
+typeset -A tests
+for i in ${*-*.sh}
+do if [[ ! -r $i ]]
+ then echo $0: $i: not found >&2
+ continue
+ fi
+ t=$(grep -c err_exit $i)
+ if (( t > 2 ))
+ then (( t = t - 2 ))
+ fi
+ tests[$i]=$t
+ T=test
+ if (( t != 1 ))
+ then T=${T}s
+ fi
+ u=${i##*/}
+ u=${u%.sh}
+ if [[ $i == $timesensitive ]]
+ then VMALLOC_OPTIONS=
+ fi
+ if (( posix || utf8 ))
+ then locales=
+ (( posix )) && locales+=" ${LANG:-C}"
+ [[ $utf8 == 0 || $i == $setslocale ]] || locales+=" C.UTF-8"
+ for lang in $locales
+ do o=$u
+ if [[ $lang == C ]]
+ then lang=
+ else o="$o($lang)"
+ lang=LANG=$lang
+ fi
+ echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
+ E=error
+ if eval $lang \$SHELL \$trace \$i
+ then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
+ else e=$?
+ if (( e != 1 ))
+ then E=${E}s
+ fi
+ echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
+ fi
+ done
+ fi
+ if (( compile ))
+ then c=$tmp/shcomp-$u.ksh
+ o="$u(shcomp)"
+ echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
+ E=error
+ if $SHCOMP $i > $c
+ then if $SHELL $trace $c
+ then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
+ else e=$?
+ if (( e != 1 ))
+ then E=${E}s
+ fi
+ echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
+ fi
+ else e=$?
+ t=1
+ T=test
+ echo test $o failed to compile ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T 1 $E ]"
+ fi
+ if [[ $i == $timesensitive ]]
+ then VMALLOC_OPTIONS=$vmalloc_options
+ fi
+ fi
+done
diff --git a/src/cmd/ksh93/tests/sigchld.sh b/src/cmd/ksh93/tests/sigchld.sh
new file mode 100755
index 0000000..d4dcee6
--- /dev/null
+++ b/src/cmd/ksh93/tests/sigchld.sh
@@ -0,0 +1,160 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+float DELAY=${1:-0.2}
+integer FOREGROUND=10 BACKGROUND=2 Errors=0
+
+s=$($SHELL -c '
+integer i foreground=0 background=0
+float delay='$DELAY' d=0 s=0
+
+set --errexit
+
+trap "(( background++ ))" CHLD
+
+(( d = delay ))
+for ((i = 0; i < '$BACKGROUND'; i++))
+do sleep $d &
+ (( d *= 4 ))
+ (( s += d ))
+done
+for ((i = 0; i < '$FOREGROUND'; i++))
+do (( foreground++ ))
+ sleep $delay
+ (( s -= delay ))
+ $SHELL -c : > /dev/null # foreground does not generate SIGCHLD
+done
+if (( (s += delay) < 1 ))
+then (( s = 1 ))
+fi
+sleep $s
+wait
+print foreground=$foreground background=$background
+') || err_exit "test loop failed"
+
+eval $s
+
+(( foreground == FOREGROUND )) || err_exit "expected '$FOREGROUND foreground' -- got '$foreground' (DELAY=$DELAY)"
+(( background == BACKGROUND )) || err_exit "expected '$BACKGROUND background' -- got '$background' (DELAY=$DELAY)"
+
+set --noerrexit
+
+if [[ ${.sh.version} == Version?*([[:upper:]])J* ]]
+then
+
+ jobmax=4
+ got=$($SHELL -c '
+ JOBMAX='$jobmax' JOBCOUNT=$(('$jobmax'*2))
+ integer running=0 maxrunning=0
+ trap "((running--))" CHLD
+ for ((i=0; i<JOBCOUNT; i++))
+ do sleep 1 &
+ if ((++running > maxrunning))
+ then ((maxrunning=running))
+ fi
+ done
+ wait
+ print running=$running maxrunning=$maxrunning
+ ')
+ exp='running=0 maxrunning='$jobmax
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected '$exp', got '$got'"
+
+ got=$($SHELL -c '
+ typeset -A proc
+
+ trap "
+ print \${proc[\$!].name} \${proc[\$!].status} \$?
+ unset proc[\$!]
+ " CHLD
+
+ { sleep 3; print a; exit 1; } &
+ proc[$!]=( name=a status=1 )
+
+ { sleep 2; print b; exit 2; } &
+ proc[$!]=( name=b status=2 )
+
+ { sleep 1; print c; exit 3; } &
+ proc[$!]=( name=c status=3 )
+
+ while (( ${#proc[@]} ))
+ do sleep -s
+ done
+ ')
+ exp='c\nc 3 3\nb\nb 2 2\na\na 1 1'
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
+fi
+
+{
+got=$( ( sleep 1;print $'\n') | $SHELL -c 'function handler { : ;}
+ trap handler CHLD; sleep .3 & IFS= read; print good')
+} 2> /dev/null
+[[ $got == good ]] || err_exit 'SIGCLD handler effects read behavior'
+
+set -- $(
+ (
+ $SHELL -xc $'
+ trap \'wait $!; print $! $?\' CHLD
+ { sleep 0.1; exit 9; } &
+ print $!
+ sleep 0.5
+ '
+ ) 2>/dev/null; print $?
+)
+if (( $# != 4 ))
+then err_exit "CHLD trap failed -- expected 4 args, got $#"
+elif (( $4 != 0 ))
+then err_exit "CHLD trap failed -- exit code $4"
+elif (( $1 != $2 ))
+then err_exit "child pid mismatch -- got '$1' != '$2'"
+elif (( $3 != 9 ))
+then err_exit "child status mismatch -- expected '9', got '$3'"
+fi
+
+trap '' CHLD
+integer d
+for ((d=0; d < 2000; d++))
+do if print foo | grep bar
+ then break
+ fi
+done
+(( d==2000 )) || err_exit "trap '' CHLD causes side effects d=$d"
+trap - CHLD
+
+tmp=$(mktemp -dt)
+trap 'rm -rf $tmp' EXIT
+x=$($SHELL 2> /dev/null -ic '/bin/notfound; sleep .5 & sleep 1;jobs')
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after notfound'
+x=$($SHELL 2> /dev/null -ic 'kill -0 12345678901234567876; sleep .5 & sleep 1;jobs')
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after error message'
+print 'set -o monitor;sleep .5 & sleep 1;jobs' > $tmp/foobar
+chmod +x $tmp/foobar
+x=$($SHELL -c "echo | $tmp/foobar")
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked for script at end of pipeline'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/signal.sh b/src/cmd/ksh93/tests/signal.sh
new file mode 100755
index 0000000..c6e150b
--- /dev/null
+++ b/src/cmd/ksh93/tests/signal.sh
@@ -0,0 +1,435 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || err_exit "cd $tmp failed"
+
+unset n s t
+typeset -A SIG
+for s in $(kill -l)
+do if ! n=$(kill -l $s 2>/dev/null)
+ then err_exit "'kill -l $s' failed"
+ elif ! t=$(kill -l $n 2>/dev/null)
+ then err_exit "'kill -l $n' failed"
+ elif [[ $s == ?(SIG)$t ]]
+ then SIG[${s#SIG}]=1
+ elif ! m=$(kill -l $t 2>/dev/null)
+ then err_exit "'kill -l $t' failed"
+ elif [[ $m != $n ]]
+ then err_exit "'kill -l $s' => $n, 'kill -l $n' => $t, kill -l $t => $m -- expected $n"
+ fi
+done
+
+(
+ set --pipefail
+ {
+ $SHELL 2> out2 <<- \EOF
+ g=false
+ trap 'print -u2 PIPED; $g && exit 0;g=true' PIPE
+ while :
+ do print hello
+ done
+ EOF
+ } | head > /dev/null
+ (( $? == 0)) || err_exit "SIGPIPE with wrong error code $?"
+ [[ $(<out2) == $'PIPED\nPIPED' ]] || err_exit 'SIGPIPE output on standard error is not correct'
+) &
+cop=$!
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "pipe with --pipefail PIPE trap hangs"
+fi
+wait
+rm -f out2
+
+[[ $( trap 'print -n got_child' SIGCHLD
+ sleep 2 &
+ for ((i=0; i < 4; i++))
+ do sleep .75
+ print -n $i
+ done) == 01got_child23 ]] || err_exit 'SIGCHLD not working'
+
+# begin standalone SIGINT test generation
+
+cat > tst <<'!'
+# shell trap tests
+#
+# tst control script that calls tst-1, must be run by ksh
+# tst-1 calls tst-2
+# tst-2 calls tst-3
+# tst-3 defaults or handles and discards/propagates SIGINT
+#
+# initial -v option lists script entry and SIGINT delivery
+#
+# three test options
+#
+# d call next script directly, otherwise via $SHELL -c
+# t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x
+# x trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit, otherwise SIGINT default
+# z trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit 0, otherwise SIGINT default
+#
+# Usage: tst [-v] [-options] shell-to-test ...
+
+# "trap + sig" is an unadvertized extension for this test
+# if run from nmake SIGINT is set to SIG_IGN
+# this call sets it back to SIG_DFL
+# semantics w.r.t. function scope must be worked out before
+# making it public
+trap + INT
+
+set -o monitor
+
+function gen
+{
+ typeset o t x d
+ for x in - x z
+ do case $x in
+ [$1]) for t in - t
+ do case $t in
+ [$1]) for d in - d
+ do case $d in
+ [$1]) o="$o $x$t$d"
+ esac
+ done
+ esac
+ done
+ esac
+ done
+ echo '' $o
+}
+
+case $1 in
+-v) v=v; shift ;;
+-*v*) v=v ;;
+*) v= ;;
+esac
+case $1 in
+*' '*) o=$1; shift ;;
+-*) o=$(gen $1); shift ;;
+*) o=$(gen -txd) ;;
+esac
+case $# in
+0) set ksh bash ksh88 pdksh ash zsh ;;
+esac
+for f in $o
+do case $# in
+ 1) ;;
+ *) echo ;;
+ esac
+ for sh
+ do if $sh -c 'exit 0' > /dev/null 2>&1
+ then case $# in
+ 1) printf '%3s ' "$f" ;;
+ *) printf '%16s %3s ' "$sh" "$f" ;;
+ esac
+ $sh tst-1 $v$f $sh > tst.out &
+ wait
+ echo $(cat tst.out)
+ fi
+ done
+done
+case $# in
+1) ;;
+*) echo ;;
+esac
+!
+cat > tst-1 <<'!'
+exec 2>/dev/null
+case $1 in
+*v*) echo 1-main ;;
+esac
+{
+ sleep 2
+ case $1 in
+ *v*) echo "SIGINT" ;;
+ esac
+ kill -s INT 0
+} &
+case $1 in
+*t*) trap '
+ echo 1-intr
+ trap - INT
+ # omitting the self kill exposes shells that deliver
+ # the SIGINT trap but exit 0 for -xt
+ # kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*d*) tst-2 $1 $2; status=$? ;;
+*) $2 -c "tst-2 $1 $2"; status=$? ;;
+esac
+printf '1-%04d\n' $status
+sleep 2
+!
+cat > tst-2 <<'!'
+case $1 in
+*z*) trap '
+ echo 2-intr
+ exit 0
+ ' INT
+ ;;
+*x*) trap '
+ echo 2-intr
+ exit
+ ' INT
+ ;;
+*t*) trap '
+ echo 2-intr
+ trap - INT
+ kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*v*) echo 2-main ;;
+esac
+case $1 in
+*d*) tst-3 $1 $2; status=$? ;;
+*) $2 -c "tst-3 $1 $2"; status=$? ;;
+esac
+printf '2-%04d\n' $status
+!
+cat > tst-3 <<'!'
+case $1 in
+*[xz]*) trap '
+ sleep 2
+ echo 3-intr
+ exit 0
+ ' INT
+ ;;
+*) trap '
+ sleep 2
+ echo 3-intr
+ trap - INT
+ kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*v*) echo 3-main ;;
+esac
+sleep 5
+printf '3-%04d\n' $?
+!
+chmod +x tst tst-?
+
+# end standalone test generation
+
+export PATH=$PATH:
+typeset -A expected
+expected[---]="3-intr"
+expected[--d]="3-intr"
+expected[-t-]="3-intr 2-intr 1-intr 1-0258"
+expected[-td]="3-intr 2-intr 1-intr 1-0258"
+expected[x--]="3-intr 2-intr 1-0000"
+expected[x-d]="3-intr 2-intr 1-0000"
+expected[xt-]="3-intr 2-intr 1-intr 1-0000"
+expected[xtd]="3-intr 2-intr 1-intr 1-0000"
+expected[z--]="3-intr 2-intr 1-0000"
+expected[z-d]="3-intr 2-intr 1-0000"
+expected[zt-]="3-intr 2-intr 1-intr 1-0000"
+expected[ztd]="3-intr 2-intr 1-intr 1-0000"
+
+tst $SHELL > tst.got
+
+while read ops out
+do [[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- expected '${expected[$ops]}', got '$out'"
+done < tst.got
+
+if [[ ${SIG[USR1]} ]]
+then float s=$SECONDS
+ [[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent'
+ (( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal'
+ ((s = SECONDS))
+ [[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent'
+ (( SECONDS-s < 4 )) && err_exit 'parent completes early'
+fi
+
+yes=$(whence -p yes)
+if [[ $yes ]]
+then for exp in TERM VTALRM PIPE
+ do if [[ ${SIG[$exp]} ]]
+ then {
+ $SHELL <<- EOF
+ foo() { return 0; }
+ trap foo EXIT
+ { sleep 2; kill -$exp \$\$; sleep 3; kill -0 \$\$ && kill -KILL \$\$; } &
+ $yes |
+ while read yes
+ do (/bin/date; sleep .1)
+ done > /dev/null
+ EOF
+ } 2>> /dev/null
+ got=$(kill -l $?)
+ [[ $exp == $got ]] || err_exit "kill -$exp \$\$ failed, required termination by signal '$got'"
+ fi
+ done
+fi
+
+SECONDS=0
+$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig ;} 2> /dev/null
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig ;} 2> /dev/null
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished')
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished')
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+trap '' SIGBUS
+[[ $($SHELL -c 'trap date SIGBUS; trap -p SIGBUS') ]] && err_exit 'SIGBUS should not have a trap'
+trap -- - SIGBUS
+
+{
+ x=$(
+ $SHELL <<- \++EOF
+ timeout()
+ {
+ trap 'trap - TERM; return' TERM
+ ( sleep $1; kill -TERM $$ ) >/dev/null 2>&1 &
+ sleep 3
+ }
+ timeout 1
+ print ok
+++EOF
+ )
+} 2> /dev/null
+[[ $x == ok ]] || err_exit 'return without arguments in trap not preserving exit status'
+
+x=$(
+ $SHELL <<- \++EOF
+ set -o pipefail
+ foobar()
+ {
+ for ((i=0; i < 10000; i++))
+ do print abcdefghijklmnopqrstuvwxyz
+ done | head > /dev/null
+ }
+ foobar
+ print ok
+ ++EOF
+)
+[[ $x == ok ]] || err_exit 'SIGPIPE exit status causes PIPE signal to be propogaged'
+
+x=$(
+ $SHELL <<- \EOF
+ trap "print GNAW" URG
+ print 1
+ ( sleep 1 ; kill -URG $$ ; sleep 1 ; print S1 ; )
+ print 2
+EOF
+)
+[[ $x == $'1\nS1\nGNAW\n2' ]] || err_exit 'signal ignored in subshell not propagated to parent'
+
+if [[ ${SIG[RTMIN]} ]]
+then {
+ $SHELL <<- \EOF
+ trap : RTMIN
+ for ((i=0 ; i < 3 ; i++))
+ do sleep 1
+ kill -RTMIN $$ 2> /dev/null
+ done &
+ wait
+ EOF
+ } 2> /dev/null
+ [[ $? == 0 ]] && err_exit 'wait interrupted by caught signal should have non-zero exit status'
+ {
+ $SHELL <<- \EOF
+ for ((i=0 ; i < 3 ; i++))
+ do sleep 1
+ kill -RTMIN $$ 2> /dev/null
+ done &
+ wait
+ EOF
+ } 2> /dev/null
+ [[ $(kill -l $?) == RTMIN ]] || err_exit 'wait interrupted by signal not caught should exit with the value of that signal+256'
+fi
+
+function b
+{
+ sleep 3
+ endb=1
+}
+
+function a
+{
+ trap 'print int' TERM
+ b
+ enda=1
+}
+
+{ /bin/sleep 1;kill -s TERM $$;}&
+unset enda endb
+a
+[[ $endb ]] && err_exit 'TERM signal did not kill function b'
+[[ $enda == 1 ]] || err_exit 'TERM signal killed function a'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/statics.sh b/src/cmd/ksh93/tests/statics.sh
new file mode 100755
index 0000000..7e67279
--- /dev/null
+++ b/src/cmd/ksh93/tests/statics.sh
@@ -0,0 +1,690 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# Written by Roland Mainz <roland.mainz@nrubsig.org>
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors < 127 && Errors++ ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+
+typeset -T test_t=(
+ typeset name
+ typeset cmd
+ typeset expected_output
+)
+
+function testfunc
+{
+ integer line_number=$1
+ typeset cmd="$2"
+ typeset expected_output="$3"
+ typeset output
+
+ output="$($SHELL -c "${cmd}" 2>&1 )"
+
+ [[ "${output}" == "${expected_output}" ]] || err_exit ${line_number} "${output} != ${expected_output}"
+}
+
+# test1: basic tests
+function test1
+{
+ # string
+ testfunc ${LINENO} '(function l { typeset -S x ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true)' "###"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true' ">###"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; (l false) ; l true' ">##"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false; ( ulimit -c 0 ; l false) ; l true' ">##"
+
+ # integer
+ # (normal)
+ testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+ # (int)
+ testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+ # (short)
+ testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+
+ # float
+ testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; l false ; l true )' "2"
+ testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "1.5"
+
+ return 0
+}
+
+# test2: test the more complex datatypes
+function test2
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+
+ test_t -r -a tests=(
+ (
+ name='compound'
+ cmd=$'
+ function l
+ {
+ compound -S s=(
+ integer a=1
+ integer b=2
+ )
+
+ (( s.a++, s.b++ ))
+
+ $1 && printf "a=%d, b=%d\n" s.a s.b
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+ (
+ name='compound_nameref'
+ cmd=$'
+ function l_n
+ {
+ nameref sn=$2
+ (( sn.a++, sn.b++ ))
+
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function l
+ {
+ compound -S s=( a=1 b=2 )
+ l_n $1 s
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='type'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function l
+ {
+ ab_t -S s
+
+ s.increment
+
+ $1 && printf "a=%d, b=%d\n" s.a s.b
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='type_nameref'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function l_n
+ {
+ nameref sn=$2
+
+ sn.increment
+
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function l
+ {
+ ab_t -S s
+ l_n $1 s
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_string_array_appendelement'
+ cmd=$'
+ function ar
+ {
+ typeset -a -S s=( "hello" )
+
+ s+=( "an element" )
+
+ $1 && { printf "%s" "${s[@]}" ; printf "\n" ; }
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='indexed_string_array_nameref_appendelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+ sn+=( "an element" )
+
+ $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; }
+ }
+ function ar
+ {
+ typeset -a -S s=( "hello" )
+ ar_n $1 s
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='associative_string_array_appendelement'
+ cmd=$'
+ function ar
+ {
+ typeset -A -S s=( [0]="hello" )
+
+ s[$(( ${#s[@]} + 1))]="an element"
+
+ $1 && { printf "%s" "${s[@]}" ; printf "\n" ; }
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='associative_string_array_nameref_appendelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn[$(( ${#sn[@]} + 1))]="an element"
+
+ $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; }
+ }
+ function ar
+ {
+ typeset -A -S s=( [0]="hello" )
+ ar_n $1 s
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[5].a++, s[5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [8][5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[8][5].a++, s[8][5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[8][5].a s[8][5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [8][5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[8][5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+ (
+ name='4d_indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [8][5][0][9]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[8][5][0][9].a++, s[8][5][0][9].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[8][5][0][9].a s[8][5][0][9].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='4d_indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [8][5][0][9]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[8][5][0][9]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -A s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[5].a++, s[5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -A s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ s[5].increment
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ?
+
+ s[9][5].increment
+ $1 && printf "a=%d, b=%d\n" s[9][5].a s[9][5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[9][5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -A s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ s[5].increment
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -A s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref currtest=tests[i]
+
+#print -u2 -- "${currtest.cmd}"
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${currtest.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ (( out.res == 0 )) || err_exit "${currtest.name}: Test shell returned with exit code ${out.res}"
+ [[ "${out.stdout}" == "${currtest.expected_output}" ]] || err_exit "${currtest.name}: Expected stdout == $(printf "%q\n" "${currtest.expected_output}"), got $(printf "%q\n" "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${currtest.name}: Expected empty stderr, got $(printf "%q\n" "${out.stderr}")"
+ done
+
+ return 0
+}
+
+# run tests
+test1
+test2
+
+
+# Test visibilty of "global" vs. "static" variables. if we have a "static" variable in a
+# function and "unset" it we should see a global variable with the same
+# name, right ?
+integer hx=5
+function test_hx_scope
+{
+ integer -S hx=9
+ $2 && unset hx
+ $1 && printf 'hx=%d\n' hx
+}
+test_hx_scope false false
+test_hx_scope false false
+# first test the "unset" call in a $(...) subshell...
+[[ "$( test_hx_scope true true )" == 'hx=5' ]] || err_exit "can't see global variable hx after unsetting static variable hx"
+# ... end then test whether the value has changed.
+[[ "${ test_hx_scope true false ;}" == 'hx=9' ]] || err_exit "hx variable somehow changed"
+
+out=$(function fun2
+{
+ nameref sn=$1
+ (( sn.a++, sn.b++ ))
+ $2 && printf "a=%d, b=%d\n" sn.a sn.b
+}
+function fun1
+{
+ compound -S s=( a=0 b=0 )
+ fun2 s $1
+}
+(fun1 false ; fun1 false ; fun1 true)
+(fun1 false ; fun1 false ; fun1 true)
+)
+[[ $out == $'a=3, b=3\na=3, b=3' ]] || err_exit 'static variables in functions with initializers not working'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh
new file mode 100755
index 0000000..819811a
--- /dev/null
+++ b/src/cmd/ksh93/tests/subshell.sh
@@ -0,0 +1,582 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u$Error_fd -n "\t"
+ print -u$Error_fd -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0 Error_fd=2
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+bincat=$(PATH=$(getconf PATH) whence -p cat)
+
+z=()
+z.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
+z.bar[0]=hello
+z.bar[2]=world
+z.bar[1]=(x=4 y=5)
+val='(
+ typeset -a bar=(
+ [0]=hello
+ [2]=world
+ [1]=(
+ x=4
+ y=5
+ )
+ )
+ typeset -A foo=(
+ [one]=hello
+ [three]=hi
+ [two]=(
+ x=3
+ y=4
+ )
+ )
+)'
+[[ $z == "$val" ]] || err_exit 'compound variable with mixed arrays not working'
+z.bar[1]=yesyes
+[[ ${z.bar[1]} == yesyes ]] || err_exit 'reassign of index array compound variable fails'
+z.bar[1]=(x=12 y=5)
+[[ ${z.bar[1]} == $'(\n\tx=12\n\ty=5\n)' ]] || err_exit 'reassign array simple to compound variable fails'
+eval val="$z"
+(
+ z.foo[three]=good
+ [[ ${z.foo[three]} == good ]] || err_exit 'associative array assignment in subshell not working'
+)
+[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
+eval val="$z"
+(
+ z.foo[two]=ok
+ [[ ${z.foo[two]} == ok ]] || err_exit 'associative array assignment to compound variable in subshell not working'
+ z.bar[1]=yes
+ [[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working'
+)
+[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
+
+x=(
+ foo=( qqq=abc rrr=def)
+ bar=( zzz=no rst=fed)
+)
+eval val="$x"
+(
+ unset x.foo
+ [[ ${x.foo.qqq} ]] && err_exit 'x.foo.qqq should be unset'
+ x.foo=good
+ [[ ${x.foo} == good ]] || err_exit 'x.foo should be good'
+)
+[[ $x == "$val" ]] || err_exit 'compound variable changes after unset leaves'
+unset l
+(
+ l=( a=1 b="BE" )
+)
+[[ ${l+foo} != foo ]] || err_exit 'l should be unset'
+
+Error_fd=9
+eval "exec $Error_fd>&2 2>/dev/null"
+
+TEST_notfound=notfound
+while whence $TEST_notfound >/dev/null 2>&1
+do TEST_notfound=notfound-$RANDOM
+done
+
+
+integer BS=1024 nb=64 ss=60 bs no
+for bs in $BS 1
+do $SHELL -c '
+ {
+ sleep '$ss'
+ kill -KILL $$
+ } &
+ set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs')
+ print ${#1}
+ kill $!
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
+ (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}"
+done
+# this time with redirection on the trailing command
+for bs in $BS 1
+do $SHELL -c '
+ {
+ sleep 2
+ sleep '$ss'
+ kill -KILL $$
+ } &
+ set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs' 2>/dev/null)
+ print ${#1}
+ kill $!
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
+ (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs and trailing redirection -- expected $((BS*nb)), got ${no:-0}"
+done
+
+# exercise command substitutuion trailing newline logic w.r.t. pipe vs. tmp file io
+
+set -- \
+ 'post-line print' \
+ '$TEST_unset; ($TEST_fork; print 1); print' \
+ 1 \
+ 'pre-line print' \
+ '$TEST_unset; ($TEST_fork; print); print 1' \
+ $'\n1' \
+ 'multiple pre-line print' \
+ '$TEST_unset; ($TEST_fork; print); print; ($TEST_fork; print 1); print' \
+ $'\n\n1' \
+ 'multiple post-line print' \
+ '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print); print' \
+ 1 \
+ 'intermediate print' \
+ '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print 2); print' \
+ $'1\n\n2' \
+ 'simple variable' \
+ '$TEST_unset; ($TEST_fork; l=2; print "$l"); print $l' \
+ 2 \
+ 'compound variable' \
+ '$TEST_unset; ($TEST_fork; l=(a=2 b="BE"); print "$l"); print $l' \
+ $'(\n\ta=2\n\tb=BE\n)' \
+
+export TEST_fork TEST_unset
+
+while (( $# >= 3 ))
+do txt=$1
+ cmd=$2
+ exp=$3
+ shift 3
+ for TEST_unset in '' 'unset var'
+ do for TEST_fork in '' 'ulimit -c 0'
+ do for TEST_shell in "eval" "$SHELL -c"
+ do if ! got=$($TEST_shell "$cmd")
+ then err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt print failed"
+ elif [[ "$got" != "$exp" ]]
+ then EXP=$(printf %q "$exp")
+ GOT=$(printf %q "$got")
+ err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt command substitution failed -- expected $EXP, got $GOT"
+ fi
+ done
+ done
+ done
+done
+
+r=$( ($SHELL -c '
+ {
+ sleep 32
+ kill -KILL $$
+ } &
+ for v in $(set | sed "s/=.*//")
+ do command unset $v
+ done
+ typeset -Z5 I
+ for ((I = 0; I < 1024; I++))
+ do eval A$I=1234567890
+ done
+ a=$(set 2>&1)
+ print ok
+ kill -KILL $!
+') 2>/dev/null)
+[[ $r == ok ]] || err_exit "large subshell command substitution hangs"
+
+for TEST_command in '' $TEST_notfound
+do for TEST_exec in '' 'exec'
+ do for TEST_fork in '' 'ulimit -c 0;'
+ do for TEST_redirect in '' '>/dev/null'
+ do for TEST_substitute in '' ': $'
+ do
+
+ TEST_test="$TEST_substitute($TEST_fork $TEST_exec $TEST_command $TEST_redirect)"
+ [[ $TEST_test == '('*([[:space:]])')' ]] && continue
+ r=$($SHELL -c '
+ {
+ sleep 2
+ kill -KILL $$
+ } &
+ '"$TEST_test"'
+ kill $!
+ print ok
+ ')
+ [[ $r == ok ]] || err_exit "shell hangs on $TEST_test"
+
+ done
+ done
+ done
+ done
+done
+
+$SHELL -c '( autoload xxxxx);print -n' || err_exit 'autoloaded functions in subshells can cause failure'
+foo=$($SHELL <<- ++EOF++
+ (trap 'print bar' EXIT;print -n foo)
+ ++EOF++
+)
+[[ $foo == foobar ]] || err_exit 'trap on exit when last commands is subshell is not triggered'
+
+err=$(
+ $SHELL 2>&1 <<- \EOF
+ date=$(whence -p date)
+ function foo
+ {
+ x=$( $date > /dev/null 2>&1 ;:)
+ }
+ # consume almost all fds to push the test to the fd limit #
+ integer max=$(ulimit --nofile)
+ (( max -= 6 ))
+ for ((i=20; i < max; i++))
+ do exec {i}>&1
+ done
+ for ((i=0; i < 20; i++))
+ do y=$(foo)
+ done
+ EOF
+) || {
+ err=${err%%$'\n'*}
+ err=${err#*:}
+ err=${err##[[:space:]]}
+ err_exit "nested command substitution with redirections failed -- $err"
+}
+
+exp=0
+$SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ exit '$exp$'
+'
+got=$?
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+exp=ok
+got=$($SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ print '$exp$'
+')
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+
+# command substitution variations #
+set -- \
+ '$(' ')' \
+ '${ ' '; }' \
+ '$(ulimit -c 0; ' ')' \
+ '$( (' ') )' \
+ '${ (' '); }' \
+ '`' '`' \
+ '`(' ')`' \
+ '`ulimit -c 0; ' '`' \
+ # end of table #
+exp=ok
+testcase[1]='
+ if %sexpr "NOMATCH" : ".*Z" >/dev/null%s
+ then print error
+ else print ok
+ fi
+ exit %s
+'
+testcase[2]='
+ function bar
+ {
+ pipeout=%1$sprintf Ok | tr O o%2$s
+ print $pipeout
+ return 0
+ }
+ foo=%1$sbar%2$s || foo="exit status $?"
+ print $foo
+ exit %3$s
+'
+while (( $# >= 2 ))
+do for ((TEST=1; TEST<=${#testcase[@]}; TEST++))
+ do body=${testcase[TEST]}
+ for code in 0 2
+ do got=${ printf "$body" "$1" "$2" "$code" | $SHELL 2>&1 }
+ status=$?
+ if (( status != code ))
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- exit status $status, expected $code"
+ elif [[ $got != $exp ]]
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- got '$got', expected '$exp'"
+ fi
+ done
+ done
+ shift 2
+done
+
+# the next tests loop on all combinations of
+# { SUB CAT INS TST APP } X { file-sizes }
+# where the file size starts at 1Ki and doubles up to and including 1Mi
+#
+# the tests and timeouts are done in async subshells to prevent
+# the test harness from hanging
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+CAT=( cat $bincat )
+INS=( "" "builtin cat; " "builtin -d cat $bincat; " ": > /dev/null; " )
+APP=( "" "; :" )
+TST=(
+ ( CMD='print foo | $cat' EXP=3 )
+ ( CMD='$cat < $tmp/lin' )
+ ( CMD='cat $tmp/lin | $cat' )
+ ( CMD='read v < $tmp/buf; print $v' LIM=4*1024 )
+ ( CMD='cat $tmp/buf | read v; print $v' LIM=4*1024 )
+)
+
+if cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null
+then T=${#TST[@]}
+ TST[T].CMD='$cat <(print foo)'
+ TST[T].EXP=3
+fi
+
+# prime the two data files to 512 bytes each
+# $tmp/lin has newlines every 16 bytes and $tmp/buf has no newlines
+# the outer loop doubles the file size at top
+
+buf=$'1234567890abcdef'
+lin=$'\n1234567890abcde'
+for ((i=0; i<5; i++))
+do buf=$buf$buf
+ lin=$lin$lin
+done
+print -n "$buf" > $tmp/buf
+print -n "$lin" > $tmp/lin
+
+unset SKIP
+for ((n=1024; n<=1024*1024; n*=2))
+do cat $tmp/buf $tmp/buf > $tmp/tmp
+ mv $tmp/tmp $tmp/buf
+ cat $tmp/lin $tmp/lin > $tmp/tmp
+ mv $tmp/tmp $tmp/lin
+ for ((S=0; S<${#SUB[@]}; S++))
+ do for ((C=0; C<${#CAT[@]}; C++))
+ do cat=${CAT[C]}
+ for ((I=0; I<${#INS[@]}; I++))
+ do for ((A=0; A<${#APP[@]}; A++))
+ do for ((T=0; T<${#TST[@]}; T++))
+ do #undent...#
+
+ if [[ ! ${SKIP[S][C][I][A][T]} ]]
+ then eval "{ x=${SUB[S].BEG}${INS[I]}${TST[T].CMD}${APP[A]}${SUB[S].END}; print \${#x}; } >\$tmp/out &"
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+ if [[ ! $got ]] && (( h ))
+ then got=HUNG
+ fi
+ if [[ ${TST[T].EXP} ]]
+ then exp=${TST[T].EXP}
+ else exp=$n
+ fi
+ if [[ $got != $exp ]]
+ then # on failure skip similar tests on larger files sizes #
+ SKIP[S][C][I][A][T]=1
+ siz=$(printf $'%#i' $exp)
+ cmd=${TST[T].CMD//\$cat/$cat}
+ cmd=${cmd//\$tmp\/buf/$siz.buf}
+ cmd=${cmd//\$tmp\/lin/$siz.lin}
+ err_exit "'x=${SUB[S].BEG}${INS[I]}${cmd}${APP[A]}${SUB[S].END} && print \${#x}' failed -- expected '$exp', got '$got'"
+ elif [[ ${TST[T].EXP} ]] || (( TST[T].LIM >= n ))
+ then SKIP[S][C][I][A][T]=1
+ fi
+ fi
+
+ #...indent#
+ done
+ done
+ done
+ done
+ done
+done
+
+# specifics -- there's more?
+
+{
+ cmd='{ exec 5>/dev/null; print "$(eval ls -d . 2>&1 1>&5)"; } >$tmp/out &'
+ eval $cmd
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+} 2>/dev/null
+exp=''
+if [[ ! $got ]] && (( h ))
+then got=HUNG
+fi
+if [[ $got != $exp ]]
+then err_exit "eval '$cmd' failed -- expected '$exp', got '$got'"
+fi
+
+float t1=$SECONDS
+sleep=$(whence -p sleep)
+if [[ $sleep ]]
+then
+ $SHELL -c "( $sleep 5 </dev/null >/dev/null 2>&1 & );exit 0" | cat
+ (( (SECONDS-t1) > 4 )) && err_exit '/bin/sleep& in subshell hanging'
+ ((t1=SECONDS))
+fi
+$SHELL -c '( sleep 5 </dev/null >/dev/null 2>&1 & );exit 0' | cat
+(( (SECONDS-t1) > 4 )) && err_exit 'sleep& in subshell hanging'
+
+exp=HOME=$HOME
+( HOME=/bin/sh )
+got=$(env | grep ^HOME=)
+[[ $got == "$exp" ]] || err_exit "( HOME=/bin/sh ) cleanup failed -- expected '$exp', got '$got'"
+
+cmd='echo $((case x in x)echo ok;esac);:)'
+exp=ok
+got=$($SHELL -c "$cmd" 2>&1)
+[[ $got == "$exp" ]] || err_exit "'$cmd' failed -- expected '$exp', got '$got'"
+
+cmd='eval "for i in 1 2; do eval /bin/echo x; done"'
+exp=$'x\nx'
+got=$($SHELL -c "$cmd")
+if [[ $got != "$exp" ]]
+then EXP=$(printf %q "$exp")
+ GOT=$(printf %q "$got")
+ err_exit "'$cmd' failed -- expected $EXP, got $GOT"
+fi
+
+(
+$SHELL -c 'sleep 20 & pid=$!; { x=$( ( seq 60000 ) );kill -9 $pid;}&;wait $pid'
+) 2> /dev/null
+(( $? )) || err_exit 'nested command substitution with large output hangs'
+
+(.sh.foo=foobar)
+[[ ${.sh.foo} == foobar ]] && err_exit '.sh subvariables in subshells remain set'
+[[ $($SHELL -c 'print 1 | : "$(/bin/cat <(/bin/cat))"') ]] && err_exit 'process substitution not working correctly in subshells'
+
+# config hang bug
+integer i
+for ((i=1; i < 1000; i++))
+do typeset foo$i=$i
+done
+{
+ : $( (ac_space=' '; set | grep ac_space) 2>&1)
+} < /dev/null | cat > /dev/null &
+sleep 1.5
+if kill -KILL $! 2> /dev/null
+then err_exit 'process timed out with hung comsub'
+fi
+wait $! 2> /dev/null
+(( $? > 128 )) && err_exit 'incorrect exit status with comsub'
+
+$SHELL 2> /dev/null -c '[[ ${ print foo },${ print bar } == foo,bar ]]' || err_exit '${ print foo },${ print bar } not working'
+$SHELL 2> /dev/null -c '[[ ${ print foo; },${ print bar } == foo,bar ]]' || err_exit '${ print foo; },${ print bar } not working'
+
+src=$'true 2>&1\n: $(true | true)\n: $(true | true)\n: $(true | true)\n'$(whence -p true)
+exp=ok
+got=$( $SHELL -c "(eval '$src'); echo $exp" )
+[[ $got == "$exp" ]] || err_exit 'subshell eval of pipeline clobbers stdout'
+
+x=$( { time $SHELL -c date >| /dev/null;} 2>&1)
+[[ $x == *real*user*sys* ]] || err_exit 'time { ...;} 2>&1 in $(...) fails'
+
+x=$($SHELL -c '( function fx { export X=123; } ; fx; ); echo $X')
+[[ $x == 123 ]] && err_exit 'global variables set from with functions inside a
+subshell can leave side effects in parent shell'
+
+date=$(whence -p date)
+err() { return $1; }
+( err 12 ) & pid=$!
+: $( $date)
+wait $pid
+[[ $? == 12 ]] || err_exit 'exit status from subshells not being preserved'
+
+if cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null
+then x="$(sed 's/^/Hello /' <(print "Fred" | sort))"
+ [[ $x == 'Hello Fred' ]] || err_exit "process substitution of pipeline in command substitution not working"
+fi
+
+{
+$SHELL <<- \EOF
+ function foo
+ {
+ integer i
+ print -u2 foobar
+ for ((i=0; i < 8000; i++))
+ do print abcdefghijk
+ done
+ print -u2 done
+ }
+ out=$(eval "foo | cat" 2>&1)
+ (( ${#out} == 96011 )) || err_exit "\${#out} is ${#out} should be 96011"
+EOF
+} & pid=$!
+$SHELL -c "{ sleep 2 && kill $pid ;}" 2> /dev/null
+(( $? == 0 )) && err_exit 'process has hung'
+
+{
+x=$( $SHELL <<- \EOF
+ function func1 { typeset IFS; : $(func2); print END ;}
+ function func2 { IFS="BAR"; }
+ func1
+ func1
+EOF
+)
+} 2> /dev/null
+[[ $x == $'END\nEND' ]] || err_exit 'bug in save/restore of IFS in subshell'
+
+true=$(whence -p true)
+date=$(whence -p date)
+tmpf=$tmp/foo
+function fun1
+{
+ $true
+ cd - >/dev/null 2>&1
+ print -u2 -- "$($date) SUCCESS"
+}
+
+print -n $(fun1 2> $tmpf)
+[[ $(< $tmpf) == *SUCCESS ]] || err_exit 'standard error output lost with command substitution'
+
+
+tmpfile=$tmp/foo
+cat > $tmpfile <<-\EOF
+ $SHELL -c 'function g { IFS= ;};function f { typeset IFS;(g);: $V;};f;f'
+ EOF
+$SHELL 2> /dev/null "$tmpfile" || err_exit 'IFS in subshell causes core dump'
+
+unset i
+if [[ -d /dev/fd ]]
+then integer i
+ for ((i=11; i < 29; i++))
+ do if ! [[ -r /dev/fd/$i || -w /dev/fd/$i ]]
+ then a=$($SHELL -c "[[ -r /dev/fd/$i || -w /dev/fd/$i ]]")
+ (( $? )) || err_exit "file descriptor $i not close on exec"
+ fi
+ done
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/substring.sh b/src/cmd/ksh93/tests/substring.sh
new file mode 100755
index 0000000..e79447f
--- /dev/null
+++ b/src/cmd/ksh93/tests/substring.sh
@@ -0,0 +1,628 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0 j=4
+base=/home/dgk/foo//bar
+string1=$base/abcabcabc
+if [[ ${string1:0} != "$string1" ]]
+then err_exit "string1:0"
+fi
+if [[ ${string1: -1} != "c" ]]
+then err_exit "string1: -1"
+fi
+if [[ ${string1:0:1000} != "$string1" ]]
+then err_exit "string1:0"
+fi
+if [[ ${string1:1} != "${string1#?}" ]]
+then err_exit "string1:1"
+fi
+if [[ ${string1:1:4} != home ]]
+then err_exit "string1:1:4"
+fi
+if [[ ${string1: -5:4} != bcab ]]
+then err_exit "string1: -5:4"
+fi
+if [[ ${string1:1:j} != home ]]
+then err_exit "string1:1:j"
+fi
+if [[ ${string1:(j?1:0):j} != home ]]
+then err_exit "string1:(j?1:0):j"
+fi
+if [[ ${string1%*zzz*} != "$string1" ]]
+then err_exit "string1%*zzz*"
+fi
+if [[ ${string1%%*zzz*} != "$string1" ]]
+then err_exit "string1%%*zzz*"
+fi
+if [[ ${string1#*zzz*} != "$string1" ]]
+then err_exit "string1#*zzz*"
+fi
+if [[ ${string1##*zzz*} != "$string1" ]]
+then err_exit "string1##*zzz*"
+fi
+if [[ ${string1%+(abc)} != "$base/abcabc" ]]
+then err_exit "string1%+(abc)"
+fi
+if [[ ${string1%%+(abc)} != "$base/" ]]
+then err_exit "string1%%+(abc)"
+fi
+if [[ ${string1%/*} != "$base" ]]
+then err_exit "string1%/*"
+fi
+if [[ "${string1%/*}" != "$base" ]]
+then err_exit '"string1%/*"'
+fi
+if [[ ${string1%"/*"} != "$string1" ]]
+then err_exit 'string1%"/*"'
+fi
+if [[ ${string1%%/*} != "" ]]
+then err_exit "string1%%/*"
+fi
+if [[ ${string1#*/bar} != /abcabcabc ]]
+then err_exit "string1#*bar"
+fi
+if [[ ${string1##*/bar} != /abcabcabc ]]
+then err_exit "string1#*bar"
+fi
+if [[ "${string1#@(*/bar|*/foo)}" != //bar/abcabcabc ]]
+then err_exit "string1#@(*/bar|*/foo)"
+fi
+if [[ ${string1##@(*/bar|*/foo)} != /abcabcabc ]]
+then err_exit "string1##@(*/bar|*/foo)"
+fi
+if [[ ${string1##*/@(bar|foo)} != /abcabcabc ]]
+then err_exit "string1##*/@(bar|foo)"
+fi
+foo=abc
+if [[ ${foo#a[b*} != abc ]]
+then err_exit "abc#a[b*} != abc"
+fi
+if [[ ${foo//[0-9]/bar} != abc ]]
+then err_exit '${foo//[0-9]/bar} not expanding correctly'
+fi
+foo='(abc)'
+if [[ ${foo#'('} != 'abc)' ]]
+then err_exit "(abc)#( != abc)"
+fi
+if [[ ${foo%')'} != '(abc' ]]
+then err_exit "(abc)%) != (abc"
+fi
+foo=a123b456c
+if [[ ${foo/[0-9]?/""} != a3b456c ]]
+then err_exit '${foo/[0-9]?/""} not expanding correctly'
+fi
+if [[ ${foo//[0-9]/""} != abc ]]
+then err_exit '${foo//[0-9]/""} not expanding correctly'
+fi
+if [[ ${foo/#a/b} != b123b456c ]]
+then err_exit '${foo/#a/b} not expanding correctly'
+fi
+if [[ ${foo/#?/b} != b123b456c ]]
+then err_exit '${foo/#?/b} not expanding correctly'
+fi
+if [[ ${foo/%c/b} != a123b456b ]]
+then err_exit '${foo/%c/b} not expanding correctly'
+fi
+if [[ ${foo/%?/b} != a123b456b ]]
+then err_exit '${foo/%?/b} not expanding correctly'
+fi
+while read -r pattern string expected
+do if (( expected ))
+ then if [[ $string != $pattern ]]
+ then err_exit "$pattern does not match $string"
+ fi
+ if [[ ${string##$pattern} != "" ]]
+ then err_exit "\${$string##$pattern} not null"
+ fi
+ if [ "${string##$pattern}" != '' ]
+ then err_exit "\"\${$string##$pattern}\" not null"
+ fi
+ if [[ ${string/$pattern} != "" ]]
+ then err_exit "\${$string/$pattern} not null"
+ fi
+ else if [[ $string == $pattern ]]
+ then err_exit "$pattern matches $string"
+ fi
+ fi
+done <<- \EOF
+ +(a)*+(a) aabca 1
+ !(*.o) foo.o 0
+ !(*.o) foo.c 1
+EOF
+xx=a/b/c/d/e
+yy=${xx#*/}
+if [[ $yy != b/c/d/e ]]
+then err_exit '${xx#*/} != a/b/c/d/e when xx=a/b/c/d/e'
+fi
+if [[ ${xx//\//\\} != 'a\b\c\d\e' ]]
+then err_exit '${xx//\//\\} not working'
+fi
+x=[123]def
+if [[ "${x//\[@(*)\]/\{\1\}}" != {123}def ]]
+then err_exit 'closing brace escape not working'
+fi
+xx=%28text%29
+if [[ ${xx//%28/abc\)} != 'abc)text%29' ]]
+then err_exit '${xx//%28/abc\)} not working'
+fi
+xx='a:b'
+str='(){}[]*?|&^%$#@l'
+for ((i=0 ; i < ${#str}; i++))
+do [[ $(eval print -r -- \"\${xx//:/\\${str:i:1}}\") == "a${str:i:1}b" ]] || err_exit "substitution of \\${str:i:1}} failed"
+ [[ $(eval print -rn -- \"\${xx//:/\'${str:i:1}\'}\") == "a${str:i:1}b" ]] || err_exit "substitution of '${str:i:1}' failed"
+ [[ $(eval print -r -- \"\${xx//:/\"${str:i:1}\"}\") == "a${str:i:1}b" ]] || err_exit "substitution of \"${str:i:1}\" failed"
+done
+[[ ${xx//:/\\n} == 'a\nb' ]] || err_exit "substituion of \\\\n failed"
+[[ ${xx//:/'\n'} == 'a\nb' ]] || err_exit "substituion of '\\n' failed"
+[[ ${xx//:/"\n"} == 'a\nb' ]] || err_exit "substituion of \"\\n\" failed"
+[[ ${xx//:/$'\n'} == $'a\nb' ]] || err_exit "substituion of \$'\\n' failed"
+unset foo
+foo=one/two/three
+if [[ ${foo//'/'/_} != one_two_three ]]
+then err_exit 'single quoting / in replacements failed'
+fi
+if [[ ${foo//"/"/_} != one_two_three ]]
+then err_exit 'double quoting / in replacements failed'
+fi
+if [[ ${foo//\//_} != one_two_three ]]
+then err_exit 'escaping / in replacements failed'
+fi
+function myexport
+{
+ nameref var=$1
+ if (( $# > 1 ))
+ then export $1=$2
+ fi
+ if (( $# > 2 ))
+ then print $(myexport "$1" "$3" )
+ return
+ fi
+ typeset val
+ val=$(export | grep "^$1=")
+ print ${val#"$1="}
+
+}
+export dgk=base
+if [[ $(myexport dgk fun) != fun ]]
+then err_exit 'export inside function not working'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored after function call'
+fi
+if [[ $(myexport dgk fun fun2) != fun2 ]]
+then err_exit 'export inside function not working with recursive function'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored after recursive function call'
+fi
+if [[ $(dgk=try3 myexport dgk) != try3 ]]
+then err_exit 'name=value not added to export list with function call'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored name=value function call'
+fi
+unset zzz
+if [[ $(myexport zzz fun) != fun ]]
+then err_exit 'export inside function not working for zzz'
+fi
+if [[ $(export | grep "zzz=") ]]
+then err_exit 'zzz exported after function call'
+fi
+set -- foo/bar bam/yes last/file/done
+if [[ ${@/*\/@(*)/\1} != 'bar yes done' ]]
+then err_exit '\1 not working with $@'
+fi
+var=(foo/bar bam/yes last/file/done)
+if [[ ${var[@]/*\/@(*)/\1} != 'bar yes done' ]]
+then err_exit '\1 not working with ${var[@]}'
+fi
+var='abc_d2ef.462abc %%'
+if [[ ${var/+(\w)/Q} != 'Q.462abc %%' ]]
+then err_exit '${var/+(\w)/Q} not workding'
+fi
+if [[ ${var//+(\w)/Q} != 'Q.Q %%' ]]
+then err_exit '${var//+(\w)/Q} not workding'
+fi
+if [[ ${var//+(\S)/Q} != 'Q Q' ]]
+then err_exit '${var//+(\S)/Q} not workding'
+fi
+var=$($SHELL -c 'v=/vin:/usr/vin r=vin; : ${v//vin/${r//v/b}};typeset -p .sh.match') 2> /dev/null
+[[ $var == 'typeset -a .sh.match=((vin vin) )' ]] || err_exit '.sh.match not correct when replacement pattern contains a substring match'
+foo='foo+bar+'
+[[ $(print -r -- ${foo//+/'|'}) != 'foo|bar|' ]] && err_exit "\${foobar//+/'|'}"
+[[ $(print -r -- ${foo//+/"|"}) != 'foo|bar|' ]] && err_exit '${foobar//+/"|"}'
+[[ $(print -r -- "${foo//+/'|'}") != 'foo|bar|' ]] && err_exit '"${foobar//+/'"'|'"'}"'
+[[ $(print -r -- "${foo//+/"|"}") != 'foo|bar|' ]] && err_exit '"${foobar//+/"|"}"'
+unset x
+x=abcedfg
+: ${x%@(d)f@(g)}
+[[ ${.sh.match[0]} == dfg ]] || err_exit '.sh.match[0] not dfg'
+[[ ${.sh.match[1]} == d ]] || err_exit '.sh.match[1] not d'
+[[ ${.sh.match[2]} == g ]] || err_exit '.sh.match[2] not g'
+x=abcedddfg
+: ${x%%+(d)f@(g)}
+[[ ${.sh.match[1]} == ddd ]] || err_exit '.sh.match[1] not ddd'
+unset a b
+a='\[abc @(*) def\]'
+b='[abc 123 def]'
+[[ ${b//$a/\1} == 123 ]] || err_exit "\${var/pattern} not working with \[ in pattern"
+unset foo
+foo='(win32.i386) '
+[[ ${foo/'('/'(x11-'} == '(x11-win32.i386) ' ]] || err_exit "\${var/pattern} not working with ' in pattern"
+$SHELL -c $'v=\'$(hello)\'; [[ ${v//\'$(\'/-I\'$(\'} == -I"$v" ]]' 2> /dev/null || err_exit "\${var/pattern} not working with \$( as pattern"
+unset X
+$SHELL -c '[[ ! ${X[@]:0:300} ]]' 2> /dev/null || err_exit '${X[@]:0:300} with X undefined fails'
+$SHELL -c '[[ ${@:0:300} == "$0" ]]' 2> /dev/null || err_exit '${@:0:300} with no arguments fails'
+i=20030704
+[[ ${i#{6}(?)} == 04 ]] || err_exit '${i#{6}(?)} not working'
+[[ ${i#{6,6}(?)} == 04 ]] || err_exit '${i#{6,6}(?)} not working'
+LC_ALL=posix
+i=" ."
+[[ $(printf "<%s>\n" ${i#' '}) == '<.>' ]] || err_exit 'printf "<%s>\n" ${i#' '} failed'
+unset x
+x=foo
+[[ "${x%o}(1)" == "fo(1)" ]] || err_exit 'print ${}() treated as pattern'
+unset i pattern string
+string=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz
+integer i
+for((i=0; i < ${#string}; i++))
+do pattern+='@(?)'
+done
+[[ $(string=$string $SHELL -c ": \${string/$pattern/}; print \${.sh.match[26]}") == Z ]] || err_exit -u2 'sh.match[26] not Z'
+: ${string/$pattern/}
+(( ${#.sh.match[@]} == 53 )) || err_exit '.sh.match has wrong number of elements'
+[[ ${.sh.match[@]:2:4} == 'B C D E' ]] || err_exit '${.sh.match[@]:2:4} incorrect'
+
+D=$';' E=$'\\\\' Q=$'"' S=$'\'' M='nested pattern substitution failed'
+
+x='-(-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-)-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-()-)-'
+[[ ${x/*%(())*/\1} == '()' ]] || err_exit $M
+x='-(-\)-)-'
+[[ ${x/*%(())*/\1} == '(-\)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(())*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-(-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-[-]-)-'
+[[ ${x/*%(()[])*/\1} == '(-[-]-)' ]] || err_exit $M
+x='-[-(-)-]-'
+[[ ${x/*%(()[])*/\1} == '(-)' ]] || err_exit $M
+x='-(-[-)-]-'
+[[ ${x/*%(()[])*/\1} == '-(-[-)-]-' ]] || err_exit $M
+x='-(-[-]-)-'
+[[ ${x/*%([]())*/\1} == '[-]' ]] || err_exit $M
+x='-[-(-)-]-'
+[[ ${x/*%([]())*/\1} == '[-(-)-]' ]] || err_exit $M
+x='-(-[-)-]-'
+[[ ${x/*%([]())*/\1} == '-(-[-)-]-' ]] || err_exit $M
+
+x='-((-))-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g)*%(())*/\1} == '((-))-' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g:*)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g:*)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g)*(?)*%(())*(?)*/:\1:\2:\3:} == '::((-))::-' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g:*(?))*%(())*(?)*/:\1:\2:\3:} == '::(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g)*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g:*(?))*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='call(a+b,x/(c/d),(0));'
+[[ ${x/+([[:alnum:]])*([[:space:]])@(*%(()))*/:\1:\2:\3:} == ':call::(a+b,x/(c/d),(0)):' ]] || err_exit $M
+
+x='-(-;-)-'
+[[ ${x/*%(()D${D})*/\1} == '-(-;-)-' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M
+x='-(-\;-)-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-\;-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)\;-)-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M
+
+x='-(-")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M
+x=$'-(-\\\'")\\\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x=$'-(-\'")\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\'")\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x='-(-")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M
+
+x='-(-\)-)-'
+[[ ${x/*%(()E${E})*/\1} == '(-\)-)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(()E${E})*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M
+x=$'-(-\'")"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'-(-\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"\'-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M
+
+x='-(-;-)-'
+[[ ${x/*%(()D\;)*/\1} == '-(-;-)-' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M
+x='-(-\;-)-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-\;-)' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)\;-)-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+
+x='-(-")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M
+x=$'-(-\\\'")\\\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x=$'-(-\'")\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\'")\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x='-(-")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M
+
+x='-(-\)-)-'
+[[ ${x/*%(()E\\)*/\1} == '(-\)-)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(()E\\)*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M
+x=$'-(-\'")"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'-(-\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"\'-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M
+
+pattern=00
+var=100
+[[ $( print $(( ${var%%00} )) ) == 1 ]] || err_exit "arithmetic with embeddded patterns fails"
+[[ $( print $(( ${var%%$pattern} )) ) == 1 ]] || err_exit "arithmetic with embeddded pattern variables fails"
+if [[ ax == @(a)* ]] && [[ ${.sh.match[1]:0:${#.sh.match[1]}} != a ]]
+then err_exit '${.sh.match[1]:1:${#.sh.match[1]}} not expanding correctly'
+fi
+
+string='foo(d:\nt\box\something)bar'
+expected='d:\nt\box\something'
+[[ ${string/*\(+([!\)])\)*/\1} == "$expected" ]] || err_exit "substring expansion failed '${string/*\(+([!\)])\)*/\1}' returned -- '$expected' expected"
+if [[ $($SHELL -c $'export LC_ALL=C.UTF-8; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ]]
+then LC_ALL=C.UTF-8 $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly'
+fi
+{ $SHELL -c 'unset x;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is not set'
+{ $SHELL -c 'x=;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is null'
+
+# subject mode pattern result #
+set -- \
+ 'a$z' 'E' '[$]|#' 'a($)z' \
+ 'a#z' 'E' '[$]|#' 'a(#)z' \
+ 'a$z' 'Elr' '[$]|#' 'a$z' \
+ 'a#z' 'Elr' '[$]|#' 'a#z' \
+ 'a$' 'E' '[$]|#' 'a($)' \
+ 'a#' 'E' '[$]|#' 'a(#)' \
+ 'a$' 'Elr' '[$]|#' 'a$' \
+ 'a#' 'Elr' '[$]|#' 'a#' \
+ '$z' 'E' '[$]|#' '($)z' \
+ '#z' 'E' '[$]|#' '(#)z' \
+ '$z' 'Elr' '[$]|#' '$z' \
+ '#z' 'Elr' '[$]|#' '#z' \
+ '$' 'E' '[$]|#' '($)' \
+ '#' 'E' '[$]|#' '(#)' \
+ '$' 'Elr' '[$]|#' '($)' \
+ '#' 'Elr' '[$]|#' '(#)' \
+ 'a$z' 'E' '\$|#' 'a$z()' \
+ 'a$z' 'E' '\\$|#' 'a$z' \
+ 'a$z' 'E' '\\\$|#' 'a($)z' \
+ 'a#z' 'E' '\\\$|#' 'a(#)z' \
+ 'a$z' 'Elr' '\\\$|#' 'a$z' \
+ 'a#z' 'Elr' '\\\$|#' 'a#z' \
+ 'a$' 'E' '\\\$|#' 'a($)' \
+ 'a#' 'E' '\\\$|#' 'a(#)' \
+ 'a$' 'Elr' '\\\$|#' 'a$' \
+ 'a#' 'Elr' '\\\$|#' 'a#' \
+ '$z' 'E' '\\\$|#' '($)z' \
+ '#z' 'E' '\\\$|#' '(#)z' \
+ '$z' 'Elr' '\\\$|#' '$z' \
+ '#z' 'Elr' '\\\$|#' '#z' \
+ '$' 'E' '\\\$|#' '($)' \
+ '#' 'E' '\\\$|#' '(#)' \
+ '$' 'Elr' '\\\$|#' '($)' \
+ '#' 'Elr' '\\\$|#' '(#)' \
+# do not delete this line #
+unset i o
+while (( $# >= 4 ))
+do i=$1
+ eval o="\${i/~($2)$3/\\(\\0\\)}"
+ if [[ "$o" != "$4" ]]
+ then err_exit "i='$1'; \${i/~($2)$3/\\(\\0\\)} failed -- expected '$4', got '$o'"
+ fi
+ eval o="\${i/~($2)($3)/\\(\\1\\)}"
+ if [[ "$o" != "$4" ]]
+ then err_exit "i='$1'; \${i/~($2)($3)/\\(\\1\\)} failed -- expected '$4', got '$o'"
+ fi
+ shift 4
+done
+
+#multibyte locale tests
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:0:1}" == a || err_exit ${x:0:1} should be a'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:1}" == "<2b|>" || err_exit ${x:1:1} should be <2b|>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:3:1}" == "<3d|\\>" || err_exit ${x:3:1} should be <3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:4:1}" == e || err_exit ${x:4:1} should bee'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1}" == "<2b|>c<3d|\\>e" || print -u2 ${x:1}" should be <2b|>c<3d|\>e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x: -1:1}" == e || err_exit ${x: -1:1} should be e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x: -2:1}" == "<3d|\\>" || err_exit ${x: -2:1} == <3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:3}" == "<2b|>c<3d|\\>" || err_exit ${x:1:3} should be <2b|>c<3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:20}" == "<2b|>c<3d|\\>e" || err_exit ${x:1:20} should be <2b|>c<3d|\>e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x#??}" == "c<3d|\\>e" || err_exit "${x#??} should be c<3d|\>e'
+
+x='a one and a two'
+[[ "${x//~(E)\<.\>/}" == ' one and two' ]] || err_exit "\< and \> not working in with ere's"
+
+{
+$SHELL -c 'typeset x="123" ; integer i=100 ; print -n "${x:i:5}"'
+} 2> /dev/null || err_exit '${x:i:j} fails when i > strlen(x)'
+
+got=$($SHELL -c 'A=""; B="B"; for I in ${A[@]} ${B[@]}; do echo "\"$I\""; done')
+[[ $got == $'"B"' ]] || err_exit '"\"$I\"" fails when $I is empty string'
+
+A='|'
+[[ $A == $A ]] || err_exit 'With A="|", [[ $A == $A ]] does not match'
+
+x="111 222 333 444 555 666"
+[[ $x == ~(E)(...).(...).(...) ]]
+[[ -v .sh.match[0] ]] || err_exit '[[ -v .sh.match[0] ]] should be true'
+[[ -v .sh.match[3] ]] || err_exit '[[ -v .sh.match[3] ]] should be true'
+[[ -v .sh.match[4] ]] && err_exit '[[ -v .sh.match[4] ]] should be false'
+[[ ${#.sh.match[@]} == 4 ]] || err_exit "\${#.sh.match[@]} should be 4, not ${#.sh.match[@]}"
+
+x="foo bar"
+dummy=${x/~(E)(*)/}
+[[ ${ print -v .sh.match;} ]] && err_exit 'print -v should show .sh.match empty when there are no matches'
+
+if $SHELL -c 'set 1 2 3 4 5 6 7 8 9 10 11 12; : ${##[0-9]}' 2>/dev/null
+then set 1 2 3 4 5 6 7 8 9 10 11 12
+ [[ ${##[0-9]} == 2 ]] || err_exit '${##[0-9]} should be 2 with $#==12'
+ [[ ${###[0-9]} == 2 ]] || err_exit '${###[0-9]} should be 2 with $#==12'
+ [[ ${#%[0-9]} == 1 ]] || err_exit '${#%[0-9]} should be 1 with $#==12'
+ [[ ${#%%[0-9]} == 1 ]] || err_exit '${#%%[0-9]} should be 1 with $#==12'
+else err_exit '${##[0-9]} give syntax error'
+fi
+
+{
+ $SHELL -c 'x="a123 456 789z"; : ${x//{3}(\d)/ }' &
+ sleep .5; kill $!; wait $!
+} 2> /dev/null || err_exit $'tokenizer can\'t handle ${var op {..} }'
+
+
+function foo
+{
+ typeset x="123 456 789 abc"
+ typeset dummy="${x/~(E-g)([[:digit:]][[:digit:]])((X)|([[:digit:]]))([[:blank:]])/_}"
+ exp=$'(\n\t[0]=\'123 \'\n\t[1]=12\n\t[2]=3\n\t[4]=3\n\t[5]=\' \'\n)'
+ [[ $(print -v .sh.match) == "$exp" ]] || err_exit '.sh.match not correct with alternations'
+}
+foo
+
+x="a 1 b"
+d=${x/~(E)(([[:digit:]])[[:space:]]*|([[:alpha:]]))/X}
+[[ $(print -v .sh.match) == $'(\n\t[0]=a\n\t[1]=a\n\t[3]=a\n)' ]] || err_exit '.sh.match not sparse'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/tilde.sh b/src/cmd/ksh93/tests/tilde.sh
new file mode 100755
index 0000000..b044723
--- /dev/null
+++ b/src/cmd/ksh93/tests/tilde.sh
@@ -0,0 +1,101 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r $Command: "$@"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if $SHELL -c '[[ ~root == /* ]]'
+then x=$(print -r -- ~root)
+ [[ $x == ~root ]] || err_exit '~user expanded in subshell prevent ~user from working'
+fi
+
+function home # id
+{
+ typeset IFS=: pwd=/etc/passwd
+ set -o noglob
+ if [[ -f $pwd ]] && grep -c "^$1:" $pwd > /dev/null
+ then set -- $(grep "^$1:" $pwd)
+ print -r -- "$6"
+ else print .
+ fi
+}
+
+OLDPWD=/bin
+if [[ ~ != $HOME ]]
+then err_exit '~' not $HOME
+fi
+x=~
+if [[ $x != $HOME ]]
+then err_exit x=~ not $HOME
+fi
+x=x:~
+if [[ $x != x:$HOME ]]
+then err_exit x=x:~ not x:$HOME
+fi
+if [[ ~+ != $PWD ]]
+then err_exit '~' not $PWD
+fi
+x=~+
+if [[ $x != $PWD ]]
+then err_exit x=~+ not $PWD
+fi
+if [[ ~- != $OLDPWD ]]
+then err_exit '~' not $PWD
+fi
+x=~-
+if [[ $x != $OLDPWD ]]
+then err_exit x=~- not $OLDPWD
+fi
+for u in root Administrator
+do h=$(home $u)
+ if [[ $h != . ]]
+ then [[ ~$u -ef $h ]] || err_exit "~$u not $h"
+ x=~$u
+ [[ $x -ef $h ]] || x="~$u not $h"
+ break
+ fi
+done
+x=~g.r.emlin
+if [[ $x != '~g.r.emlin' ]]
+then err_exit "x=~g.r.emlin failed -- expected '~g.r.emlin', got '$x'"
+fi
+x=~:~
+if [[ $x != "$HOME:$HOME" ]]
+then err_exit "x=~:~ failed, expected '$HOME:$HOME', got '$x'"
+fi
+HOME=/
+[[ ~ == / ]] || err_exit '~ should be /'
+[[ ~/foo == /foo ]] || err_exit '~/foo should be /foo when ~==/'
+print $'print ~+\n[[ $1 ]] && $0' > $tmp/tilde
+chmod +x $tmp/tilde
+nl=$'\n'
+[[ $($tmp/tilde foo) == "$PWD$nl$PWD" ]] 2> /dev/null || err_exit 'tilde fails inside a script run by name'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/timetype.sh b/src/cmd/ksh93/tests/timetype.sh
new file mode 100755
index 0000000..16453c4
--- /dev/null
+++ b/src/cmd/ksh93/tests/timetype.sh
@@ -0,0 +1,81 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Time_t=(
+ integer .=-1
+ _='%F+%H:%M'
+ get()
+ {
+ if (( _ < 0 ))
+ then .sh.value=${ printf "%(${_._})T" now ;}
+ else .sh.value=${ printf "%(${_._})T" "#$((_))" ;}
+ fi
+ }
+ set()
+ {
+ .sh.value=${ printf "%(%#)T" "${.sh.value}";}
+ }
+)
+
+d=$(printf "%(%F+%H:%M)T" now)
+integer s=$(printf "%(%#)T" "$d")
+Time_t t=$d
+[[ $t == "$d" ]] || err_exit "printf %T != Time_t -- expected '$d', got '$t'"
+(( t == s )) || err_exit "numeric Time_t failed -- expected '$s', got '$t'"
+t._='%#'
+[[ $t == $s ]] || err_exit "t._='%#' failed -- expected '$s', got '$t'"
+unset t
+Time_t tt=(yesterday today tomorrow)
+tt[3]=2pm
+[[ ${!tt[@]} == '0 1 2 3' ]] || err_exit "indexed array subscript names failed -- expected '0 1 2 3', got '${!tt[@]}'"
+[[ ${tt[0]} == *+00:00 ]] || err_exit "tt[0] failed -- expected 00:00, got '${tt[0]##*+}'"
+[[ ${tt[1]} == *+00:00 ]] || err_exit "tt[1] failed -- expected 00:00, got '${tt[1]##*+}'"
+[[ ${tt[2]} == *+00:00 ]] || err_exit "tt[2] failed -- expected 00:00, got '${tt[2]##*+}'"
+[[ ${tt[3]} == *+14:00 ]] || err_exit "tt[3] failed -- expected 14:00, got '${tt[3]##*+}'"
+unset tt
+Time_t tt=('2008-08-11+00:00:00,yesterday' '2008-08-11+00:00:00,today' '2008-08-11+00:00:00,tomorrow')
+tt[3]=9am
+tt[4]=5pm
+(( (tt[1] - tt[0]) == 24*3600 )) || err_exit "today-yesterday='$((tt[1] - tt[0]))' != 1 day"
+(( (tt[2] - tt[1]) == 24*3600 )) || err_exit "tomorrow-today='$((tt[2] - tt[1]))' != 1 day"
+(( (tt[4] - tt[3]) == 8*3600 )) || err_exit "9am..5pm='$((tt[4] - tt[3]))' != 8 hours"
+unset tt
+Time_t tt=([yesterday]='2008-08-11+00:00:00,yesterday' [today]='2008-08-11+00:00:00,today' [tomorrow]='2008-08-11+00:00:00,tomorrow')
+tt[2pm]='2008-08-11+00:00:00,2pm'
+[[ ${tt[yesterday]} == *+00:00 ]] || err_exit "tt[yesterday] failed -- expected 00:00, got '${tt[yesterday]##*+}'"
+[[ ${tt[today]} == *+00:00 ]] || err_exit "tt[today] failed -- expected 00:00, got '${tt[today]##*+}'"
+[[ ${tt[tomorrow]} == *+00:00 ]] || err_exit "tt[tomorrow] failed -- expected 00:00, got '${tt[tomorrow]##*+}'"
+[[ ${tt[2pm]} == *+14:00 ]] || err_exit "tt[2pm] failed -- expected 14:00, got '${tt[2pm]##*+}'"
+(( (tt[today] - tt[yesterday] ) == 24*3600 )) || err_exit "tt[today]-tt[yesterday] failed -- expected 24*3600, got $(((tt[today]-tt[yesterday])/3600.0))*3600"
+(( (tt[tomorrow] - tt[today] ) == 24*3600 )) || err_exit "tt[tomorrow]-tt[today] failed -- expected 24*3600, got $(((tt[tomorrow]-tt[today])/3600.0))*3600"
+(( (tt[2pm] - tt[today] ) == 14*3600 )) || err_exit "tt[2pm]-tt[today] failed -- expected 14*3600, got $(((tt[2pm]-tt[today])/3600.0))*3600"
+unset tt
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/treemove.sh b/src/cmd/ksh93/tests/treemove.sh
new file mode 100755
index 0000000..8e293c0
--- /dev/null
+++ b/src/cmd/ksh93/tests/treemove.sh
@@ -0,0 +1,163 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether "typeset -m" correctly moves local variables
+# into a global variable tree.
+#
+# This was reported as CR #XXXXXXXX ("XXXX"):
+# -- snip --
+#XXXX
+# -- snip --
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+
+## test start
+typeset -C tree1 tree2
+
+# add node to tree which uses "typeset -m" to move a local variable
+# into tree1.subtree["a_node"]
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+ # move local note into the array
+false
+ typeset -m tr.subtree["a_node"]=node
+ return 0
+}
+
+# Alternative version which uses "nameref" instead of "typeset -m"
+function f2
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ nameref node=tr.subtree["a_node"]
+ node.one="hello"
+ node.two="world"
+ return 0
+}
+
+f1 tree1
+f2 tree2
+
+[[ "${tree1.subtree["a_node"].one}" == "hello" ]] || err_exit "expected tree1.subtree[\"a_node\"].one == 'hello', got ${tree1.subtree["a_node"].one}"
+[[ "${tree1.subtree["a_node"].two}" == "world" ]] || err_exit "expected tree1.subtree[\"a_node\"].two == 'world', got ${tree1.subtree["a_node"].two}"
+[[ "${tree1}" == "${tree2}" ]] || err_exit "tree1 and tree2 differ:$'\n'"
+
+unset c
+compound c
+typeset -C -a c.ar
+c.ar[4]=( a4=1 )
+typeset -m "c.ar[5]=c.ar[4]"
+exp=$'(\n\ttypeset -C -a ar=(\n\t\t[5]=(\n\t\t\ta4=1\n\t\t)\n\t)\n)'
+[[ $(print -v c) == "$exp" ]] || err_exit 'typeset -m "c.ar[5]=c.ar[4]" not working'
+
+typeset -T x_t=( hello=world )
+function m
+{
+ compound c
+ compound -a c.x
+ x_t c.x[4][5][8].field
+ x_t x
+ typeset -m c.x[4][6][9].field=x
+ exp=$'(\n\ttypeset -C -a x=(\n\t\t[4]=(\n\t\t\t[5]=(\n\t\t\t\t[8]=(\n\t\t\t\t\tx_t field=(\n\t\t\t\t\t\thello=world\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t\t[6]=(\n\t\t\t\t[9]=(\n\t\t\t\t\tx_t field=(\n\t\t\t\t\t\thello=world\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || err_exit "typeset -m c.x[4][6][9].field=x where x is a type is not working"
+}
+m
+
+function moveme
+{
+ nameref src=$2 dest=$1
+ typeset -m dest=src
+}
+function main
+{
+ compound a=( aa=1 )
+ compound -a ar
+ moveme ar[4] a 2> /dev/null || err_exit 'function moveme fails'
+ exp=$'(\n\t[4]=(\n\t\taa=1\n\t)\n)'
+ [[ $(print -v ar) == "$exp" ]] || err_exit 'typeset -m dest=src where dest and src are name references fails'
+}
+main
+
+
+{
+$SHELL <<- \EOF
+ function main
+ {
+ compound c=(
+ compound -a board
+ )
+ for ((i=0 ; i < 2 ; i++ )) ; do
+ compound el=(typeset id='pawn')
+ typeset -m "c.board[1][i]=el"
+ done
+ exp=$'(\n\ttypeset -C -a board=(\n\t\t[1]=(\n\t\t\t(\n\t\t\t\tid=pawn\n\t\t\t)\n\t\t\t(\n\t\t\t\tid=pawn\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || exit 1
+ }
+ main
+EOF
+} 2> /dev/null
+if ((exitval=$?))
+then if [[ $(kill -l $exitval) == SEGV ]]
+ then err_exit 'typeset -m "c.board[1][i]=el" core dumps'
+ else err_exit 'typeset -m "c.board[1][i]=el" gives wrong value'
+ fi
+fi
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/types.sh b/src/cmd/ksh93/tests/types.sh
new file mode 100755
index 0000000..e8f82e1
--- /dev/null
+++ b/src/cmd/ksh93/tests/types.sh
@@ -0,0 +1,632 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+integer n=2
+
+typeset -T Type_t=(
+ typeset name=foobar
+ typeset x=(hi=ok bar=yes)
+ typeset y=(xa=xx xq=89)
+ typeset -A aa=([one]=abc [two]=def)
+ typeset -a ia=(abc def)
+ typeset -i z=5
+)
+for ((i=0; i < 10; i++))
+do
+ Type_t r s
+ [[ $r == "$s" ]] || err_exit 'r is not equal to s'
+ typeset -C x=r.x
+ y=(xa=bb xq=cc)
+ y2=xyz
+ z2=xyz
+ typeset -C z=y
+ [[ $y == "$z" ]] || err_exit 'y is not equal to z'
+ typeset -C s.y=z
+ [[ $y == "${s.y}" ]] || err_exit 'y is not equal to s.y'
+ .sh.q=$y
+ typeset -C www=.sh.q
+ [[ $www == "$z" ]] || err_exit 'www is not equal to z'
+ typeset -C s.x=r.x
+ [[ ${s.x} == "${r.x}" ]] || err_exit 's.x is not equal to r.x'
+
+ function foo
+ {
+ nameref x=$1 y=$2
+ typeset z=$x
+ y=$x
+ [[ $x == "$y" ]] || err_exit "x is not equal to y with ${!x}"
+ }
+ foo r.y y
+ [[ $y == "${r.y}" ]] || err_exit 'y is not equal to r.y'
+ typeset -C y=z
+ foo y r.y
+ [[ $y == "${r.y}" ]] || err_exit 'y is not equal to r.y again'
+ typeset -C y=z
+ (
+ q=${z}
+ [[ $q == "$z" ]] || err_exit 'q is not equal to z'
+ z=abc
+ )
+ [[ $z == "$y" ]] || err_exit 'value of z not preserved after subshell'
+ unset z y r s x z2 y2 www .sh.q
+done
+typeset -T Frame_t=( typeset file lineno )
+Frame_t frame
+[[ $(typeset -p frame) == 'Frame_t frame=(typeset file;typeset lineno)' ]] || err_exit 'empty fields in type not displayed'
+x=( typeset -a arr=([2]=abc [4]=(x=1 y=def));zz=abc)
+typeset -C y=x
+[[ "$x" == "$y" ]] || print -u2 'y is not equal to x'
+Type_t z=(y=(xa=bb xq=cc))
+typeset -A arr=([foo]=one [bar]=2)
+typeset -A brr=([foo]=one [bar]=2)
+[[ "${arr[@]}" == "${brr[@]}" ]] || err_exit 'arr is not brr'
+for ((i=0; i < 1; i++))
+do typeset -m zzz=x
+ [[ $zzz == "$y" ]] || err_exit 'zzz is not equal to y'
+ typeset -m x=zzz
+ [[ $x == "$y" ]] || err_exit 'x is not equal to y'
+ Type_t t=(y=(xa=bb xq=cc))
+ typeset -m r=t
+ [[ $r == "$z" ]] || err_exit 'r is not equal to z'
+ typeset -m t=r
+ [[ $t == "$z" ]] || err_exit 't is not equal to z'
+ typeset -m crr=arr
+ [[ "${crr[@]}" == "${brr[@]}" ]] || err_exit 'crr is not brr'
+ typeset -m arr=crr
+ [[ "${arr[@]}" == "${brr[@]}" ]] || err_exit 'brr is not arr'
+done
+typeset -m brr[foo]=brr[bar]
+[[ ${brr[foo]} == 2 ]] || err_exit 'move an associative array element fails'
+[[ ${brr[bar]} ]] && err_exit 'brr[bar] should be unset after move'
+unset x y zzz
+x=(a b c)
+typeset -m x[1]=x[2]
+[[ ${x[1]} == c ]] || err_exit 'move an indexed array element fails'
+[[ ${x[2]} ]] && err_exit 'x[2] should be unset after move'
+cat > $tmp/types <<- \+++
+ typeset -T Pt_t=(float x=1. y=0.)
+ Pt_t p=(y=2)
+ print -r -- ${p.y}
++++
+expected=2
+got=$(. $tmp/types) 2>/dev/null
+[[ "$got" == "$expected" ]] || err_exit "typedefs in dot script failed -- expected '$expected', got '$got'"
+typeset -T X_t=(
+ typeset x=foo y=bar
+ typeset s=${_.x}
+ create()
+ {
+ _.y=bam
+ }
+)
+X_t x
+[[ ${x.x} == foo ]] || err_exit 'x.x should be foo'
+[[ ${x.y} == bam ]] || err_exit 'x.y should be bam'
+[[ ${x.s} == ${x.x} ]] || err_exit 'x.s should be x.x'
+typeset -T Y_t=( X_t r )
+Y_t z
+[[ ${z.r.x} == foo ]] || err_exit 'z.r.x should be foo'
+[[ ${z.r.y} == bam ]] || err_exit 'z.r.y should be bam'
+[[ ${z.r.s} == ${z.r.x} ]] || err_exit 'z.r.s should be z.r.x'
+
+unset xx yy
+typeset -T xx=(typeset yy=zz)
+xx=yy
+{ typeset -T xx=(typeset yy=zz) ;} 2>/dev/null && err_exit 'type redefinition should fail'
+$SHELL 2> /dev/null <<- +++ || err_exit 'typedef with only f(){} fails'
+ typeset -T X_t=(
+ f()
+ {
+ print ok
+ }
+ )
++++
+$SHELL 2> /dev/null <<- +++ || err_exit 'unable to redefine f discipline function'
+ typeset -T X_t=(
+ x=1
+ f()
+ {
+ print ok
+ }
+ )
+ X_t z=(
+ function f
+ {
+ print override f
+ }
+ )
++++
+$SHELL 2> /dev/null <<- +++ && err_exit 'invalid discipline name should be an error'
+ typeset -T X_t=(
+ x=1
+ f()
+ {
+ print ok
+ }
+ )
+ X_t z=(
+ function g
+ {
+ print override f
+ }
+ )
++++
+# compound variables containing type variables
+Type_t r
+var=(
+ typeset x=foobar
+ Type_t r
+ integer z=5
+)
+[[ ${var.r} == "$r" ]] || err_exit 'var.r != r'
+(( var.z == 5)) || err_exit 'var.z !=5'
+[[ "$var" == *x=foobar* ]] || err_exit '$var does not contain x=foobar'
+
+typeset -T A_t=(
+ typeset x=aha
+ typeset b=${_.x}
+)
+unset x
+A_t x
+expected=aha
+got=${x.b}
+[[ "$got" == "$expected" ]] || err_exit "type '_' reference failed -- expected '$expected', got '$got'"
+
+typeset -T Tst_t=(
+ function f
+ {
+ A_t a
+ print ${ _.g ${a.x}; }
+ }
+ function g
+ {
+ print foo
+ }
+)
+Tst_t tst
+expected=foo
+got=${ tst.f;}
+[[ "$got" == "$expected" ]] || err_exit "_.g where g is a function in type discipline method failed -- expected '$expected', got '$got'"
+
+typeset -T B_t=(
+ integer -a arr
+ function f
+ {
+ (( _.arr[0] = 0 ))
+ (( _.arr[1] = 1 ))
+ print ${_.arr[*]}
+ }
+)
+unset x
+B_t x
+expected='0 1'
+got=${ x.f;}
+[[ "$got" == "$expected" ]] || err_exit "array assignment of subscripts in type discipline arithmetic failed -- expected '$expected', got '$got'"
+
+typeset -T Fileinfo_t=(
+ size=-1
+ typeset -a text=()
+ integer mtime=-1
+)
+Fileinfo_t -A _Dbg_filenames
+Fileinfo_t finfo
+function bar
+{
+ finfo.text=(line1 line2 line3)
+ finfo.size=${#finfo.text[@]}
+ _Dbg_filenames[foo]=finfo
+}
+bar
+
+expected='Fileinfo_t -A _Dbg_filenames=([foo]=(size=3;typeset -a text=(line1 line2 line3);typeset -l -i mtime=-1))'
+got=$(typeset -p _Dbg_filenames)
+[[ "$got" == "$expected" ]] || {
+ got=$(printf %q "$got")
+ err_exit "copy to associative array of types in function failed -- expected '$expected', got $got"
+}
+
+$SHELL > /dev/null <<- '+++++' || err_exit 'passing _ as nameref arg not working'
+ function f1
+ {
+ typeset -n v=$1
+ print -r -- "$v"
+ }
+ typeset -T A_t=(
+ typeset blah=xxx
+ function f { f1 _ ;}
+ )
+ A_t a
+ [[ ${ a.f ./t1;} == "$a" ]]
++++++
+expected='A_t b.a=(name=one)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name=aha
+ )
+ typeset -T B_t=(
+ typeset arr
+ A_t a
+ f()
+ {
+ _.a=(name=one)
+ typeset -p _.a
+ }
+ )
+ B_t b
+ b.f
++++
+) == "$expected" ]] 2> /dev/null || err_exit '_.a=(name=one) not expanding correctly'
+expected='A_t x=(name=xxx)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name
+ )
+ A_t x=(name="xxx")
+ typeset -p x
++++
+) == "$expected" ]] || err_exit 'empty field in definition does not expand correctly'
+
+typeset -T Foo_t=(
+ integer x=3
+ integer y=4
+ len() { print -r -- $(( sqrt(_.x**2 + _.y**2))) ;}
+)
+Foo_t foo
+[[ ${foo.len} == 5 ]] || err_exit "discipline function len not working"
+
+typeset -T benchmark_t=(
+ integer num_iterations
+)
+function do_benchmarks
+{
+ nameref tst=b
+ integer num_iterations
+ (( num_iterations= int(tst.num_iterations * 1.0) ))
+ printf "%d\n" num_iterations
+}
+benchmark_t b=(num_iterations=5)
+[[ $(do_benchmarks) == 5 ]] || err_exit 'scoping of nameref of type variables in arithmetic expressions not working'
+
+function cat_content
+{
+ cat <<- EOF
+ (
+ foo_t -a foolist=(
+ ( val=3 )
+ ( val=4 )
+ ( val=5 )
+ )
+ )
+ EOF
+ return 0
+}
+typeset -T foo_t=(
+ integer val=-1
+ function print
+ {
+ print -- ${_.val}
+ }
+)
+function do_something
+{
+ nameref li=$1 # "li" may be an index or associative array
+ li[2].print
+}
+cat_content | read -C x
+[[ $(do_something x.foolist) == 5 ]] || err_exit 'subscripts not honored for arrays of type with disciplines'
+
+typeset -T benchcmd_t=(
+ float x=1
+ float y=2
+)
+unset x
+compound x=(
+ float o
+ benchcmd_t -a m
+ integer h
+)
+expected=$'(\n\ttypeset -l -i h=0\n\tbenchcmd_t -a m\n\ttypeset -l -E o=0\n)'
+[[ $x == "$expected" ]] || err_exit 'compound variable with array of types with no elements not working'
+
+expected=$'Std_file_t db.file[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)'
+{
+ got=$($SHELL <<- \EOF
+ MAGIC='stdinstall (at&t research) 2009-08-25'
+ typeset -T Std_file_t=(
+ typeset action
+ typeset -A sum
+ )
+ typeset -T Std_t=(
+ typeset magic=$MAGIC
+ Std_file_t -A file
+ )
+ Std_t db=(magic='stdinstall (at&t research) 2009-08-25';Std_file_t -A file=( [/./home/gsf/.env.sh]=(action=preserve;typeset -A sum=([9b67ab407d01a52b3e73e3945b9a3ee0]=1);)[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)[/home/gsf/.profile]=(action=preserve;typeset -A sum=([3ce23137335219672bf2865d003a098e]=1);));)
+ typeset -p db.file[/etc/profile]
+ EOF)
+} 2> /dev/null
+[[ $got == "$expected" ]] || err_exit 'types with arrays of types as members fails'
+
+typeset -T x_t=(
+ integer dummy
+ function set
+ {
+ [[ ${.sh.name} == v ]] || err_exit "name=${.sh.name} should be v"
+ [[ ${.sh.subscript} == 4 ]] || err_exit "subscript=${.sh.subscript} should be 4"
+ [[ ${.sh.value} == hello ]] || err_exit "value=${.sh.value} should be hello"
+ }
+)
+x_t -a v
+v[4]="hello"
+
+typeset -T oset=(
+ typeset -A s
+)
+oset foo bar
+: ${foo.s[a]:=foobar}
+: ${bar.s[d]:=foobar}
+[[ ${bar.s[a]} == foobar ]] && err_exit '${var:=val} for types assigns to type instead of type instance'
+
+typeset -T olist=(
+ typeset -a l
+)
+olist foo
+foo.l[1]=x
+[[ ${!foo.l[*]} == *0* ]] && '0-th elment of foo.l should not be set'
+
+typeset -T oset2=( typeset -A foo )
+oset2 bar
+: ${bar.foo[a]}
+bar.foo[a]=b
+[[ ${#bar.foo[*]} == 1 ]] || err_exit "bar.foo should have 1 element not ${#bar.foo[*]}"
+[[ ${bar.foo[*]} == b ]] || err_exit "bar.foo[*] should be 'b' not ${bar.foo[*]}"
+[[ ${bar.foo[a]} == b ]] || err_exit "bar.foo[a] should be 'b' not ${bar.foo[*]}"
+
+{ x=$( $SHELL 2> /dev/null << \++EOF++
+ typeset -T ab_t=(
+ integer a=1 b=2
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function ar_n
+ {
+ nameref sn=$2
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( )
+ ar_n $1 s[5]
+ }
+ x=$(ar false ; ar false ; ar true ; printf ";")
+ y=$(ar false ; ar false ; ar true ; printf ";")
+ print -r -- "\"$x\"" == "\"$y\""
+++EOF++
+) ;} 2> /dev/null
+[[ $x == *a=4*b=5* ]] || err_exit 'static types in a function not working'
+{ eval "[[ $x ]]";} 2> /dev/null || err_exit 'arrays of types leaving side effects in subshells'
+
+typeset -T y_t=(
+ typeset dummy
+ function print_b
+ {
+ print "B"
+ }
+)
+y_t a b=(
+ function print_b
+ {
+ print "1"
+ }
+)
+[[ $(a.print_b) == B ]] || err_exit 'default discipline not working'
+[[ $(b.print_b) == 1 ]] || err_exit 'discipline override not working'
+
+$SHELL 2> /dev/null -c 'true || { typeset -T Type_t=(typeset name=foo);
+ Type_t z=(name=bar) ;}' || err_exit 'unable to parse type command until typeset -T executes'
+
+cd "$tmp"
+FPATH=$PWD
+PATH=$PWD:$PATH
+cat > A_t <<- \EOF
+ typeset -T A_t=(
+ B_t b
+ )
+EOF
+cat > B_t <<- \EOF
+ typeset -T B_t=(
+ integer n=5
+ )
+EOF
+
+unset n
+if n=$(FPATH=$PWD PATH=$PWD:$PATH $SHELL 2> /dev/null -c 'A_t a; print ${a.b.n}')
+then (( n==5 )) || err_exit 'dynamic loading of types gives wrong result'
+else err_exit 'unable to load types dynamically'
+fi
+
+# check that typeset -T reproduces a type.
+if $SHELL > /dev/null 2>&1 -c 'typeset -T'
+then $SHELL > junk1 <<- \+++EOF
+ typeset -T foo_t=(
+ integer x=3 y=4
+ float z=1.2
+ len()
+ {
+ ((.sh.value=sqrt(_.x**2 + _.y**2) ))
+ }
+ function count
+ {
+ print z=$z
+ }
+ )
+ typeset -T
+ print 'typeset -T'
+ +++EOF
+ $SHELL -c '. ./junk1;print "typeset -T"' > junk2
+ diff junk[12] > /dev/null || err_exit 'typeset -T not idempotent'
+ $SHELL -c '. ./junk1;print "typeset +f"' > junk2
+ [[ -s junk2 ]] || err_exit 'non-discipline-method functions found'
+else
+ err_exit 'typeset -T not supported'
+fi
+
+[[ $($SHELL -c 'typeset -T x=( typeset -a h ) ; x j; print -v j.h') ]] && err_exit 'type with indexed array without elements inserts element 0'
+
+[[ $($SHELL -c 'typeset -T x=( integer -a s ) ; compound c ; x c.i ; c.i.s[4]=666 ; print -v c') == *'[0]'* ]] && err_exit 'type with indexed array with non-zero element inserts element 0'
+
+
+{ $SHELL -c '(sleep 3;kill $$)& typeset -T x=( typeset -a s );compound c;x c.i;c.i.s[7][5][3]=hello;x c.j=c.i;[[ ${c.i} == "${c.j}" ]]';} 2> /dev/null
+exitval=$?
+if [[ $(kill -l $exitval) == TERM ]]
+then err_exit 'clone of multi-dimensional array timed out'
+elif ((exitval))
+then err_exit "c.i and c.j are not the same multi-dimensional array"
+fi
+
+typeset -T foobar_t=(
+ float x=1 y=0
+ slen()
+ {
+ print -r -- $((sqrt(_.x**2 + _.y**2)))
+ }
+ typeset -fS slen
+ len()
+ {
+ print -r -- $((sqrt(_.x**2 + _.y**2)))
+ }
+)
+unset z
+foobar_t z=(x=3 y=4)
+(( z.len == 5 )) || err_exit 'z.len should be 5'
+(( z.slen == 1 )) || err_exit 'z.slen should be 1'
+(( .sh.type.foobar_t.slen == 1 )) || err_exit '.sh.type.foobar_t.slen should be 1'
+(( .sh.type.foobar_t.len == 1 )) || err_exit '.sh.type.foobar_t.len should be 1'
+
+typeset -T z_t=( typeset -a ce )
+z_t x1
+x1.ce[3][4]=45
+compound c
+z_t -a c.x2
+c.x2[9]=x1
+got=$(typeset +p "c.x2[9].ce")
+exp='typeset -a c.x2[9].ce'
+[[ $got == "$exp" ]] || err_exit "typeset +p 'c.x2[9].ce' failed -- expected '$exp', got '$got'"
+
+unset b
+typeset -T a_t=(
+ typeset a="hello"
+)
+typeset -T b_t=(
+ a_t b
+)
+compound b
+compound -a b.ca
+b_t b.ca[4].b
+exp='typeset -C b=(typeset -C -a ca=( [4]=(b_t b=(a_t b=(a=hello))));)'
+got=$(typeset -p b)
+[[ $got == "$exp" ]] || err_exit 'typeset -p of nested type not correct'
+
+typeset -T u_t=(
+ integer dummy
+ unset()
+ {
+ print unset
+ }
+)
+unset z
+u_t -a x | read z
+[[ $z == unset ]] && err_exit 'unset discipline called on type creation'
+
+{ z=$($SHELL 2> /dev/null 'typeset -T foo; typeset -T') ;} 2> /dev/null
+[[ $z == 'typeset -T foo' ]] || err_exit '"typeset -T foo; typeset -T" failed'
+
+{ z=$($SHELL 2> /dev/null 'typeset -T foo=bar; typeset -T') ;} 2> /dev/null
+[[ $z ]] && err_exit '"typeset -T foo=bar" should not creates type foo'
+
+{
+$SHELL << \EOF
+ typeset -T board_t=(
+ compound -a board_y
+ function binsert
+ {
+ nameref figure=$1
+ integer y=$2 x=$3
+ typeset -m "_.board_y[y].board_x[x].field=figure"
+ }
+ )
+ function main
+ {
+ compound c=(
+ board_t b
+ )
+ for ((i=0 ; i < 2 ; i++ )) ; do
+ compound p=( hello=world )
+ c.b.binsert p 1 $i
+ done
+ exp='typeset -C c=(board_t b=(typeset -a board_y=( [1]=(typeset -a board_x=( [0]=(field=(hello=world;))[1]=(field=(hello=world)));));))'
+ [[ $(typeset -p c) == "$exp" ]] || exit 1
+ }
+ main
+EOF
+} 2> /dev/null
+if (( exitval=$?))
+then if [[ $(kill -l $exitval) == SEGV ]]
+ then err_exit 'typeset -m in type discipline causes exception'
+ else err_exit 'typeset -m in type discipline gives wrong value'
+ fi
+fi
+
+typeset -T pawn_t=(
+ print_debug()
+ {
+ print 'PAWN'
+ }
+)
+function main
+{
+ compound c=(
+ compound -a board
+ )
+
+ for ((i=2 ; i < 8 ; i++ )) ; do
+ pawn_t c.board[1][$i]
+ done
+
+}
+main 2> /dev/null && err_exit 'type assignment to compound array instance should generate an error'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh
new file mode 100755
index 0000000..be7c308
--- /dev/null
+++ b/src/cmd/ksh93/tests/variables.sh
@@ -0,0 +1,665 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+[[ ${.sh.version} == "$KSH_VERSION" ]] || err_exit '.sh.version != KSH_VERSION'
+unset ss
+[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset'
+[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset'
+[[ ${#ss} == 0 ]] || err_exit '${#ss} should be 0 when ss is unset'
+# RANDOM
+if (( RANDOM==RANDOM || $RANDOM==$RANDOM ))
+then err_exit RANDOM variable not working
+fi
+# SECONDS
+sleep 3
+if (( SECONDS < 2 ))
+then err_exit SECONDS variable not working
+fi
+# _
+set abc def
+if [[ $_ != def ]]
+then err_exit _ variable not working
+fi
+# ERRNO
+#set abc def
+#rm -f foobar#
+#ERRNO=
+#2> /dev/null < foobar#
+#if (( ERRNO == 0 ))
+#then err_exit ERRNO variable not working
+#fi
+# PWD
+if [[ ! $PWD -ef . ]]
+then err_exit PWD variable failed, not equivalent to .
+fi
+# PPID
+exp=$$
+got=${ $SHELL -c 'print $PPID'; }
+if [[ ${ $SHELL -c 'print $PPID'; } != $$ ]]
+then err_exit "PPID variable failed -- expected '$exp', got '$got'"
+fi
+# OLDPWD
+old=$PWD
+cd /
+if [[ $OLDPWD != $old ]]
+then err_exit "OLDPWD variable failed -- expected '$old', got '$OLDPWD'"
+fi
+cd $old || err_exit cd failed
+# REPLY
+read <<-!
+ foobar
+ !
+if [[ $REPLY != foobar ]]
+then err_exit REPLY variable not working
+fi
+integer save=$LINENO
+# LINENO
+LINENO=10
+#
+# These lines intentionally left blank
+#
+if (( LINENO != 13))
+then err_exit LINENO variable not working
+fi
+LINENO=save+10
+IFS=:
+x=a::b::c
+if [[ $x != a::b::c ]]
+then err_exit "word splitting on constants"
+fi
+set -- $x
+if [[ $# != 5 ]]
+then err_exit ":: doesn't separate null arguments "
+fi
+set x
+if x$1=0 2> /dev/null
+then err_exit "x\$1=value treated as an assignment"
+fi
+# check for attributes across subshells
+typeset -i x=3
+y=1/0
+if ( typeset x=y ) 2> /dev/null
+then err_exit "attributes not passed to subshells"
+fi
+unset x
+function x.set
+{
+ nameref foo=${.sh.name}.save
+ foo=${.sh.value}
+ .sh.value=$0
+}
+x=bar
+if [[ $x != x.set ]]
+then err_exit 'x.set does not override assignment'
+fi
+x.get()
+{
+ nameref foo=${.sh.name}.save
+ .sh.value=$foo
+}
+
+if [[ $x != bar ]]
+then err_exit 'x.get does not work correctly'
+fi
+typeset +n foo
+unset foo
+foo=bar
+(
+ unset foo
+ set +u
+ if [[ $foo != '' ]]
+ then err_exit '$foo not null after unset in subsehll'
+ fi
+)
+if [[ $foo != bar ]]
+then err_exit 'unset foo in subshell produces side effect '
+fi
+unset foo
+if [[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]]
+then err_exit '${foo?hi there} with foo unset does not print hi there on 2'
+fi
+x=$0
+set foobar
+if [[ ${@:0} != "$x foobar" ]]
+then err_exit '${@:0} not expanding correctly'
+fi
+set --
+if [[ ${*:0:1} != "$0" ]]
+then err_exit '${@:0} not expanding correctly'
+fi
+ACCESS=0
+function COUNT.set
+{
+ (( ACCESS++ ))
+}
+COUNT=0
+(( COUNT++ ))
+if (( COUNT != 1 || ACCESS!=2 ))
+then err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS"
+fi
+LANG=C > /dev/null 2>&1
+if [[ $LANG != C ]]
+then err_exit "C locale not working"
+fi
+unset RANDOM
+unset -n foo
+foo=junk
+function foo.get
+{
+ .sh.value=stuff
+ unset -f foo.get
+}
+if [[ $foo != stuff ]]
+then err_exit "foo.get discipline not working"
+fi
+if [[ $foo != junk ]]
+then err_exit "foo.get discipline not working after unset"
+fi
+# special variables
+set -- 1 2 3 4 5 6 7 8 9 10
+sleep 1000 &
+if [[ $(print -r -- ${#10}) != 2 ]]
+then err_exit '${#10}, where ${10}=10 not working'
+fi
+for i in @ '*' ! '#' - '?' '$'
+do false
+ eval foo='$'$i bar='$'{$i}
+ if [[ ${foo} != "${bar}" ]]
+ then err_exit "\$$i not equal to \${$i}"
+ fi
+ command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error"
+ if [[ $i != [@*] && ${foo%?} != "$bar" ]]
+ then err_exit "\${$i%?} not correct"
+ fi
+ command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error"
+ if [[ $i != [@*] && ${foo#?} != "$bar" ]]
+ then err_exit "\${$i#?} not correct"
+ fi
+ command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta
+x error"
+ if [[ $i != @([@*]) && ${#foo} != "$bar" ]]
+ then err_exit "\${#$i} not correct"
+ fi
+done
+kill $!
+unset x
+CDPATH=/
+x=$(cd ${tmp#/})
+if [[ $x != $tmp ]]
+then err_exit 'CDPATH does not display new directory'
+fi
+CDPATH=/:
+x=$(cd ${tmp%/*}; cd ${tmp##*/})
+if [[ $x ]]
+then err_exit 'CDPATH displays new directory when not used'
+fi
+x=$(cd ${tmp#/})
+if [[ $x != $tmp ]]
+then err_exit "CDPATH ${tmp#/} does not display new directory"
+fi
+TMOUT=100
+(TMOUT=20)
+if (( TMOUT !=100 ))
+then err_exit 'setting TMOUT in subshell affects parent'
+fi
+unset y
+function setdisc # var
+{
+ eval function $1.get'
+ {
+ .sh.value=good
+ }
+ '
+}
+y=bad
+setdisc y
+if [[ $y != good ]]
+then err_exit 'setdisc function not working'
+fi
+integer x=$LINENO
+: $'\
+'
+if (( LINENO != x+3 ))
+then err_exit '\<newline> gets linenumber count wrong'
+fi
+set --
+set -- "${@-}"
+if (( $# !=1 ))
+then err_exit '"${@-}" not expanding to null string'
+fi
+for i in : % + / 3b '**' '***' '@@' '{' '[' '}' !! '*a' '$foo'
+do (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error"
+done
+unset IFS
+( IFS=' ' ; read -r a b c <<-!
+ x y z
+ !
+ if [[ $b ]]
+ then err_exit 'IFS=" " not causing adjacent space to be null string'
+ fi
+)
+read -r a b c <<-!
+x y z
+!
+if [[ $b != y ]]
+then err_exit 'IFS not restored after subshell'
+fi
+
+# The next part generates 3428 IFS set/read tests.
+
+unset IFS x
+function split
+{
+ i=$1 s=$2 r=$3
+ IFS=': '
+ set -- $i
+ IFS=' '
+ g="[$#]"
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ g="$g($1)"
+ shift
+ done
+ case "$g" in
+ "$s") ;;
+ *) err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;;
+ esac
+ print "$i" | IFS=": " read arg rem; g="($arg)($rem)"
+ case "$g" in
+ "$r") ;;
+ *) err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;;
+ esac
+}
+for str in \
+ '-' \
+ 'a' \
+ '- -' \
+ '- a' \
+ 'a -' \
+ 'a b' \
+ '- - -' \
+ '- - a' \
+ '- a -' \
+ '- a b' \
+ 'a - -' \
+ 'a - b' \
+ 'a b -' \
+ 'a b c'
+do
+ IFS=' '
+ set x $str
+ shift
+ case $# in
+ 0) continue ;;
+ esac
+ f1=$1
+ case $f1 in
+ '-') f1='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f1$d1 in
+ '') split "$d0$f1$d1" "[0]" "()()" ;;
+ ' ') ;;
+ *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;;
+ esac
+ done
+ done
+ continue
+ ;;
+ esac
+ f2=$1
+ case $f2 in
+ '-') f2='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in ' ' ':' ' :' ': ' ' : '
+ do
+ case ' ' in
+ $f1$d1|$d1$f2) continue ;;
+ esac
+ for d2 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f2$d2 in
+ '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;;
+ ' ') ;;
+ *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;;
+ esac
+ done
+ done
+ done
+ continue
+ ;;
+ esac
+ f3=$1
+ case $f3 in
+ '-') f3='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in ':' ' :' ': ' ' : '
+ do
+ case ' ' in
+ $f1$d1|$d1$f2) continue ;;
+ esac
+ for d2 in ' ' ':' ' :' ': ' ' : '
+ do
+ case $f2$d2 in
+ ' ') continue ;;
+ esac
+ case ' ' in
+ $f2$d2|$d2$f3) continue ;;
+ esac
+ for d3 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f3$d3 in
+ '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;;
+ ' ') ;;
+ *) x=$f2$d2$f3$d3
+ x=${x#' '}
+ x=${x%' '}
+ split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)"
+ ;;
+ esac
+ done
+ done
+ done
+ done
+ continue
+ ;;
+ esac
+done
+unset IFS
+
+if [[ $( (print ${12345:?}) 2>&1) != *12345* ]]
+then err_exit 'incorrect error message with ${12345?}'
+fi
+unset foobar
+if [[ $( (print ${foobar:?}) 2>&1) != *foobar* ]]
+then err_exit 'incorrect error message with ${foobar?}'
+fi
+unset bar
+if [[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]]
+then err_exit 'incorrect error message with ${foobar?}'
+fi
+{ $SHELL -c '
+function foo
+{
+ typeset SECONDS=0
+ sleep 1.5
+ print $SECONDS
+
+}
+x=$(foo)
+(( x >1 && x < 2 ))
+'
+} 2> /dev/null || err_exit 'SECONDS not working in function'
+cat > $tmp/script <<-\!
+ posixfun()
+ {
+ unset x
+ nameref x=$1
+ print -r -- "$x"
+ }
+ function fun
+ {
+ nameref x=$1
+ print -r -- "$x"
+ }
+ if [[ $1 ]]
+ then file=${.sh.file}
+ else print -r -- "${.sh.file}"
+ fi
+!
+chmod +x $tmp/script
+. $tmp/script 1
+[[ $file == $tmp/script ]] || err_exit ".sh.file not working for dot scripts"
+[[ $($SHELL $tmp/script) == $tmp/script ]] || err_exit ".sh.file not working for scripts"
+[[ $(posixfun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for posix functions"
+[[ $(fun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for functions"
+[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions"
+[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions"
+[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions"
+[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions"
+(
+ [[ $(posixfun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for posix functions in subshells"
+ [[ $(fun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for functions in subshells"
+ (( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell"
+)
+TIMEFORMAT='this is a test'
+[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working'
+: ${.sh.version}
+[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name'
+: ${.sh.version}
+[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name'
+: ${.sh.version}
+[[ $(cd /bin;env | grep PWD=) == *.sh.* ]] && err_exit '.sh. prefixed to PWD'
+# unset discipline bug fix
+dave=dave
+function dave.unset
+{
+ unset dave
+}
+unset dave
+[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed'
+
+print 'print ${VAR}' > $tmp/script
+unset VAR
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "previously unset environment variable not passed to script, expected 'new', got '$got'"
+[[ ! $VAR ]] || err_exit "previously unset environment variable set after script, expected '', got '$VAR'"
+unset VAR
+VAR=old
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "environment variable covering local variable not passed to script, expected 'new', got '$got'"
+[[ $VAR == old ]] || err_exit "previously set local variable changed after script, expected 'old', got '$VAR'"
+unset VAR
+export VAR=old
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "environment variable covering environment variable not passed to script, expected 'new', got '$got'"
+[[ $VAR == old ]] || err_exit "previously set environment variable changed after script, expected 'old', got '$VAR'"
+
+(
+ unset dave
+ function dave.append
+ {
+ .sh.value+=$dave
+ dave=
+ }
+ dave=foo; dave+=bar
+ [[ $dave == barfoo ]] || exit 2
+) 2> /dev/null
+case $? in
+0) ;;
+1) err_exit 'append discipline not implemented';;
+*) err_exit 'append discipline not working';;
+esac
+.sh.foobar=hello
+{
+ function .sh.foobar.get
+ {
+ .sh.value=world
+ }
+} 2> /dev/null || err_exit "cannot add get discipline to .sh.foobar"
+[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working'
+x='a|b'
+IFS='|'
+set -- $x
+[[ $2 == b ]] || err_exit '$2 should be b after set'
+exec 3>&2 2> /dev/null
+set -x
+( IFS= ) 2> /dev/null
+set +x
+exec 2>&3-
+set -- $x
+[[ $2 == b ]] || err_exit '$2 should be b after subshell'
+: & pid=$!
+( : & )
+[[ $pid == $! ]] || err_exit '$! value not preserved across subshells'
+unset foo
+typeset -A foo
+function foo.set
+{
+ case ${.sh.subscript} in
+ bar) if ((.sh.value > 1 ))
+ then .sh.value=5
+ foo[barrier_hit]=yes
+ fi
+ ;;
+ barrier_hit)
+ if [[ ${.sh.value} == yes ]]
+ then foo[barrier_not_hit]=no
+ else foo[barrier_not_hit]=yes
+ fi
+ ;;
+ esac
+}
+foo[barrier_hit]=no
+foo[bar]=1
+(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1'
+[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no'
+[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes'
+foo[barrier_hit]=no
+foo[bar]=2
+(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5'
+[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes'
+[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no'
+unset x
+typeset -i x
+function x.set
+{
+ typeset sub=${.sh.subscript}
+ (( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value ))
+}
+x[0]=0 x[1]=1 x[2]=2 x[3]=3
+[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly'
+float seconds
+((SECONDS=3*4))
+seconds=SECONDS
+(( seconds < 12 || seconds > 12.1 )) && err_exit "SECONDS is $seconds and should be close to 12"
+unset a
+function a.set
+{
+ print -r -- "${.sh.name}=${.sh.value}"
+}
+[[ $(a=1) == a=1 ]] || err_exit 'set discipline not working in subshell assignment'
+[[ $(a=1 :) == a=1 ]] || err_exit 'set discipline not working in subshell command'
+
+[[ ${.sh.subshell} == 0 ]] || err_exit '${.sh.subshell} should be 0'
+(
+ [[ ${.sh.subshell} == 1 ]] || err_exit '${.sh.subshell} should be 1'
+ (
+ [[ ${.sh.subshell} == 2 ]] || err_exit '${.sh.subshell} should be 2'
+ )
+)
+
+set -- {1..32768}
+(( $# == 32768 )) || err_exit "\$# failed -- expected 32768, got $#"
+set --
+
+unset r v x
+path=$PATH
+x=foo
+for v in EDITOR VISUAL OPTIND CDPATH FPATH PATH ENV LINENO RANDOM SECONDS _
+do nameref r=$v
+ unset $v
+ if ( $SHELL -c "unset $v; : \$$v" ) 2>/dev/null
+ then [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
+ r=$x
+ [[ $r == $x ]] || err_exit "$v=$x failed -- expected '$x', got '$r'"
+ else err_exit "unset $v; : \$$v failed"
+ fi
+done
+
+x=x
+for v in LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC
+do nameref r=$v
+ unset $v
+ [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
+ d=$($SHELL -c "$v=$x" 2>&1)
+ [[ $d ]] || err_exit "$v=$x failed -- expected locale diagnostic"
+ { g=$( r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == '' ]] || err_exit "$v=$x failed -- expected '', got '$g'"
+ { g=$( r=C; r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == 'C' ]] || err_exit "$v=C; $v=$x failed -- expected 'C', got '$g'"
+done
+PATH=$path
+
+cd $tmp
+
+print print -n zzz > zzz
+chmod +x zzz
+exp='aaazzz'
+got=$($SHELL -c 'unset SHLVL; print -n aaa; ./zzz' 2>&1) >/dev/null 2>&1
+[[ $got == "$exp" ]] || err_exit "unset SHLVL causes script failure -- expected '$exp', got '$got'"
+
+mkdir glean
+for cmd in date ok
+do exp="$cmd ok"
+ rm -f $cmd
+ print print $exp > glean/$cmd
+ chmod +x glean/$cmd
+ got=$(CDPATH=:.. $SHELL -c "PATH=:/bin:/usr/bin; date > /dev/null; cd glean && ./$cmd" 2>&1)
+ [[ $got == "$exp" ]] || err_exit "cd with CDPATH after PATH change failed -- expected '$exp', got '$got'"
+done
+
+v=LC_CTYPE
+unset $v
+[[ -v $v ]] && err_exit "unset $v; [[ -v $v ]] failed"
+eval $v=C
+[[ -v $v ]] || err_exit "$v=C; [[ -v $v ]] failed"
+
+cmd='set --nounset; unset foo; : ${!foo*}'
+$SHELL -c "$cmd" 2>/dev/null || err_exit "'$cmd' exit status $?, expected 0"
+
+SHLVL=1
+level=$($SHELL -c $'$SHELL -c \'print -r "$SHLVL"\'')
+[[ $level == 3 ]] || err_exit "SHLVL should be 3 not $level"
+
+[[ $($SHELL -c '{ x=1; : ${x.};print ok;}' 2> /dev/null) == ok ]] || err_exit '${x.} where x is a simple variable causes shell to abort'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/vartree1.sh b/src/cmd/ksh93/tests/vartree1.sh
new file mode 100755
index 0000000..d558dc6
--- /dev/null
+++ b/src/cmd/ksh93/tests/vartree1.sh
@@ -0,0 +1,215 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# variable tree test #001
+# Propose of this test is whether ksh93 handles global variable trees
+# and function-local variable trees the same way, including "nameref"
+# and "unset" handling.
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+function build_tree
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ #dest_tree.l1["$a"].l2["$b"].l3["$c"].entries+=( "$index" )
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+function add_tree_leaf
+{
+ nameref tree_leafnode="$1"
+ nameref data_node=srcdata.hashnodes["$2"]
+ typeset add_mode="$3"
+
+ case "${add_mode}" in
+ "leaf_name")
+ tree_leafnode="${data_node.name}"
+ return 0
+ ;;
+ "leaf_compound")
+ tree_leafnode=(
+ typeset name="${data_node.name}"
+ typeset -a filenames=( "${data_node.filenames[@]}" )
+ typeset -a comments=( "${data_node.comments[@]}" )
+ typeset -a xlfd=( "${data_node.xlfd[@]}" )
+ )
+ return 0
+ ;;
+ *)
+ print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}"
+ return 1
+ ;;
+ esac
+
+ # not reached
+ return 1
+}
+
+# "mysrcdata_local" and "mysrcdata_global" must be identical
+typeset mysrcdata_global=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+)
+
+mytree_global=()
+
+function main
+{
+ # "mysrcdata_local" and "mysrcdata_global" must be identical
+ typeset mysrcdata_local=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+ )
+
+ # build tree using global tree variables
+ build_tree mytree_global mysrcdata_global leaf_compound || \
+ err_exit 'build_tree mytree_global mysrcdata_global leaf_compound returned an error'
+
+ (( $(print -r -- "${mytree_global}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global' too small"
+
+ # build tree using local tree variables
+ mytree_local=()
+ build_tree mytree_local mysrcdata_local leaf_compound || \
+ err_exit 'build_tree mytree_local mysrcdata_local leaf_compound returned an error'
+
+ (( $(print -r -- "${mytree_local}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local' too small"
+
+ # Compare trees
+ if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical"
+ fi
+
+ unset 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ [[ "${mytree_global}" != "${mytree_local}" ]] || err_exit "mytree_global and mytree_local should differ"
+
+ unset 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ # Compare trees (after "unset")
+ if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical after unset"
+ fi
+}
+
+main
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/vartree2.sh b/src/cmd/ksh93/tests/vartree2.sh
new file mode 100755
index 0000000..e3e4cff
--- /dev/null
+++ b/src/cmd/ksh93/tests/vartree2.sh
@@ -0,0 +1,335 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# variable tree test #002
+# Propose of this test is whether ksh93 handles global variable trees
+# and function-local variable trees the same way, including "nameref"
+# and "unset" handling.
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+# "built_tree1" and "built_tree2" are identical except the way how they test
+# whether a variable exists:
+# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
+# as non-zero length content
+# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+function build_tree1
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+# "built_tree1" and "built_tree2" are identical except the way how they test
+# whether a variable exists:
+# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
+# as non-zero length content
+# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+function build_tree2
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ #if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ #if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+
+function add_tree_leaf
+{
+ nameref tree_leafnode="$1"
+ nameref data_node=srcdata.hashnodes["$2"]
+ typeset add_mode="$3"
+
+ case "${add_mode}" in
+ "leaf_name")
+ tree_leafnode="${data_node.name}"
+ return 0
+ ;;
+ "leaf_compound")
+ tree_leafnode=(
+ typeset name="${data_node.name}"
+ typeset -a filenames=( "${data_node.filenames[@]}" )
+ typeset -a comments=( "${data_node.comments[@]}" )
+ typeset -a xlfd=( "${data_node.xlfd[@]}" )
+ )
+ return 0
+ ;;
+ *)
+ print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}"
+ return 1
+ ;;
+ esac
+
+ # not reached
+ return 1
+}
+
+# "mysrcdata_local" and "mysrcdata_global" must be identical
+typeset mysrcdata_global=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+)
+
+mytree_global1=()
+mytree_global2=()
+
+function main
+{
+ # "mysrcdata_local" and "mysrcdata_global" must be identical
+ typeset mysrcdata_local=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+ )
+
+ #### Build tree using global tree variables
+ build_tree1 mytree_global1 mysrcdata_global leaf_compound || \
+ err_exit 'build_tree1 mytree_global1 mysrcdata_global leaf_compound returned an error'
+ (( $(print -r -- "${mytree_global1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global1' too small"
+
+ build_tree2 mytree_global2 mysrcdata_global leaf_compound || \
+ err_exit 'build_tree2 mytree_global2 mysrcdata_global leaf_compound returned an error'
+ (( $(print -r -- "${mytree_global2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global2' too small"
+
+
+ #### build tree using local tree variables
+ mytree_local1=()
+ mytree_local2=()
+
+ build_tree1 mytree_local1 mysrcdata_local leaf_compound || \
+ err_exit 'build_tree1 mytree_local1 mysrcdata_local leaf_compound returned an error'
+ (( $(print -r -- "${mytree_local1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local1' too small"
+
+ build_tree2 mytree_local2 mysrcdata_local leaf_compound || \
+ err_exit 'build_tree2 mytree_local2 mysrcdata_local leaf_compound returned an error'
+ (( $(print -r -- "${mytree_local2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local2' too small"
+
+
+ #### Compare treess
+ if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
+ err_exit "compound trees 'mytree_global1' and 'mytree_local1' not identical"
+ fi
+
+ if [[ "${mytree_global1}" != "${mytree_global2}" ]] ; then
+ err_exit "compound trees 'mytree_global1' and 'mytree_global2' not identical"
+ fi
+
+ if [[ "${mytree_local1}" != "${mytree_local2}" ]] ; then
+ err_exit "compound trees 'mytree_local1' and 'mytree_local2' not identical"
+ fi
+
+
+ #### test "unset" in a subshell
+ ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ err_exit "try 1: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
+ ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ err_exit "try 2: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
+
+ # remove parent node (array element) and then check whether the child is gone, too:
+ (
+ unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]'
+ [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'} ]]
+ ) && err_exit "global: parent node removed (array element), child still exists"
+ (
+ unset 'mytree_local1.l1[urw].l2[itc zapfdingbats]'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array element), child still exists"
+
+ # remove parent node (array variable) and then check whether the child is gone, too:
+ (
+ unset 'mytree_local1.l1[urw].l2'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "global: parent node removed (array variable), child still exists"
+ (
+ unset 'mytree_local1.l1[urw].l2'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array variable), child still exists"
+
+
+ #### test "unset" and compare trees
+ unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ [[ "${mytree_global1}" != "${mytree_local1}" ]] || err_exit "mytree_global1 and mytree_local1 should differ"
+
+ unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ # Compare trees (after "unset")
+ if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
+ err_exit "compound trees 'mytree_local1' and 'mytree_global1' not identical after unset"
+ fi
+}
+
+main
+
+exit $((Errors<125?Errors:125))